# ikas Code Components Project

You are building **Preact + TypeScript components for an e-commerce storefront**.
This project uses the ikas Code Components framework with an MCP server for API documentation.

**ALWAYS query MCP tools before writing code that uses storefront APIs.**
Never guess function signatures or type shapes — the MCP server is the source of truth.

## CRITICAL: Auto-Generated Files

**NEVER manually create or edit `ikas.config.json`, `types.ts`, `global-types.ts`, or `src/components/index.ts`** — they are all auto-generated by CLI commands.
Use `npx ikas-component config add-component --props '[...]'` or `npx ikas-component config add-prop` to manage components and props.
These commands update `ikas.config.json`, `types.ts`, `global-types.ts`, AND `src/components/index.ts` (including the component export) automatically.

**The CLI does NOT edit your component source.** `remove-prop` and `remove-enum` update `ikas.config.json` and the generated `types.ts` / `global-types.ts` only — `index.tsx`, sub-components, and `styles.css` are untouched. After removing a prop or enum, grep the source for the old identifier and clean up dead references yourself before building.

## MCP Tools (12 tools)

### Starting a New Section
| Tool | Purpose |
|------|---------|
| `get_section_template(sectionType)` | **Start here** — production-ready starter template (index.tsx + types.ts + styles.css + config) for common sections: header, footer, product-detail, product-list, cart, login, register, hero-banner, blog-post, faq, etc. |
| `get_framework_guide(topic)` | Framework docs — "ai-workflow", "common-pitfalls", "prop-types", "css-scoping", "form-handling", "imports", "sections-vs-components" |
| `get_code_example(task)` | Code examples — "add to cart", "variant selection", "image-handling", "product-detail-section", "cart-section" |

### Looking Up APIs
| Tool | Purpose |
|------|---------|
| `search_docs(query)` | Search across all storefront API docs and framework guides |
| `get_function_doc(name)` | Full docs for a specific function (e.g. "addItemToCart", "Router.navigate") |
| `list_functions(category?)` | List functions by category: ProductDetail, Cart, ProductList, Navigation, Customer, Order, Image, Blog, Brand, Category, Pricing, Form, Validation, Pagination, Filtering |
| `get_prop_types()` | All available ikas.config.json prop types with TS types and examples |

### Exploring Types
| Tool | Purpose |
|------|---------|
| `get_model_guide(model)` | **One-stop-shop** — type definition + all utility functions + examples + related types for a model (e.g. "IkasProduct", "IkasOrder") |
| `get_type_definition(name)` | Full definition of a type or enum (e.g. "IkasProduct", "IkasOrderStatus") |
| `get_functions_for_type(typeName)` | All utility functions for a type (e.g. "IkasImage") |
| `search_types(query)` | Search types/enums by keyword (e.g. "price", "address", "status") |
| `list_types(domain?, kind?)` | List all types, optionally filtered by domain ("product", "cart", "order") or kind ("type", "enum") |

## CLI Commands

**Never edit ikas.config.json or types.ts manually** — use the CLI commands:

| Command | Purpose |
|---------|---------|
| `npx ikas-component config add-component --name "Name" --type section --props '[...]'` | **Primary** — create component with all props in one command |
| `npx ikas-component config add-component --name "Name" --type section` | Create component with no props (add later) |
| `npx ikas-component config add-prop --component "Name" --name title --displayName "Title" --type TEXT --required [--group content]` | Add a single prop incrementally |
| `npx ikas-component config update-prop --component "Name" --prop title --type RICH_TEXT [--group colors]` | Update a prop's type or group |
| `npx ikas-component config remove-prop --component "Name" --prop title` | Remove a prop |
| `npx ikas-component config remove-component --name "Name"` | Remove a component |
| `npx ikas-component config add-prop-group --component "Name" --id colors --name "Colors" [--description "..."] [--parent style]` | Create a prop group |
| `npx ikas-component config update-prop-group --component "Name" --id colors [--name "..."] [--description "..."]` | Update a prop group |
| `npx ikas-component config remove-prop-group --component "Name" --id colors` | Remove a prop group |
| `npx ikas-component config list` | List all components and their props |
| `npx ikas-component config add-enum --name "Size" --options '[{"name":"Small","value":"s"}]'` | Create a custom ENUM type (returns `enumTypeId`) |
| `npx ikas-component config update-enum --id <enumId> --name "..." [--options '[...]']` | Update enum name/options |
| `npx ikas-component config remove-enum --id <enumId>` | Remove enum (fails if any prop still references it) |
| `npx ikas-component config list-enums` | List all custom enums |
| `npx ikas-component check --json` | Type-check all components, output errors as JSON |
| `npx ikas-component build` | Compile server.js + client.js + styles.css per component |
| `npx ikas-component dev` | Start dev server (Vite 5200 + WebSocket 5201) |

## Workflow: Building a New Section

1. `get_section_template("product-detail-section")` → get starter files + CLI command with --props
2. For any custom ENUM props the section needs: `config add-enum` **first** (capture the returned `enumTypeId`), then reference it in `add-prop --type ENUM --enumTypeId <id>`. Order matters — an ENUM prop without a pre-existing `enumTypeId` is rejected.
3. Run the CLI command (creates component + props + types.ts in one step)
4. Write `index.tsx` and `styles.css` using the template (do NOT edit `types.ts` or `global-types.ts` — both are regenerated on every prop/enum mutation)
5. Look up APIs → `get_model_guide("IkasProduct")`, `get_function_doc("addItemToCart")`
6. `npx ikas-component check --json` → fix type errors
7. `npx ikas-component build` → verify clean build

### Custom ENUM lifecycle

- **Create:** `add-enum` → `add-prop --type ENUM --enumTypeId <id>`. The enum must exist before the prop is created.
- **Rename options:** `update-enum --id <id> --options '[...]'`. `types.ts` regenerates automatically.
- **Remove:** remove (or repoint) every prop that references the enum **first**, then `remove-enum`. `remove-enum` blocks with an error while any prop still references the id.
- `global-types.ts` is regenerated unconditionally on `add-enum` / `update-enum` / `remove-enum` / `remove-prop` — never hand-edit it.
- Template snippets from `get_section_template` use `{{ENUM_ID:<EnumName>}}` placeholders (e.g. `{{ENUM_ID:AspectRatio}}`). Create the matching `add-enum` first, then substitute the returned id.

## Sub-Component Structure

**ALWAYS create sub-components in `src/sub-components/` with their own folder containing `index.tsx` and `styles.css`. NEVER create flat .tsx files inside a component folder.**

```
src/
├── components/
│   ├── ProductList/
│   │   ├── index.tsx         # imports from ../../sub-components/...
│   │   ├── types.ts          # auto-generated (CLI-managed)
│   │   └── styles.css
│   └── index.ts
├── sub-components/
│   ├── ProductCard/
│   │   ├── index.tsx          # sub-component with inline Props
│   │   └── styles.css
│   └── FilterSidebar/
│       ├── index.tsx
│       └── styles.css
├── global.css                 # unscoped global styles
└── global-types.ts            # auto-generated shared enum types
```

**Key rules:**
- `src/components/` = registered in ikas.config.json. `src/sub-components/` = internal helpers (NOT in ikas.config.json)
- Sub-components do NOT have `types.ts` — define `Props` inline in `index.tsx`
- Custom enum types are exported from `src/global-types.ts` (auto-generated). Sub-components can import them: `import type { MyEnum } from "../../global-types";`
- TSX: use `import ProductCard from "../../sub-components/ProductCard";`
- Sub-components should be wrapped with `observer()` from `@ikas/component-utils`
- Sub-components can be shared across multiple parent sections

```tsx
// src/sub-components/ProductCard/index.tsx — inline Props, no types.ts
import { IkasProduct, getSelectedProductVariant } from "@ikas/bp-storefront";

interface Props { product: IkasProduct; }

export default function ProductCard({ product }: Props) { ... }
```

## Key Patterns

### Component Exports & Reactivity
```tsx
// Root components are automatically reactive — the ikas runtime wraps them in autorun().
// Do NOT import or use observer() on root exports.
import { Props } from "./types";

export function MySection({ product }: Props) { ... }
export default MySection;
```

```tsx
// Only use observer() on extracted SUB-COMPONENTS
import { observer } from "@ikas/component-utils";

const CartBadge = observer(function CartBadge() {
  const count = cartStore.order?.orderLineItems?.length ?? 0;
  return <span>{count}</span>;
});
```

### Null Safety
```tsx
// Storefront models can be null — always check before accessing
if (!product) return null;
const price = product.selectedVariant?.price?.formattedPrice ?? "";
```

### Mutations
```tsx
// Functions like addItemToCart() mutate the model in-place (MobX observable)
// No need to capture return value — root components re-render automatically via autorun()
await addItemToCart({ product });
```

### COMPONENT & COMPONENT_LIST Props
These props let you create **slot-based** architectures where store owners can drag child components into your section/component from the editor.

- `COMPONENT` — a single child component slot (TS type: `any`)
- `COMPONENT_LIST` — a list of child components (TS type: `any`)

**Rendering:** Use the `<IkasComponentRenderer>` wrapper to render child components:
```tsx
import { IkasComponentRenderer } from "@ikas/bp-storefront";
import { Props } from "./types";

export function MySection({ title, cardList, ...props }: Props) {
  return (
    <section>
      <h2>{title}</h2>
      <div className="cards">
        {/* COMPONENT_LIST — render a list of child components */}
        <IkasComponentRenderer
          id="card-list"
          components={cardList as any[]}
          parentProps={props}
        />
      </div>
    </section>
  );
}
export default MySection;
```

**Key rules:**
- Always pass `parentProps={props}` so child components can access parent data via dynamic values
- Cast the prop value: `components={myList as any[]}` for COMPONENT_LIST, `components={[myComp] as any[]}` for COMPONENT
- `<IkasComponentRenderer>` handles rendering, styling, and reactivity of child components automatically

**Config example:**
```json
{
  "name": "cardList",
  "displayName": "Card List",
  "type": "COMPONENT_LIST"
}
```

### CSS Scoping
All CSS is auto-scoped with `.cc_{componentId}` prefix. Write plain class names — they are scoped at build time.

### Preact Event Handling
Use `onInput` instead of `onChange` for text inputs (Preact behavior).

### Import Source
```tsx
import { addItemToCart, IkasProduct, IkasImage } from "@ikas/bp-storefront";
```

## No Static Text Rule

**CRITICAL: Never hardcode user-visible text in JSX.** All text strings (headings, button labels,
empty states, loading messages, form labels) MUST be TEXT props with defaultValues.

Wrong: `<h1>Sign In</h1>`
Correct: `<h1>{title}</h1>` with `title` as TEXT prop (defaultValue: "Sign In")

For button loading states, use two separate props:
- `submitButtonText` (default: "Sign In")
- `submittingButtonText` (default: "Signing in...")

Group text props under a "Texts" propGroup or another specific text group name.

**Assistive strings (`aria-label`, `aria-describedby`, `alt`, sr-only text):** if the string is meaningful to end users (e.g. icon-only button label, product image alt), make it a TEXT prop. English literal defaults are acceptable for purely structural labels a merchant would never want to change (e.g. `role="dialog" aria-modal="true"`). When in doubt, make it a prop.

## Sections vs Components

- **Sections** = page-level, full-width containers (Header, Hero, Product Grid, Footer).
  Set `"type": "section"` via CLI. Use `<section>` root element. Props interface: `Props`.
  **Sections MUST always include a `backgroundColor` COLOR prop** (default: `#ffffff`).
  Apply via inline style: `style={backgroundColor ? { backgroundColor } : undefined}`
  Consider also adding `textColor` COLOR props for text elements directly on the section background.
- **Components** = child elements placed inside sections (buttons, cards, badges).
  Defaults to `"component"`. Use `<div>` root element. Props interface: `Props`.

## Prop Groups

Organize props into collapsible groups in the editor sidebar. Use prop groups when a component has props that are related to each other.

### Config Format
- Define groups in `propGroups` array on the component in `ikas.config.json`
- Assign props to groups via `groupId` on each prop
- Groups can nest 1 level deep via `children`
- Props without `groupId` appear ungrouped at root level
- Group IDs must be unique within a component

### CLI Commands
- `config add-prop-group --component "Name" --id content --name "Content"` — create group
- `config add-prop-group --component "Name" --id colors --name "Colors" --parent style` — create nested group
- `config add-prop --component "Name" --name title --displayName "Title" --type TEXT --group content` — add prop to group
- `config update-prop --component "Name" --prop title --group colors` — move prop to different group
- `config remove-prop-group --component "Name" --id content` — remove group (props become ungrouped)

### When to Use
- props that are related to each other → group related props
- Sections with content + style props → separate "Content" and "Appearance" groups
- Complex sections → use nested groups (e.g., "Style" → "Colors", "Typography")

## Workflow Addition

When building a section with props that are related to each other, organize into prop groups after defining props:
```bash
npx ikas-component config add-prop-group --component "Name" --id content --name "Content"
npx ikas-component config update-prop --component "Name" --prop title --group content
```

## Build Verification

IMPORTANT: After completing any task, always run `npx ikas-component build` (or `npm run build`) to check for
TypeScript and build errors. Fix any errors before considering the task done.
