# Coralite Framework

## CRITICAL DIRECTIVES
When generating code or answering questions about Coralite, you MUST adhere to the following rules:
1. **NO VANILLA BOILERPLATE:** Do not write standard `customElements.define()` or `class extends HTMLElement` blocks for components. You MUST always use Coralite's `defineComponent` exported from `coralite`.
2. **AST SPLICING AWARENESS:** If a component is written declaratively in HTML (e.g., `<my-component>`), the server **preserves** the host tag to act as the Web Component container. It injects the component's template contents as children (Light DOM) and attaches deterministic tracking attributes (e.g., `data-cid="my-component-0"`) to the host tag itself.
3. **ZERO-CONFIG DEPENDENCIES:** Coralite uses AST static analysis. To import JavaScript on the client, use standard dynamic imports (`await import('pkg')`) inside the `script` block.
4. To mount a Web Component imperatively, use `document.createElement('my-component')` using a string literal containing a hyphen, which the bundler automatically detects.
---

## 1. The Serialization Boundary
**CRITICAL RULE:** You cannot use top-level imports or variables (declared outside `defineComponent`) directly inside the `script` block. The `script` block is serialized and sent to the browser. To bridge server-side data to the client, you must use the `data` block.

## 2. File Structure: Pages vs. Components
* **Pages**: Pages are standard `.html` files (e.g., `index.html`) that serve as route entry points. They act as the **consumers** of components by declaring custom element tags within their HTML body (e.g., `<my-navbar></my-navbar>`).
* **Components**: A Coralite component is strictly an `.html` file. It is not a `.js` or `.jsx` file. A component file consists of up to three top-level root tags:
  1. `<template id="component-name">` (**Required**): Defines the declarative HTML structure.
  2. `<style>` (**Optional**): Defines component-specific styles.
  3. `<script type="module">` (**Optional**): Defines the reactive logic using `defineComponent`.
* **The Relationship**: When a Page consumes a component tag, the server-side build process discovers the component, **preserves the custom element host tag**, and splices the component's inner `<template>` HTML into it. It then processes the `<style>`, and bundles the serialized `<script>` into the client-side JavaScript chunk.

## 3. System Architecture
* **Rendering**: Strictly Server-Side Rendered (SSR) with deterministic ID generation (`my-component-0`). No heavy client-side AST rendering.
* **Architecture**: Coralite utilizes a hybrid model where components are either fully declarative (SSR-only) or true imperative Web Components. Imperative components lazily loaded via JavaScript use native HTML template stamping (`this.innerHTML = templateHTML`) with Light DOM projection, entirely eliminating the need for client-side HTML parsers.
* **API Paradigm**: Coralite uses a "Flat Options" API. All logic is defined within four strictly isolated blocks: `attributes`, `data`, `getters`, and `script`.
* **State Equation**: `Attributes + Data + Getters = State`. The template only sees this unified reactive proxy.
* **Scope Isolation**: Component state (like variables defined in the script or internal `ref` IDs) is strictly isolated. It does **not** cascade down to child components. Only explicitly passed HTML attributes and globally injected plugin states cascade.

## 4. Static Components
Static components are purely HTML-based elements without scripting logic.
* **Definition**: Must be wrapped in a `<template id="component-name">` tag.
* **Usage**: The custom element tag name in the HTML page must exactly match the template's `id` (e.g., `<component-name></component-name>`).
* **Data Binding**: Data is passed via HTML attributes and rendered inside the template using double curly braces: `{{ attributeName }}`.

## 5. Dynamic Components (defineComponent)
Dynamic components are authored by appending a `<script type="module">` below the `<template>`, exporting the core `defineComponent` helper.

### 5.1 Anti-Patterns
When generating code for Coralite components, **DO NOT** use standard Web Component boilerplate.

**❌ BAD (Vanilla Web Component):**
```javascript
class MyComponent extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
  }
  connectedCallback() { ... }
}
customElements.define('my-component', MyComponent);
```

**✅ GOOD (Coralite defineComponent):**

```javascript
import { defineComponent } from 'coralite'
export default defineComponent({
  script: ({ state, signal, refs }) => { ... }
})
```

### 5.2 Component Structure: Isolated Blocks

A component definition consists of four primary blocks:

#### 1. `attributes` (Sync)

* **Purpose**: Coerces HTML attributes into JavaScript primitives.
* **Rule**: Strictly limited to primitives (`String`, `Number`, `Boolean`). `Object` and `Array` types are strictly blocked to avoid JSON-in-HTML parsing errors.
* **Reactivity**: Changes to HTML attributes (via `setAttribute`) automatically trigger updates to the unified `state`.

#### 2. `data({ state, page, ...context })` (Async/Server)

* **Purpose**: Fetches initial state on the server during the build process.
* **Arguments** (The Context Object):
* `state`: Contains the component's resolved attributes (e.g., `state.category`). **Always use this to read HTML attribute values passed to the component.**
* `page`: Contains global metadata about the consuming page/route (e.g., URL, file info). **Do NOT use this to look up component attributes.**


* **Serialization**: This block is fully stripped from the client bundle by the build tool. The returned object is serialized and merged into the unified client-side `state`.

#### 3. `getters` (Sync)

* **Purpose**: Pure functions for derived state (isomorphic).
* **Rule**: These receive a **Read-Only Proxy** of the state. They must never mutate state and cannot be `async`.
* **Reactivity**: Automatically re-evaluated when any underlying state dependency changes.

#### 4. `script({ state, signal, refs, ...pluginContext })` (Client)

* **Purpose**: The client-side controller for the component.
* **Arguments** (Injected via Client Context):
* `state`: A **Read/Write Mutable Proxy**. Mutations here automatically trigger getter evaluations and precise DOM updates.
* `signal`: An `AbortSignal` mapped to the component's lifecycle. Used for native cleanup (e.g., aborting fetch requests, removing global listeners) when disconnected.
* `refs`: A dictionary of dynamically generated, globally unique IDs (e.g., `my-comp-0__btn`) for elements marked with the `ref` attribute (provided by the Core `refs` plugin).
* `...pluginContext`: **Extensible Boundary.** Any active Coralite plugin that augments the `client.context` will inject its attributes directly into this destructured argument object.


* **Usage**: All DOM events, imperative mutations, third-party library initializations, and side-effects live here.

### 5.3 The "Smart State, Dumb Template" Paradigm

HTML templates in Coralite are strictly declarative and "dumb". They do not support JavaScript logic or dot-notation. The template can *only* render flat keys from the unified `state`.

### 5.4 Native Web APIs

* **Communication**: Use standard `CustomEvent` for component-to-component communication.
* **Cleanup**: Always use the provided `AbortSignal` (`signal`) to clean up event listeners and abort pending network requests when the component unmounts.

### 5.5 Slots Projection & Transformation (`slots`)

You define transformations in the `slots` object. Each key is a slot name (use `'default'` for unnamed slots).

* **Signature**: `(slotNodes, state) => HTMLString | NodeArray | void`
* **Scope**: Slotted content is evaluated within the parent component's local scope.
* **Preservation**: Coralite maps original Light DOM elements automatically, projecting them synchronously upon connected callbacks for dynamic imperative components.

### 5.6 CSS Scoping (PostCSS)

Coralite components are strictly scoped by default, despite rendering in the global Light DOM. The compiler injects a unique instance identifier and PostCSS nests all CSS rules securely beneath that attribute selector.

---

## 6. Framework Extensibility (definePlugin)

Plugins use a strictly isomorphic API boundary, divided clearly into `server` (Node.js/Build) and `client` (Browser/Runtime) objects.

### 6.1 The Plugin API Schema

The `definePlugin` function enforces the following schema:

```javascript
import { definePlugin } from 'coralite'

export default definePlugin({
  name: 'my-plugin', // Required. Acts as the virtual module import specifier.
  
  // SERVER: Strictly Node.js / Build-Time Execution
  server: {
    exports: { ... }, // Two-Phase Curried functions for component data() blocks
    components: [ ... ], // Array of paths to plugin-provided .html components
    onPageSet: (ctx) => { ... }, // And other global SSR hooks...
    onBeforeComponentRender: ({ state, componentId, instanceId, refs, textNodes, attributes, element, session }) => { ... },
    onAfterComponentRender: ({ result, state, ...context }) => { ... }
  },

  // CLIENT: Strictly Browser / Run-Time Execution
  client: {
    context: { ... }, // Client-side context injections (Two-Phase Currying)
    onBeforeComponentRender: ({ state, instanceId, element, options }) => { ... },
    onAfterComponentRender: (element) => { ... }
  }
})
```

### 6.2 The `server.exports` System (Server-Side Virtual Modules)

The `server.exports` property defines methods available to components **during the server-side build process**.

* **Top-Level Imports**: Plugins are imported at the top level of the component's `<script>` block using the plugin's `name` as the module specifier.
* **Server-Only Execution**: Because these modules are virtual, imported functions **MUST** only be invoked within the `data()` block. The build tool strips these imports before sending the script to the client.
* **Two-Phase Currying**: Functions receive the `CoralitePluginContext` in Phase 1, and return the function the component developer uses in Phase 2.

### 6.3 Isomorphic Component Lifecycle Hooks

Plugins can intercept specific components during AST generation (Server) and DOM hydration (Client):

* `onBeforeComponentRender`: Runs before tokens are replaced/proxied. Perfect for injecting variables into the local `state`.
* **Server Payload**: AST Pointers (`refs`, `textNodes`, `attributes`).
* **Client Payload**: Mutable State, Physical Element Reference.

* `onAfterComponentRender`: Runs after the component is rendered.
* **Server Payload**: The completed AST array (`result`).
* **Client Payload**: Executes after the browser's microtask queue flushes the DOM.

### 6.4 Client Context Injection (Two-Phase Currying)

Client injections mapped in `client.context` use a curried setup:

* **Phase 1 (Global Setup)**: `(globalContext) => ...` Runs exactly once when the plugin registers. Use this for shared plugin state.
* **Phase 2 (Local Instance)**: `(instanceContext) => ...` Runs when a component mounts. Returns the actual utility injected into the script context.

## 7. Built-In Plugins

* **Metadata Plugin**: Extracts SEO data during the build phase.
* **Refs Plugin**: Generates clean deterministic IDs (e.g., `my-comp-0__btn`) natively bridging the SSR/Client gap. Provides a `refs('name')` dictionary function directly within the `script` context.
* **Static Asset Plugin**: Copies static assets to the build output folder.
* **Testing Plugin**: Automates E2E testing preparation by duplicating all `ref` attributes to `data-testid` deterministically on both server and client.

## 8. E2E Testing

* **Readiness**: Await `window.__coralite_ready__` after navigation.
* **Selectors**: Rely on `data-testid` generated by the **Testing Plugin** (e.g., `[data-testid="my-component-0__submit-btn"]`) for robust selectors.