# Coralite Framework - Project Guidelines

## CRITICAL DIRECTIVES
1. **NO VANILLA BOILERPLATE:** Do not write standard `customElements.define()` or `class extends HTMLElement`. Always use Coralite's `defineComponent` exported from `coralite`.
2. **COMPONENT NAMING:** Component names MUST contain at least one hyphen (e.g., `<my-component>`) to ensure Custom Element spec compliance and trigger lazy loading.
3. **AST SPLICING AWARENESS:** The server preserves the host tag and injects template contents as Light DOM with deterministic `data-cid` attributes.
4. **CSS SCOPING:** CSS scoping is achieved in the Light DOM using an AST compiler to inject unique identifiers and nest rules via PostCSS. Shadow DOM is NOT used.
5. **ZERO-CONFIG DEPENDENCIES:** Use standard dynamic imports (`await import('pkg')`) inside the `script` block for client-side JS.
6. **IMPERATIVE MOUNTING:** To mount a component imperatively, use `document.createElement('my-component')`. You must pass data via `setAttribute` to sync with component state. Do not directly assign properties or use a `data()` block for purely imperative components.

## 1. File Structure: Pages vs. Components
* **Pages**: Standard `.html` files in `src/pages` that consume components.
* **Components**: `.html` files in `src/components` consisting of `<template>`, `<style>`, and `<script type="module">`.

## 2. Dynamic Components (defineComponent)
Always export `defineComponent` from your component's script. Follow the "Flat Options" API strictly.

```javascript
import { defineComponent } from 'coralite'
export default defineComponent({
  // Attributes STRICTLY prohibit Object/Array types. Primitives only (String, Number, Boolean).
  // Standard HTML5 boolean attributes are handled specifically; bare attributes like `disabled` coerce to true.
  attributes: { /* e.g., name: String, active: Boolean */ },

  // Server-side logic. Executes during SSR. Used for data fetching and complex objects.
  async data({ state, page }) { return {}; },
  
  // Derived state. Getters are read-only proxies that strictly block mutations.
  // Can be async/Promises; the framework handles resolution without race conditions.
  getters: { /* Derived state logic */ },
  
  // Client-side logic.
  script({ state, root, instanceId, signal, refs }) { /* Client-side interactions */ }
})
```

## 3. The "Smart State, Dumb Template" Paradigm
Templates are strictly declarative. No JavaScript logic or dot-notation is allowed in the HTML markup. Only render flat keys from the unified `state` (e.g., `{{ myKey }}`). Reactive logic must be strictly isolated in JavaScript `getters`.

## 4. Slots
The `slots` function can be provided to `defineComponent` to customize slot rendering:
* **Signature**: `(slotNodes, state) => HTMLString | NodeArray | void`
* Unnamed slots map to 'default'. The original nodes and internal state are preserved.

## 5. Non-Hydrated Components (`no-hydration`)
When the `no-hydration` boolean attribute is present on a component:
* The host element is stripped (unwrapped) from the final HTML during SSR.
* Its rendered children are promoted to the parent's level in the DOM.
* Any nested custom elements within a `no-hydration` subtree are recursively stripped and excluded from client-side hydration.
* Server-side `data()` and `getters` still execute during SSR to facilitate rendering, but no client-side instance is created.

## 6. Native Web APIs & Lifecycle
* **Communication**: Use standard `CustomEvent`.
* **Cleanup**: Always use the provided `AbortSignal` (`signal`) for event listeners and fetch requests. The `onDisconnected` hook fires synchronously when the element is removed, and event listeners attached with `signal` are automatically aborted.
* **Refs**: The standard context provides `refs`, an Array of `{name: string, element: Node}` containing DOM nodes mapped by `ref` attributes.

## 7. Plugins (definePlugin)
Plugins are critical for extending the framework and enforce a strict isomorphic boundary:
* **Structure**: Must use `definePlugin` with a `name`, `server: {}` (for Node.js/Build logic), and `client: {}` (for Browser/esbuild logic).
* **Server Block**: All SSR lifecycle hooks, plugin `exports`, and `components` arrays must reside within the `server` block.
* **Two-Phase Currying**: The API uses currying for extensibility. `server.exports` uses `(session) => (instanceContext) =>` and `client.context` uses `(globalContext) => (instanceContext) =>`.
* **Terminology**: `renderContext` is deprecated; always use `session` across the plugin API.
