# ikas Code Components

You are building **Preact + TypeScript components for an e-commerce storefront**.
**ALWAYS query MCP tools before writing code that uses storefront APIs.**

## CRITICAL: Auto-Generated Files

**NEVER manually create or edit `ikas.config.json`, `types.ts` or `global-types.ts`** — they are auto-generated by CLI commands.
Use `npx ikas-component config add-component --props '[...]'` or `npx ikas-component config add-prop` to manage props.
These commands update `ikas.config.json`, `types.ts`, and `global-types.ts` 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
- get_section_template(sectionType) — **Start here** — production-ready starter template for common sections (header, footer, product-detail, product-list, cart, login, hero-banner, blog-post, faq, etc.)
- get_framework_guide(topic) — Framework docs ("ai-workflow", "common-pitfalls", "prop-types", "css-scoping", "form-handling", "imports")
- get_code_example(task) — Code examples ("add to cart", "variant selection", "image-handling")

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

### Exploring Types
- get_model_guide(model) — **One-stop-shop** — type def + utility functions + examples for a model (e.g. "IkasProduct", "IkasOrder")
- get_type_definition(name) — Full definition of a type or enum
- get_functions_for_type(typeName) — All utility functions for a type
- search_types(query) — Search types/enums by keyword ("price", "address", "status")
- list_types(domain?, kind?) — List all types, filter by domain or kind ("type"/"enum")

## CLI Commands (never edit ikas.config.json or types.ts manually)
- npx ikas-component config add-component --name "Name" --type section --props '[...]' — **Primary** — create with all props in one command
- npx ikas-component config add-component --name "Name" --type section — Create component with no props
- npx ikas-component config add-prop --component "Name" --name title --displayName "Title" --type TEXT --required [--group content] — Add a prop incrementally
- npx ikas-component config update-prop --component "Name" --prop title --type RICH_TEXT [--group colors] — Update a prop 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" [--parent style] — Create a prop group
- npx ikas-component config update-prop-group --component "Name" --id colors [--name "..."] — 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
- 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>` (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`.**
- `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: `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
- NEVER create flat .tsx files inside a component folder

## Key Patterns
- Root components are automatically reactive (ikas runtime uses autorun). Do NOT use observer() on root exports.
  Pattern: `export function MySection({ title }: Props) { ... }` + `export default MySection;`
  Only use observer() on sub-components.
- Null safety: storefront models can be null — always check before accessing
- Mutations: addItemToCart() etc. mutate MobX observables in-place — no return capture needed
- COMPONENT & COMPONENT_LIST props: slot-based child components rendered via `<IkasComponentRenderer>`
  `import { IkasComponentRenderer } from "@ikas/bp-storefront"`
  `<IkasComponentRenderer components={myList as any[]} parentProps={props} />`
  Always pass `parentProps={props}` so children can access parent data. Cast with `as any[]`.
- CSS: write plain class names — auto-scoped with .cc_{componentId} at build time
- Events: use onInput (not onChange) for text inputs (Preact behavior)
- Imports: `import { addItemToCart, IkasProduct } 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 (e.g., `submitButtonText` + `submittingButtonText`).
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 where a merchant would never want to change them (e.g. `role="dialog" aria-modal="true"`). When in doubt, make it a prop.

## Sections vs Components
- Sections = page-level 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 inside sections (buttons, cards, badges)
  Defaults to "component". Use <div> root element. Props interface: Props.

## Prop Groups
Organize props that are related to each other into collapsible groups in editor sidebar.
- Define groups in `propGroups` on component in ikas.config.json
- Assign props via `groupId` on each prop
- Nest 1 level deep with `children`
- Group IDs must be unique within a component
- CLI: add-prop-group, update-prop-group, remove-prop-group
- Add prop to group: add-prop --group <groupId> or update-prop --group <groupId>

## 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.
