@ikas/code-components-mcp 0.34.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,23 +17,26 @@
17
17
  "ikas-config": {
18
18
  "title": "ikas.config.json Schema",
19
19
  "description": "Configuration file that defines components, their props, and metadata",
20
- "content": "The `ikas.config.json` file is the central configuration for your code components project.\n\n```json\n{\n \"name\": \"my-project\",\n \"version\": \"1.0.0\",\n \"components\": [\n {\n \"id\": \"my-component\",\n \"name\": \"My Component\",\n \"entry\": \"./src/components/MyComponent/index.tsx\",\n \"styles\": \"./src/components/MyComponent/styles.css\",\n \"props\": [\n {\n \"name\": \"title\",\n \"displayName\": \"Title\",\n \"type\": \"TEXT\",\n \"required\": true,\n \"defaultValue\": \"Hello\",\n \"description\": \"The main heading text\"\n }\n ]\n },\n {\n \"id\": \"hero-banner\",\n \"name\": \"Hero Banner\",\n \"type\": \"section\",\n \"entry\": \"./src/components/HeroBanner/index.tsx\",\n \"styles\": \"./src/components/HeroBanner/styles.css\",\n \"props\": [\n {\n \"name\": \"heading\",\n \"displayName\": \"Heading\",\n \"type\": \"TEXT\",\n \"required\": true,\n \"defaultValue\": \"Welcome\"\n }\n ]\n }\n ]\n}\n```\n\n### Top-level fields:\n- `name` (string): Project name\n- `version` (string): Project version\n- `components` (array): List of component definitions\n\n### Component fields:\n- `id` (string): Unique identifier (kebab-case)\n- `name` (string): Display name in the editor\n- `type` (string, optional): `\"component\"` (default) or `\"section\"` — sections are page-level containers (e.g. header, hero banner, footer), components are child elements placed inside sections (e.g. button, card, badge)\n- `entry` (string): Path to the component's entry file (index.tsx)\n- `styles` (string): Path to the component's CSS file\n- `props` (array): List of prop definitions\n\n### Prop fields:\n- `name` (string): Prop name used in code (camelCase)\n- `displayName` (string): Label shown in the editor UI\n- `type` (string): One of the available prop types\n- `required` (boolean): Whether the prop must be set\n- `defaultValue` (any): Default value matching the prop type\n- `description` (string): Help text shown in editor\n- `options` (array, SELECT only): Array of `{ label, value }` for SELECT type",
20
+ "content": "The `ikas.config.json` file is the central configuration for your code components project.\n\n```json\n{\n \"name\": \"my-project\",\n \"version\": \"1.0.0\",\n \"components\": [\n {\n \"id\": \"my-component\",\n \"name\": \"My Component\",\n \"entry\": \"./src/components/MyComponent/index.tsx\",\n \"styles\": \"./src/components/MyComponent/styles.css\",\n \"props\": [\n {\n \"name\": \"title\",\n \"displayName\": \"Title\",\n \"type\": \"TEXT\",\n \"required\": true,\n \"defaultValue\": \"Hello\",\n \"description\": \"The main heading text\"\n }\n ]\n },\n {\n \"id\": \"hero-banner\",\n \"name\": \"Hero Banner\",\n \"type\": \"section\",\n \"entry\": \"./src/components/HeroBanner/index.tsx\",\n \"styles\": \"./src/components/HeroBanner/styles.css\",\n \"props\": [\n {\n \"name\": \"heading\",\n \"displayName\": \"Heading\",\n \"type\": \"TEXT\",\n \"required\": true,\n \"defaultValue\": \"Welcome\"\n }\n ]\n }\n ]\n}\n```\n\n### Top-level fields:\n- `name` (string): Project name\n- `version` (string): Project version\n- `components` (array): List of component definitions\n\n### Component fields:\n- `id` (string): Unique identifier (kebab-case)\n- `name` (string): Display name in the editor\n- `type` (string, optional): `\"component\"` (default) or `\"section\"` — sections are page-level containers (e.g. header, hero banner, footer), components are child elements placed inside sections (e.g. button, card, badge)\n- `entry` (string): Path to the component's entry file (index.tsx)\n- `styles` (string): Path to the component's CSS file\n- `props` (array): List of prop definitions\n\n### Prop fields:\n- `name` (string): Prop name used in code (camelCase)\n- `displayName` (string): Label shown in the editor UI\n- `type` (string): One of the available prop types\n- `required` (boolean): Whether the prop must be set\n- `defaultValue` (any): Default value matching the prop type\n- `description` (string): Help text shown in editor\n- `options` (array, SELECT only): Array of `{ label, value }` for SELECT type\n- `groupId` (string, optional): Assign this prop to a prop group (references a group's `id`)\n\n### Prop Groups (optional):\nAdd `propGroups` array on a component to organize props into collapsible groups in the editor.\n- `id` (string): Unique group identifier within the component\n- `name` (string): Display name in editor\n- `description` (string, optional): Group description\n- `children` (array, optional): Nested groups (max 1 level)\n\nSee `get_framework_guide(\"prop-groups\")` for full details and examples.",
21
21
  "tags": [
22
22
  "config",
23
23
  "configuration",
24
24
  "ikas.config",
25
25
  "props",
26
26
  "schema",
27
- "components"
27
+ "components",
28
+ "propGroups",
29
+ "groupId"
28
30
  ]
29
31
  },
30
32
  "prop-types": {
31
33
  "title": "Available Prop Types",
32
34
  "description": "All prop types that can be used in ikas.config.json",
33
- "content": "Props define what the store editor can configure for each component. Each prop has a `type` that determines the editor UI and the TypeScript type received in your component.\n\n| Type | Editor UI | TypeScript Type | Description |\n|------|-----------|----------------|-------------|\n| `TEXT` | Text input | `string` | Single-line text |\n| `NUMBER` | Number input | `number` | Numeric value |\n| `BOOLEAN` | Toggle switch | `boolean` | True/false toggle |\n| `IMAGE` | Image picker | `IkasImage | null` | Image from editor. Use `getDefaultSrc(image)` for URL |\n| `LINK` | Link editor | `IkasNavigationLink` | Navigation link with href, label, subLinks |\n| `LIST_OF_LINK` | Link list editor | `IkasNavigationLinkList` | List of navigation links |\n| `COLOR` | Color picker | `string` | CSS color value (hex, rgb, etc.) |\n| `SELECT` | Dropdown | `string` | Single selection from options list |\n| `PRODUCT` | Product picker | `IkasProduct` | Single product reference |\n| `PRODUCT_LIST` | Product list picker | `IkasProduct[]` | Multiple product references |\n| `CATEGORY` | Category picker | `IkasCategory` | Single category reference |\n| `CATEGORY_LIST` | Category list picker | `IkasCategory[]` | Multiple category references |\n| `BRAND` | Brand picker | `IkasBrand` | Single brand reference |\n| `BRAND_LIST` | Brand list picker | `IkasBrand[]` | Multiple brand references |\n| `BLOG` | Blog post picker | `IkasBlog` | Single blog post reference |\n| `BLOG_LIST` | Blog post list picker | `IkasBlog[]` | Multiple blog post references |\n| `FONT_STYLE_TYPE` | Font style editor | `IkasFontStyle` | Font family, size, weight, etc. |\n\n### SELECT type example:\n```json\n{\n \"name\": \"layout\",\n \"displayName\": \"Layout\",\n \"type\": \"SELECT\",\n \"options\": [\n { \"label\": \"Grid\", \"value\": \"grid\" },\n { \"label\": \"List\", \"value\": \"list\" }\n ],\n \"defaultValue\": \"grid\"\n}\n```\n\n### IMAGE type example:\n```json\n{\n \"name\": \"heroImage\",\n \"displayName\": \"Hero Image\",\n \"type\": \"IMAGE\",\n \"required\": false\n}\n```\nAccess in component: `getDefaultSrc(props.heroImage)` (import `getDefaultSrc` from `@ikas/bp-storefront`)",
35
+ "content": "Props define what the store editor can configure for each component. Each prop has a `type` that determines the editor UI and the TypeScript type received in your component.\n\n| Type | Editor UI | TypeScript Type | Description |\n|------|-----------|----------------|-------------|\n| `TEXT` | Text input | `string` | Single-line text |\n| `NUMBER` | Number input | `number` | Numeric value |\n| `BOOLEAN` | Toggle switch | `boolean` | True/false toggle |\n| `IMAGE` | Image picker | `IkasImage | null` | Image from editor. Use `getDefaultSrc(image)` for URL |\n| `LINK` | Link editor | `IkasNavigationLink` | Navigation link with href, label, subLinks |\n| `LIST_OF_LINK` | Link list editor | `IkasNavigationLinkList` | List of navigation links |\n| `COLOR` | Color picker | `string` | CSS color value (hex, rgb, etc.) |\n| `SELECT` | Dropdown | `string` | Single selection from options list |\n| `PRODUCT` | Product picker | `IkasProduct` | Single product reference |\n| `PRODUCT_LIST` | Product list picker | `IkasProduct[]` | Multiple product references |\n| `CATEGORY` | Category picker | `IkasCategory` | Single category reference |\n| `CATEGORY_LIST` | Category list picker | `IkasCategory[]` | Multiple category references |\n| `BRAND` | Brand picker | `IkasBrand` | Single brand reference |\n| `BRAND_LIST` | Brand list picker | `IkasBrand[]` | Multiple brand references |\n| `BLOG` | Blog post picker | `IkasBlog` | Single blog post reference |\n| `BLOG_LIST` | Blog post list picker | `IkasBlog[]` | Multiple blog post references |\n| `FONT_STYLE_TYPE` | Font style editor | `IkasFontStyle` | Font family, size, weight, etc. |\n\n### SELECT type example:\n```json\n{\n \"name\": \"layout\",\n \"displayName\": \"Layout\",\n \"type\": \"SELECT\",\n \"options\": [\n { \"label\": \"Grid\", \"value\": \"grid\" },\n { \"label\": \"List\", \"value\": \"list\" }\n ],\n \"defaultValue\": \"grid\"\n}\n```\n\n### IMAGE type example:\n```json\n{\n \"name\": \"heroImage\",\n \"displayName\": \"Hero Image\",\n \"type\": \"IMAGE\",\n \"required\": false\n}\n```\nAccess in component: `getDefaultSrc(props.heroImage)` (import `getDefaultSrc` from `@ikas/bp-storefront`)\n\n### Prop grouping\nProps can be assigned to groups via `groupId` for organized editor sidebar display. See `get_framework_guide(\"prop-groups\")` for details.",
34
36
  "tags": [
35
37
  "props",
36
38
  "types",
39
+ "groupId",
37
40
  "TEXT",
38
41
  "NUMBER",
39
42
  "BOOLEAN",
@@ -52,7 +55,7 @@
52
55
  "component-structure": {
53
56
  "title": "Component Structure",
54
57
  "description": "How to write a Preact component for ikas",
55
- "content": "Each component consists of three files. There are two patterns: **components** (child elements) and **sections** (page-level containers).\n\n## Component Pattern (child elements like buttons, cards, badges)\n\n### index.tsx - Component Implementation\n```tsx\nimport { Props } from \"./types\";\n\nexport function MyComponent({ title, showButton }: Props) {\n return (\n <div className=\"my-component\">\n <h1>{title}</h1>\n {showButton && <button>Click me</button>}\n </div>\n );\n}\n\nexport default MyComponent;\n```\n\n### types.ts - Props Interface\n```typescript\nexport interface Props {\n title: string; // TEXT prop -> string\n showButton?: boolean; // optional BOOLEAN prop\n count: number; // NUMBER prop -> number\n}\n```\n\n### styles.css\n```css\n.my-component {\n padding: 16px;\n}\n\n.my-component h1 {\n font-size: 24px;\n}\n```\n\n## Section Pattern (page-level containers like headers, hero banners, footers)\n\nSections use a `<section>` root element, full-width styling, and a `Props` interface. In `ikas.config.json` they have `\"type\": \"section\"`.\n\n### index.tsx - Section Implementation\n```tsx\nimport { Props } from \"./types\";\n\nexport function HeroBanner({ heading, subtitle, backgroundColor }: Props) {\n return (\n <section className=\"hero-banner\" style={backgroundColor ? { backgroundColor } : undefined}>\n <div className=\"hero-banner-inner\">\n <h2>{heading}</h2>\n {subtitle && <p>{subtitle}</p>}\n </div>\n </section>\n );\n}\n\nexport default HeroBanner;\n```\n\n### types.ts - Section Props Interface\n```typescript\nexport interface Props {\n heading: string;\n subtitle?: string;\n backgroundColor?: string;\n}\n```\n\n### styles.css - Full-width section styles\n```css\n.hero-banner {\n width: 100%;\n padding: 64px 24px;\n}\n\n.hero-banner-inner {\n max-width: 1200px;\n margin: 0 auto;\n}\n```\n\n## Key Rules\n- Export the component as both a named export and a default export: `export function X() {...}` + `export default X;`\n- Use Preact (not React) - but JSX syntax is the same\n- Import types from `./types` for props\n- Use `className` not `class` for CSS classes\n- Storefront functions and types come from `@ikas/bp-storefront`\n- CSS classes are automatically scoped to your component at build time. Use plain CSS class selectors - they won't conflict with other components or the page.\n\n## Root Components Are Automatically Reactive\n\nThe ikas runtime wraps every root component render in a MobX `autorun()`, so **root exports are already reactive** — they automatically re-render when any MobX store they read (`cartStore`, `customerStore`, etc.) changes. You do **not** need `observer()` on root component exports.\n\n### Correct: Plain root export reading stores\n```tsx\nimport { cartStore } from \"@ikas/bp-storefront\";\nimport { Props } from \"./types\";\n\nexport function CartSummary({ title }: Props) {\n const itemCount = cartStore.cart?.orderLineItems.length ?? 0;\n return (\n <section className=\"cart-summary\">\n <h2>{title}</h2>\n <p>{itemCount} items in cart</p>\n </section>\n );\n}\n\nexport default CartSummary;\n```\n\n### Anti-pattern: Do NOT wrap root exports with observer\n```tsx\n// WRONG — observer() is redundant on root components\nconst CartSummary = observer(function CartSummary({ title }: Props) {\n ...\n});\nexport default CartSummary;\n```\n\n## Using observer for Sub-Components\n\nWhen you extract a **sub-component** that independently reads MobX stores, wrap it with `observer()` from `@ikas/component-utils` so it re-renders when store data changes.\n\n### When to use observer\n- A **sub-component** (not the root export) reads `cartStore.cart`, `customerStore.customer`, or any other MobX observable\n- You extract part of a component into a separate function that needs independent reactivity\n\n### When observer is NOT needed\n- **Root component exports** — the ikas runtime handles reactivity via `autorun()`\n- Components that only use props passed from parent — no store reads\n- Static components with no reactive data\n\n### Example: Root export with observer sub-component\n```tsx\nimport { observer } from \"@ikas/component-utils\";\nimport { cartStore } from \"@ikas/bp-storefront\";\nimport { Props } from \"./types\";\n\n// Sub-component: needs observer() for independent reactivity\nconst CartBadge = observer(function CartBadge() {\n const itemCount = cartStore.cart?.orderLineItems.length ?? 0;\n return <span className=\"cart-badge\">{itemCount}</span>;\n});\n\n// Root export: NO observer needed — autorun() handles reactivity\nexport function Header({ logo }: Props) {\n return (\n <header>\n <img src={logo} alt=\"Logo\" />\n <CartBadge />\n </header>\n );\n}\n\nexport default Header;\n```\n\n**Important:** When using `observer` on sub-components, define the component as a named function expression (not arrow function) and assign it to a `const`. This ensures proper display names in React DevTools.\n\n## Sub-Component File Organization\n\nWhen you extract sub-components, **ALWAYS** place them in `src/sub-components/` with their own folder containing `index.tsx` and `styles.css`. Never create flat `.tsx` files inside a component folder. See `get_framework_guide(\"sub-component-patterns\")` for the full pattern, directory structure, CSS @import rules, and examples.",
58
+ "content": "Each component consists of three files. There are two patterns: **components** (child elements) and **sections** (page-level containers).\n\n## Component Pattern (child elements like buttons, cards, badges)\n\n### index.tsx - Component Implementation\n```tsx\nimport { Props } from \"./types\";\n\nexport function MyComponent({ title, showButton }: Props) {\n return (\n <div className=\"my-component\">\n <h1>{title}</h1>\n {showButton && <button>Click me</button>}\n </div>\n );\n}\n\nexport default MyComponent;\n```\n\n### types.ts - Props Interface\n```typescript\nexport interface Props {\n title: string; // TEXT prop -> string\n showButton?: boolean; // optional BOOLEAN prop\n count: number; // NUMBER prop -> number\n}\n```\n\n### styles.css\n```css\n.my-component {\n padding: 16px;\n}\n\n.my-component h1 {\n font-size: 24px;\n}\n```\n\n## Section Pattern (page-level containers like headers, hero banners, footers)\n\nSections use a `<section>` root element, full-width styling, and a `Props` interface. In `ikas.config.json` they have `\"type\": \"section\"`. **Every section MUST include a `backgroundColor` COLOR prop** (default: `#ffffff`) so store owners can customize the section background. Consider also adding `textColor` COLOR props for text elements sitting directly on the section background, so they remain readable when the background changes.\n\n### index.tsx - Section Implementation\n```tsx\nimport { Props } from \"./types\";\n\nexport function HeroBanner({ heading, subtitle, backgroundColor }: Props) {\n return (\n <section className=\"hero-banner\" style={backgroundColor ? { backgroundColor } : undefined}>\n <div className=\"hero-banner-inner\">\n <h2>{heading}</h2>\n {subtitle && <p>{subtitle}</p>}\n </div>\n </section>\n );\n}\n\nexport default HeroBanner;\n```\n\n### types.ts - Section Props Interface\n```typescript\nexport interface Props {\n heading: string;\n subtitle?: string;\n backgroundColor?: string;\n}\n```\n\n### styles.css - Full-width section styles\n```css\n.hero-banner {\n width: 100%;\n padding: 64px 24px;\n}\n\n.hero-banner-inner {\n max-width: 1200px;\n margin: 0 auto;\n}\n```\n\n## Key Rules\n- Export the component as both a named export and a default export: `export function X() {...}` + `export default X;`\n- Use Preact (not React) - but JSX syntax is the same\n- Import types from `./types` for props\n- Use `className` not `class` for CSS classes\n- Storefront functions and types come from `@ikas/bp-storefront`\n- CSS classes are automatically scoped to your component at build time. Use plain CSS class selectors - they won't conflict with other components or the page.\n- **All user-visible text MUST be TEXT props** — never hardcode strings in JSX. This ensures all text is translatable. Use `defaultValue` in config for English defaults.\n- **Sections MUST include a `backgroundColor` COLOR prop** (default: `#ffffff`). Apply via `style={backgroundColor ? { backgroundColor } : undefined}` on the root `<section>` element. Optionally add `textColor` for text directly on the section background.\n\n## Root Components Are Automatically Reactive\n\nThe ikas runtime wraps every root component render in a MobX `autorun()`, so **root exports are already reactive** — they automatically re-render when any MobX store they read (`cartStore`, `customerStore`, etc.) changes. You do **not** need `observer()` on root component exports.\n\n### Correct: Plain root export reading stores\n```tsx\nimport { cartStore } from \"@ikas/bp-storefront\";\nimport { Props } from \"./types\";\n\nexport function CartSummary({ title }: Props) {\n const itemCount = cartStore.cart?.orderLineItems.length ?? 0;\n return (\n <section className=\"cart-summary\">\n <h2>{title}</h2>\n <p>{itemCount} items in cart</p>\n </section>\n );\n}\n\nexport default CartSummary;\n```\n\n### Anti-pattern: Do NOT wrap root exports with observer\n```tsx\n// WRONG — observer() is redundant on root components\nconst CartSummary = observer(function CartSummary({ title }: Props) {\n ...\n});\nexport default CartSummary;\n```\n\n## Using observer for Sub-Components\n\nWhen you extract a **sub-component** that independently reads MobX stores, wrap it with `observer()` from `@ikas/component-utils` so it re-renders when store data changes.\n\n### When to use observer\n- A **sub-component** (not the root export) reads `cartStore.cart`, `customerStore.customer`, or any other MobX observable\n- You extract part of a component into a separate function that needs independent reactivity\n\n### When observer is NOT needed\n- **Root component exports** — the ikas runtime handles reactivity via `autorun()`\n- Components that only use props passed from parent — no store reads\n- Static components with no reactive data\n\n### Example: Root export with observer sub-component\n```tsx\nimport { observer } from \"@ikas/component-utils\";\nimport { cartStore } from \"@ikas/bp-storefront\";\nimport { Props } from \"./types\";\n\n// Sub-component: needs observer() for independent reactivity\nconst CartBadge = observer(function CartBadge() {\n const itemCount = cartStore.cart?.orderLineItems.length ?? 0;\n return <span className=\"cart-badge\">{itemCount}</span>;\n});\n\n// Root export: NO observer needed — autorun() handles reactivity\nexport function Header({ logo }: Props) {\n return (\n <header>\n <img src={logo} alt=\"Logo\" />\n <CartBadge />\n </header>\n );\n}\n\nexport default Header;\n```\n\n**Important:** When using `observer` on sub-components, define the component as a named function expression (not arrow function) and assign it to a `const`. This ensures proper display names in React DevTools.\n\n## Sub-Component File Organization\n\nWhen you extract sub-components, **ALWAYS** place them in `src/sub-components/` with their own folder containing `index.tsx` and `styles.css`. Never create flat `.tsx` files inside a component folder. See `get_framework_guide(\"sub-component-patterns\")` for the full pattern, directory structure, CSS @import rules, and examples.",
56
59
  "tags": [
57
60
  "component",
58
61
  "preact",
@@ -124,7 +127,7 @@
124
127
  "sections-vs-components": {
125
128
  "title": "Sections vs Components",
126
129
  "description": "The difference between sections (page-level containers) and components (child elements)",
127
- "content": "ikas code components have two types: **sections** and **components**.\n\n## Sections\nSections are page-level, full-width containers that make up the structure of a page. Examples: Header, Hero Banner, Footer, Product Grid, Featured Collection.\n\n- Set `\"type\": \"section\"` in `ikas.config.json`\n- Use a `<section>` root element with full-width styling\n- Name the props interface `Props` in `types.ts`\n- Typically have full-width layout with inner max-width container\n- Styles: `width: 100%; padding: 64px 24px;` with `.inner { max-width: 1200px; margin: 0 auto; }`\n\n## Components\nComponents are child elements that are placed inside sections. Examples: Button, Product Card, Badge, Price Display, Image Gallery.\n\n- No `type` field needed in `ikas.config.json` (defaults to `\"component\"`)\n- Use a `<div>` root element\n- Name the props interface `Props` in `types.ts`\n- Sized by their content or parent container\n\n## Config Difference\nThe only config difference is the `type` field on the component definition:\n\n```json\n{\n \"components\": [\n {\n \"id\": \"product-card\",\n \"name\": \"Product Card\",\n \"entry\": \"./src/components/ProductCard/index.tsx\",\n \"styles\": \"./src/components/ProductCard/styles.css\",\n \"props\": []\n },\n {\n \"id\": \"hero-banner\",\n \"name\": \"Hero Banner\",\n \"type\": \"section\",\n \"entry\": \"./src/components/HeroBanner/index.tsx\",\n \"styles\": \"./src/components/HeroBanner/styles.css\",\n \"props\": []\n }\n ]\n}\n```\n\n## How to Decide\n- Will it span the full width of the page and sit at the top level? → **Section**\n- Will it be placed inside another container or repeated in a list? → **Component**",
130
+ "content": "ikas code components have two types: **sections** and **components**.\n\n## Sections\nSections are page-level, full-width containers that make up the structure of a page. Examples: Header, Hero Banner, Footer, Product Grid, Featured Collection.\n\n- Set `\"type\": \"section\"` in `ikas.config.json`\n- Use a `<section>` root element with full-width styling\n- Name the props interface `Props` in `types.ts`\n- Typically have full-width layout with inner max-width container\n- Styles: `width: 100%; padding: 64px 24px;` with `.inner { max-width: 1200px; margin: 0 auto; }`\n- **MUST include a `backgroundColor` COLOR prop** (default: `#ffffff`). Apply via inline style on the `<section>` element: `style={backgroundColor ? { backgroundColor } : undefined}`\n- Consider adding `textColor` COLOR props for text elements sitting directly on the section background, so they remain readable when the background changes\n\n## Components\nComponents are child elements that are placed inside sections. Examples: Button, Product Card, Badge, Price Display, Image Gallery.\n\n- No `type` field needed in `ikas.config.json` (defaults to `\"component\"`)\n- Use a `<div>` root element\n- Name the props interface `Props` in `types.ts`\n- Sized by their content or parent container\n\n## Config Difference\nThe only config difference is the `type` field on the component definition:\n\n```json\n{\n \"components\": [\n {\n \"id\": \"product-card\",\n \"name\": \"Product Card\",\n \"entry\": \"./src/components/ProductCard/index.tsx\",\n \"styles\": \"./src/components/ProductCard/styles.css\",\n \"props\": []\n },\n {\n \"id\": \"hero-banner\",\n \"name\": \"Hero Banner\",\n \"type\": \"section\",\n \"entry\": \"./src/components/HeroBanner/index.tsx\",\n \"styles\": \"./src/components/HeroBanner/styles.css\",\n \"props\": []\n }\n ]\n}\n```\n\n## Required Section Prop: backgroundColor\n\nEvery section MUST include a `backgroundColor` COLOR prop so store owners can customize the section background.\n\n### Config:\n```json\n{ \"name\": \"backgroundColor\", \"displayName\": \"Background Color\", \"type\": \"COLOR\", \"defaultValue\": \"#ffffff\" }\n```\n\n### Usage in index.tsx:\n```tsx\nexport function MySection({ title, backgroundColor = \"#ffffff\" }: Props) {\n return (\n <section className=\"my-section\" style={backgroundColor ? { backgroundColor } : undefined}>\n <div className=\"my-section-inner\">\n <h1>{title}</h1>\n </div>\n </section>\n );\n}\n```\n\nOptionally, also add `textColor` and/or `headingColor` COLOR props for text elements sitting directly on the section background. This ensures text remains readable when the store owner changes the background color.\n\n## How to Decide\n- Will it span the full width of the page and sit at the top level? → **Section**\n- Will it be placed inside another container or repeated in a list? → **Component**",
128
131
  "tags": [
129
132
  "section",
130
133
  "component",
@@ -138,7 +141,7 @@
138
141
  "common-pitfalls": {
139
142
  "title": "Common Pitfalls",
140
143
  "description": "Frequent mistakes LLMs and developers make when building ikas code components",
141
- "content": "## Common Pitfalls\n\nThese are the most common mistakes when building ikas code components. Avoid them for correct, working code.\n\n### 1. Root Component Should NOT Use observer\n\nThe ikas runtime wraps root component renders in `autorun()`, making them automatically reactive. Wrapping a root export with `observer()` is redundant and misleading.\n\n**Wrong** — observer on root export:\n```tsx\nimport { observer } from \"@ikas/component-utils\";\nimport { cartStore } from \"@ikas/bp-storefront\";\n\nconst CartSection = observer(function CartSection({ title }: Props) {\n const items = cartStore.cart?.orderLineItems ?? [];\n return <section>{title}: {items.length} items</section>;\n});\nexport default CartSection;\n```\n\n**Correct** — plain named export:\n```tsx\nimport { cartStore } from \"@ikas/bp-storefront\";\n\nexport function CartSection({ title }: Props) {\n const items = cartStore.cart?.orderLineItems ?? [];\n return <section>{title}: {items.length} items</section>;\n}\n\nexport default CartSection;\n```\n\n### 2. Observer Sub-Component Naming\n\nWhen using `observer()` on **sub-components**, use a named function expression — not an arrow function — for proper DevTools display names.\n\n**Wrong** — arrow function loses display name:\n```tsx\nconst CartBadge = observer(() => {\n return <span>{cartStore.cart?.orderLineItems.length ?? 0}</span>;\n});\n```\n\n**Correct** — named function expression:\n```tsx\nconst CartBadge = observer(function CartBadge() {\n return <span>{cartStore.cart?.orderLineItems.length ?? 0}</span>;\n});\n```\n\n### 3. Mutation Semantics\n\nMany storefront functions (122+) return `void` and **mutate their arguments in place**. Do NOT try to capture a return value:\n\n```tsx\n// WRONG — selectVariantValue returns void, not a new product\nconst updated = selectVariantValue(product, value);\n\n// CORRECT — mutates product in place, observer re-renders automatically\nselectVariantValue(product, dvv.variantValue);\n```\n\nOther mutation functions: `initLoginForm()`, `setLoginFormEmail()`, `clearFilter()`, `selectFilterValue()`.\n\n### 4. CSS Scoping Limits\n\nOnly **class selectors** in `styles.css` are reliably scoped. Element selectors are NOT scoped:\n\n```css\n/* SAFE — scoped to your component */\n.product-card { padding: 16px; }\n.product-card .title { font-size: 18px; }\n\n/* UNSAFE — NOT reliably scoped, may affect other components */\ndiv { margin: 0; }\nh1 { font-size: 24px; }\n```\n\nAlways use class selectors for all styles.\n\n### 5. Prop Null Handling\n\nProps from the editor can be `undefined` when the store owner hasn't set them. Always use optional chaining:\n\n```tsx\n// WRONG — will crash if product is undefined\n<h1>{props.product.name}</h1>\n\n// CORRECT\n<h1>{props.product?.name}</h1>\n{props.heroImage && <img src={getDefaultSrc(props.heroImage)} />}\n```\n\n### 6. IkasProductImage vs IkasImage\n\n`variant.images` is `IkasProductImage[]`, NOT `IkasImage[]`. You must access the `.image` property to get the `IkasImage` needed by CDN helpers:\n\n```tsx\n// WRONG — productImage is IkasProductImage, not IkasImage\ngetDefaultSrc(productImage);\n\n// CORRECT — access .image to get IkasImage\ngetDefaultSrc(productImage.image);\n\n// Full pattern:\nconst images: IkasImage[] = variant.images\n .map((pi) => pi.image)\n .filter((img): img is IkasImage => img != null);\n```\n\n### 7. Type Assertion Pattern\n\nSome storefront functions have type inference gaps. Use `as unknown as` casts when needed — this is a known pattern:\n\n```tsx\nconst inStock = hasProductStock(product) as unknown as boolean;\nconst finalPrice = getProductVariantFormattedFinalPrice(variant) as unknown as string;\nconst canAddToCart = isAddToCartEnabled(product) as unknown as boolean;\n```\n\nThis applies to functions like `hasProductStock`, `hasProductVariantStock`, `isAddToCartEnabled`, `hasProductVariantDiscount`, `getProductVariantDiscountPercentage`, `getProductVariantFormattedFinalPrice`, `getProductVariantFormattedSellPrice`, `getProductVariantFormattedDiscountAmount`, and `getProductVariantFormattedCampaignPrice`.\n\nNote: `getProductVariantMainImage` returns `IkasProductImage | undefined` (NOT `IkasImage`). Access `.image` to get the `IkasImage` for CDN helpers like `getDefaultSrc()`.\n\n### 8. Store Data Null Safety\n\nStore data (`customerStore.customer`, `cartStore.cart`, `baseStore`) is `null` before initialization completes. Always guard access:\n\n```tsx\n// WRONG — crashes if customer is null\n<h1>{customerStore.customer.firstName}</h1>\n\n// CORRECT — null check first\nif (!customerStore.customer) return <div>Loading...</div>;\n<h1>{customerStore.customer.firstName}</h1>\n\n// Also correct — optional chaining\n<h1>{customerStore.customer?.firstName ?? \"Guest\"}</h1>\n```\n\nSame for `cartStore.cart` — always use `cartStore.cart?.orderLineItems ?? []`.\n\n### 9. ProductList/BlogList Data Access\n\n`productList.data` is the correct way to access products in a product list. Similarly, `blogList.data` for blogs. The display names `.products` / `.blogs` are only used by the blueprint editor — they do NOT exist at runtime:\n\n```tsx\n// CORRECT — use .data for both product lists and blog lists\nconst products = productList?.data ?? [];\nconst blogs = blogList?.data ?? [];\n\n// WRONG — .products / .blogs are display names, not actual fields\nconst products = productList?.products ?? [];\nconst blogs = blogList?.blogs ?? [];\n```\n\n### 10. Form Field Access Pattern\n\nForm fields are objects with `.value`, `.label`, `.hasError`, `.message`. Never access the field directly as a primitive:\n\n```tsx\n// WRONG — loginForm.email is a field object, not a string\n<input value={loginForm.email} />\n\n// CORRECT — access .value for the actual value\n<input value={loginForm.email.value} />\n{loginForm.email.hasError && <span>{loginForm.email.message}</span>}\n```\n\n### 11. Optional Chaining for Editor Props\n\nAll props from `ikas.config.json` can be `undefined` in the editor before the store owner sets them. Always use optional chaining and defaults:\n\n```tsx\n// WRONG — will crash in the editor\n<h1>{props.title}</h1>\n<img src={getDefaultSrc(props.image)} />\n{props.links.links.map(...)}\n\n// CORRECT — safe access with defaults\n<h1>{props.title ?? \"Default Title\"}</h1>\n{props.image && <img src={getDefaultSrc(props.image)} />}\n{(props.links?.links ?? []).map(...)}\n```\n\n### 12. Event Handler Typing\n\nPreact uses different event types than React. Use `(e: Event)` not `(e: React.ChangeEvent)`. Access values with casting. Preact uses `onInput` not `onChange` for text inputs:\n\n```tsx\n// WRONG — React patterns don't work in Preact\nonChange={(e: React.ChangeEvent<HTMLInputElement>) => setValue(e.target.value)}\n\n// CORRECT — Preact event handling\nonInput={(e: Event) => setValue((e.target as HTMLInputElement).value)}\n```\n\nFor select elements:\n```tsx\nonChange={(e: Event) => setOption((e.target as HTMLSelectElement).value)}\n```\n\n### 13. Function Parameter Order\n\nMany storefront functions take specific parameter orders. Always verify with `get_function_doc()` before using:\n\n```tsx\n// WRONG — submitLoginForm only takes the form, not the store\nsubmitLoginForm(customerStore, loginForm);\n\n// CORRECT\nsubmitLoginForm(loginForm);\n\n// WRONG — wrong parameter order for addItemToCart\naddItemToCart(product, variant, 1);\n\n// CORRECT — variant first, then product, then quantity\naddItemToCart(variant, product, 1);\n\n// WRONG — selectVariantValue takes product and variantValue\nselectVariantValue(variant, value);\n\n// CORRECT\nselectVariantValue(product, dvv.variantValue);\n```\n\nWhen in doubt, use the `get_function_doc(functionName)` MCP tool to check the exact signature.",
144
+ "content": "## Common Pitfalls\n\nThese are the most common mistakes when building ikas code components. Avoid them for correct, working code.\n\n### 1. Root Component Should NOT Use observer\n\nThe ikas runtime wraps root component renders in `autorun()`, making them automatically reactive. Wrapping a root export with `observer()` is redundant and misleading.\n\n**Wrong** — observer on root export:\n```tsx\nimport { observer } from \"@ikas/component-utils\";\nimport { cartStore } from \"@ikas/bp-storefront\";\n\nconst CartSection = observer(function CartSection({ title }: Props) {\n const items = cartStore.cart?.orderLineItems ?? [];\n return <section>{title}: {items.length} items</section>;\n});\nexport default CartSection;\n```\n\n**Correct** — plain named export:\n```tsx\nimport { cartStore } from \"@ikas/bp-storefront\";\n\nexport function CartSection({ title }: Props) {\n const items = cartStore.cart?.orderLineItems ?? [];\n return <section>{title}: {items.length} items</section>;\n}\n\nexport default CartSection;\n```\n\n### 2. Observer Sub-Component Naming\n\nWhen using `observer()` on **sub-components**, use a named function expression — not an arrow function — for proper DevTools display names.\n\n**Wrong** — arrow function loses display name:\n```tsx\nconst CartBadge = observer(() => {\n return <span>{cartStore.cart?.orderLineItems.length ?? 0}</span>;\n});\n```\n\n**Correct** — named function expression:\n```tsx\nconst CartBadge = observer(function CartBadge() {\n return <span>{cartStore.cart?.orderLineItems.length ?? 0}</span>;\n});\n```\n\n### 3. Mutation Semantics\n\nMany storefront functions (122+) return `void` and **mutate their arguments in place**. Do NOT try to capture a return value:\n\n```tsx\n// WRONG — selectVariantValue returns void, not a new product\nconst updated = selectVariantValue(product, value);\n\n// CORRECT — mutates product in place, observer re-renders automatically\nselectVariantValue(product, dvv.variantValue);\n```\n\nOther mutation functions: `initLoginForm()`, `setLoginFormEmail()`, `clearFilter()`, `selectFilterValue()`.\n\n### 4. CSS Scoping Limits\n\nOnly **class selectors** in `styles.css` are reliably scoped. Element selectors are NOT scoped:\n\n```css\n/* SAFE — scoped to your component */\n.product-card { padding: 16px; }\n.product-card .title { font-size: 18px; }\n\n/* UNSAFE — NOT reliably scoped, may affect other components */\ndiv { margin: 0; }\nh1 { font-size: 24px; }\n```\n\nAlways use class selectors for all styles.\n\n### 5. Prop Null Handling\n\nProps from the editor can be `undefined` when the store owner hasn't set them. Always use optional chaining:\n\n```tsx\n// WRONG — will crash if product is undefined\n<h1>{props.product.name}</h1>\n\n// CORRECT\n<h1>{props.product?.name}</h1>\n{props.heroImage && <img src={getDefaultSrc(props.heroImage)} />}\n```\n\n### 6. IkasProductImage vs IkasImage\n\n`variant.images` is `IkasProductImage[]`, NOT `IkasImage[]`. You must access the `.image` property to get the `IkasImage` needed by CDN helpers:\n\n```tsx\n// WRONG — productImage is IkasProductImage, not IkasImage\ngetDefaultSrc(productImage);\n\n// CORRECT — access .image to get IkasImage\ngetDefaultSrc(productImage.image);\n\n// Full pattern:\nconst images: IkasImage[] = variant.images\n .map((pi) => pi.image)\n .filter((img): img is IkasImage => img != null);\n```\n\n### 7. Type Assertion Pattern\n\nSome storefront functions have type inference gaps. Use `as unknown as` casts when needed — this is a known pattern:\n\n```tsx\nconst inStock = hasProductStock(product) as unknown as boolean;\nconst finalPrice = getProductVariantFormattedFinalPrice(variant) as unknown as string;\nconst canAddToCart = isAddToCartEnabled(product) as unknown as boolean;\n```\n\nThis applies to functions like `hasProductStock`, `hasProductVariantStock`, `isAddToCartEnabled`, `hasProductVariantDiscount`, `getProductVariantDiscountPercentage`, `getProductVariantFormattedFinalPrice`, `getProductVariantFormattedSellPrice`, `getProductVariantFormattedDiscountAmount`, and `getProductVariantFormattedCampaignPrice`.\n\nNote: `getProductVariantMainImage` returns `IkasProductImage | undefined` (NOT `IkasImage`). Access `.image` to get the `IkasImage` for CDN helpers like `getDefaultSrc()`.\n\n### 8. Store Data Null Safety\n\nStore data (`customerStore.customer`, `cartStore.cart`, `baseStore`) is `null` before initialization completes. Always guard access:\n\n```tsx\n// WRONG — crashes if customer is null\n<h1>{customerStore.customer.firstName}</h1>\n\n// CORRECT — null check first\nif (!customerStore.customer) return <div>Loading...</div>;\n<h1>{customerStore.customer.firstName}</h1>\n\n// Also correct — optional chaining\n<h1>{customerStore.customer?.firstName ?? \"Guest\"}</h1>\n```\n\nSame for `cartStore.cart` — always use `cartStore.cart?.orderLineItems ?? []`.\n\n### 9. ProductList/BlogList Data Access\n\n`productList.data` is the correct way to access products in a product list. Similarly, `blogList.data` for blogs. The display names `.products` / `.blogs` are only used by the blueprint editor — they do NOT exist at runtime:\n\n```tsx\n// CORRECT — use .data for both product lists and blog lists\nconst products = productList?.data ?? [];\nconst blogs = blogList?.data ?? [];\n\n// WRONG — .products / .blogs are display names, not actual fields\nconst products = productList?.products ?? [];\nconst blogs = blogList?.blogs ?? [];\n```\n\n### 10. Form Field Access Pattern\n\nForm fields are objects with `.value`, `.label`, `.hasError`, `.message`. Never access the field directly as a primitive:\n\n```tsx\n// WRONG — loginForm.email is a field object, not a string\n<input value={loginForm.email} />\n\n// CORRECT — access .value for the actual value\n<input value={loginForm.email.value} />\n{loginForm.email.hasError && <span>{loginForm.email.message}</span>}\n```\n\n### 11. Optional Chaining for Editor Props\n\nAll props from `ikas.config.json` can be `undefined` in the editor before the store owner sets them. Always use optional chaining and defaults:\n\n```tsx\n// WRONG — will crash in the editor\n<h1>{props.title}</h1>\n<img src={getDefaultSrc(props.image)} />\n{props.links.links.map(...)}\n\n// CORRECT — safe access with defaults\n<h1>{props.title ?? \"Default Title\"}</h1>\n{props.image && <img src={getDefaultSrc(props.image)} />}\n{(props.links?.links ?? []).map(...)}\n```\n\n### 12. Event Handler Typing\n\nPreact uses different event types than React. Use `(e: Event)` not `(e: React.ChangeEvent)`. Access values with casting. Preact uses `onInput` not `onChange` for text inputs:\n\n```tsx\n// WRONG — React patterns don't work in Preact\nonChange={(e: React.ChangeEvent<HTMLInputElement>) => setValue(e.target.value)}\n\n// CORRECT — Preact event handling\nonInput={(e: Event) => setValue((e.target as HTMLInputElement).value)}\n```\n\nFor select elements:\n```tsx\nonChange={(e: Event) => setOption((e.target as HTMLSelectElement).value)}\n```\n\n### 13. Function Parameter Order\n\nMany storefront functions take specific parameter orders. Always verify with `get_function_doc()` before using:\n\n```tsx\n// WRONG — submitLoginForm only takes the form, not the store\nsubmitLoginForm(customerStore, loginForm);\n\n// CORRECT\nsubmitLoginForm(loginForm);\n\n// WRONG — wrong parameter order for addItemToCart\naddItemToCart(product, variant, 1);\n\n// CORRECT — variant first, then product, then quantity\naddItemToCart(variant, product, 1);\n\n// WRONG — selectVariantValue takes product and variantValue\nselectVariantValue(variant, value);\n\n// CORRECT\nselectVariantValue(product, dvv.variantValue);\n```\n\nWhen in doubt, use the `get_function_doc(functionName)` MCP tool to check the exact signature.\n\n### 14. Missing backgroundColor Prop on Sections\n\nEvery section MUST include a `backgroundColor` COLOR prop so store owners can customize the section background. Without it, the section has a hardcoded background that cannot be changed in the editor.\n\n**Wrong** — section with no backgroundColor prop:\n```json\n// ikas.config.json\n{ \"id\": \"my-section\", \"type\": \"section\", \"props\": [\n { \"name\": \"title\", \"type\": \"TEXT\" }\n]}\n```\n```tsx\nexport function MySection({ title }: Props) {\n return <section className=\"my-section\"><h1>{title}</h1></section>;\n}\n```\n\n**Correct** — section with backgroundColor prop:\n```json\n// ikas.config.json\n{ \"id\": \"my-section\", \"type\": \"section\", \"props\": [\n { \"name\": \"title\", \"type\": \"TEXT\" },\n { \"name\": \"backgroundColor\", \"displayName\": \"Background Color\", \"type\": \"COLOR\", \"defaultValue\": \"#ffffff\" }\n]}\n```\n```tsx\nexport function MySection({ title, backgroundColor = \"#ffffff\" }: Props) {\n return (\n <section className=\"my-section\" style={backgroundColor ? { backgroundColor } : undefined}>\n <h1>{title}</h1>\n </section>\n );\n}\n```\n\nOptionally, also consider adding `textColor` COLOR props for text elements sitting directly on the section background, so they remain readable when the store owner changes the background color.\n\n### 15. Forgetting to Group Props for Complex Sections\n\nSections with 5+ props should use prop groups to organize the editor sidebar. Without groups, store owners see a long flat list of unrelated props.\n\n**Better** — organize related props into groups:\n```json\n{\n \"propGroups\": [\n { \"id\": \"content\", \"name\": \"Content\" },\n { \"id\": \"appearance\", \"name\": \"Appearance\" }\n ],\n \"props\": [\n { \"name\": \"heading\", \"groupId\": \"content\", ... },\n { \"name\": \"bgColor\", \"groupId\": \"appearance\", ... }\n ]\n}\n```\n\nSee `get_framework_guide(\"prop-groups\")` for full details.\n\n### 16. Hardcoded Static Text in Components\n\nAll user-visible text MUST be TEXT props — never hardcode strings in JSX. Hardcoded text cannot be translated for multilingual storefronts.\n\n**Wrong** — hardcoded strings:\n```tsx\nexport function LoginSection({ backgroundColor }: Props) {\n return (\n <section style={backgroundColor ? { backgroundColor } : undefined}>\n <h1>Sign In</h1>\n <button>{form.isSubmitting ? \"Signing in...\" : \"Sign In\"}</button>\n <p>Don't have an account? <a href=\"/register\">Create one</a></p>\n </section>\n );\n}\n```\n\n**Correct** — all text as TEXT props with defaultValues:\n```json\n// ikas.config.json\n{ \"props\": [\n { \"name\": \"title\", \"type\": \"TEXT\", \"defaultValue\": \"Sign In\", \"groupId\": \"texts\" },\n { \"name\": \"submitButtonText\", \"type\": \"TEXT\", \"defaultValue\": \"Sign In\", \"groupId\": \"texts\" },\n { \"name\": \"submittingButtonText\", \"type\": \"TEXT\", \"defaultValue\": \"Signing in...\", \"groupId\": \"texts\" },\n { \"name\": \"noAccountText\", \"type\": \"TEXT\", \"defaultValue\": \"Don't have an account?\", \"groupId\": \"texts\" },\n { \"name\": \"createAccountLinkText\", \"type\": \"TEXT\", \"defaultValue\": \"Create one\", \"groupId\": \"texts\" }\n],\n\"propGroups\": [{ \"id\": \"texts\", \"name\": \"Texts\" }]}\n```\n```tsx\nexport function LoginSection({ title = \"Sign In\", submitButtonText = \"Sign In\",\n submittingButtonText = \"Signing in...\", noAccountText = \"Don't have an account?\",\n createAccountLinkText = \"Create one\", backgroundColor }: Props) {\n return (\n <section style={backgroundColor ? { backgroundColor } : undefined}>\n <h1>{title}</h1>\n <button>{form.isSubmitting ? submittingButtonText : submitButtonText}</button>\n <p>{noAccountText} <a href=\"/register\">{createAccountLinkText}</a></p>\n </section>\n );\n}\n```\n\nFor button loading states, use two separate TEXT props (e.g., `submitButtonText` + `submittingButtonText`). Group text props under a \"Texts\" propGroup when the component has 5+ props.",
142
145
  "tags": [
143
146
  "pitfalls",
144
147
  "gotchas",
@@ -150,7 +153,10 @@
150
153
  "null-safety",
151
154
  "forms",
152
155
  "events",
153
- "parameters"
156
+ "parameters",
157
+ "static-text",
158
+ "translation",
159
+ "i18n"
154
160
  ]
155
161
  },
156
162
  "sub-component-patterns": {
@@ -171,7 +177,7 @@
171
177
  "ai-workflow": {
172
178
  "title": "AI Agent Workflow for Building ikas Components",
173
179
  "description": "Step-by-step guide for AI coding agents building ikas storefront components using CLI commands and MCP tools",
174
- "content": "## AI Agent Workflow\n\nThis is the recommended step-by-step workflow for AI agents building ikas code components. Follow these steps in order for reliable, error-free results.\n\n**IMPORTANT: NEVER create or edit `types.ts` manually — it is auto-generated by the CLI.** The CLI commands below update BOTH `ikas.config.json` AND `types.ts` automatically.\n\n### Step 1: Create Component with Props\n\nUse `get_section_template(sectionType)` to get a starter template — it includes a ready-to-run CLI command with `--props`.\n\nThen run the single `add-component --props` command to create the component scaffold WITH all props in one step:\n```bash\nnpx ikas-component config add-component --name \"HeroSection\" --type section --props '[{\"name\":\"title\",\"displayName\":\"Title\",\"type\":\"TEXT\",\"required\":true},{\"name\":\"backgroundImage\",\"displayName\":\"Background Image\",\"type\":\"IMAGE\"},{\"name\":\"showButton\",\"displayName\":\"Show Button\",\"type\":\"BOOLEAN\"}]'\n```\n\nThis creates the component directory with `index.tsx`, `types.ts` (with correct Props interface), `styles.css`, updates `ikas.config.json`, and updates the barrel export. The output is JSON:\n```json\n{\"success\": true, \"componentId\": \"abc123-hero-section\", \"componentName\": \"HeroSection\", \"type\": \"section\", \"propsCount\": 3, \"files\": [...]}\n```\n\nThe `--props` flag accepts a JSON array of prop objects. Each prop needs `name` + `type` at minimum. `displayName` is auto-generated from camelCase name if omitted (e.g. `backgroundImage` → `\"Background Image\"`).\n\nTo add more props later, use `add-prop`:\n```bash\nnpx ikas-component config add-prop --component \"HeroSection\" --name \"subtitle\" --displayName \"Subtitle\" --type TEXT\n```\n\n### Step 2: Get Reference Material\n\nBefore writing component code, use MCP tools to get the right patterns:\n- `get_section_template(sectionType)` — Get a starter template for common section types (product-detail, cart, login, header, footer, etc.)\n- `get_framework_guide(\"common-pitfalls\")` — Review common mistakes to avoid\n- `get_framework_guide(\"component-structure\")` — Review component structure patterns\n- `get_function_doc(functionName)` — Look up exact function signatures before using them\n- `get_model_guide(typeName)` — Get comprehensive info about a model type\n\n### Step 3: Write the Component Code\n\nEdit `src/components/{ComponentName}/index.tsx` with the implementation. **Do NOT edit `types.ts`** — it was already generated correctly in Step 1. Key rules:\n- Import props from `./types` (auto-generated in Step 1)\n- Import storefront functions from `@ikas/bp-storefront`\n- Root export should use named + default export: `export function X({ ... }: Props) { ... }` + `export default X;`\n- Only wrap sub-components with `observer()` when they independently read MobX stores\n- Use optional chaining for all props: `props.title ?? \"Default\"`\n- Use `as unknown as boolean` cast for functions like `hasProductStock`, `isAddToCartEnabled`\n\n### Step 4: Write Styles\n\nEdit `src/components/{ComponentName}/styles.css`. Key rules:\n- Use class selectors only (`.my-class`), never bare element selectors\n- CSS is auto-scoped at build time — no manual namespacing needed\n- For sections: `width: 100%; padding: 64px 24px;` with inner max-width container\n\n### Step 5: Verify with Type Checking\n\nRun the lightweight type checker:\n```bash\nnpx ikas-component check --json\n```\n\nSuccess output:\n```json\n{\"success\": true, \"errors\": []}\n```\n\nError output:\n```json\n{\"success\": false, \"errorCount\": 2, \"errors\": [{\"file\": \"src/components/Hero/index.tsx\", \"line\": 15, \"column\": 3, \"code\": \"TS2339\", \"message\": \"Property 'title' does not exist on type 'Props'\"}]}\n```\n\n### Step 6: Fix Errors and Re-check\n\nFor each error:\n1. Read the file and line number from the error\n2. Fix the issue (common fixes below)\n3. Re-run `npx ikas-component check --json`\n\n**Common error fixes:**\n- `Property 'x' does not exist on type 'Props'` — Prop wasn't added via CLI. Run `npx ikas-component config add-prop`.\n- `Cannot find module '@ikas/bp-storefront'` — Normal in type-check if node_modules not fully installed. Focus on component-level errors.\n- `Type 'X' is not assignable to type 'Y'` — Check function signature with `get_function_doc()`.\n\n### Step 7: Full Build Validation\n\nOnce type checking passes, run the full build:\n```bash\nnpx ikas-component build\n```\n\nThis runs type checking + esbuild compilation + CSS scoping.\n\n### Quick Reference: CLI Commands\n\n| Command | Purpose |\n|---------|--------|\n| `npx ikas-component config add-component --name X --type section --props '[...]'` | **Primary** — create component with all props |\n| `npx ikas-component config add-component --name X --type section` | Create component with no props |\n| `npx ikas-component config add-prop --component X --name y --displayName Y --type TEXT` | Add a prop incrementally |\n| `npx ikas-component config update-prop --component X --prop y --required true` | Update a prop |\n| `npx ikas-component config remove-prop --component X --prop y` | Remove a prop |\n| `npx ikas-component config remove-component --name X` | Remove a component |\n| `npx ikas-component config list` | List all components and props |\n| `npx ikas-component check --json` | Type-check with JSON output |\n| `npx ikas-component build` | Full production build |\n\n### Quick Reference: MCP Tools\n\n| Tool | When to Use |\n|------|------------|\n| `get_section_template(type)` | Starting a new section — get starter code + CLI command |\n| `get_framework_guide(topic)` | Understanding patterns, pitfalls, architecture |\n| `get_function_doc(name)` | Looking up exact function signature |\n| `get_model_guide(type)` | Working with a model type (IkasProduct, IkasCart, etc.) |\n| `get_prop_types()` | Checking available prop types for ikas.config.json |\n| `search_docs(query)` | Finding relevant functions/docs by keyword |",
180
+ "content": "## AI Agent Workflow\n\nThis is the recommended step-by-step workflow for AI agents building ikas code components. Follow these steps in order for reliable, error-free results.\n\n**IMPORTANT: NEVER create or edit `types.ts` manually — it is auto-generated by the CLI.** The CLI commands below update BOTH `ikas.config.json` AND `types.ts` automatically.\n\n### Step 1: Create Component with Props\n\nUse `get_section_template(sectionType)` to get a starter template — it includes a ready-to-run CLI command with `--props`.\n\n**Important:** When creating a section, always include a `backgroundColor` COLOR prop (default: `#ffffff`). Optionally consider adding `textColor` for text elements directly on the section background.\n\n**Important:** Ensure ALL user-visible text (headings, buttons, labels, empty states, loading text) is exposed as TEXT props. Never hardcode text strings in JSX. Use `defaultValue` for English defaults. For button loading states, use two separate props (e.g., `submitButtonText` + `submittingButtonText`). Group text props under a \"Texts\" propGroup when 5+ props exist.\n\nThen run the single `add-component --props` command to create the component scaffold WITH all props in one step:\n```bash\nnpx ikas-component config add-component --name \"HeroSection\" --type section --props '[{\"name\":\"title\",\"displayName\":\"Title\",\"type\":\"TEXT\",\"required\":true},{\"name\":\"backgroundImage\",\"displayName\":\"Background Image\",\"type\":\"IMAGE\"},{\"name\":\"showButton\",\"displayName\":\"Show Button\",\"type\":\"BOOLEAN\"}]'\n```\n\nThis creates the component directory with `index.tsx`, `types.ts` (with correct Props interface), `styles.css`, updates `ikas.config.json`, and updates the barrel export. The output is JSON:\n```json\n{\"success\": true, \"componentId\": \"abc123-hero-section\", \"componentName\": \"HeroSection\", \"type\": \"section\", \"propsCount\": 3, \"files\": [...]}\n```\n\nThe `--props` flag accepts a JSON array of prop objects. Each prop needs `name` + `type` at minimum. `displayName` is auto-generated from camelCase name if omitted (e.g. `backgroundImage` → `\"Background Image\"`).\n\nTo add more props later, use `add-prop`:\n```bash\nnpx ikas-component config add-prop --component \"HeroSection\" --name \"subtitle\" --displayName \"Subtitle\" --type TEXT\n```\n\n### Step 2: Get Reference Material\n\nBefore writing component code, use MCP tools to get the right patterns:\n- `get_section_template(sectionType)` — Get a starter template for common section types (product-detail, cart, login, header, footer, etc.)\n- `get_framework_guide(\"common-pitfalls\")` — Review common mistakes to avoid\n- `get_framework_guide(\"component-structure\")` — Review component structure patterns\n- `get_function_doc(functionName)` — Look up exact function signatures before using them\n- `get_model_guide(typeName)` — Get comprehensive info about a model type\n\n### Step 3: Write the Component Code\n\nEdit `src/components/{ComponentName}/index.tsx` with the implementation. **Do NOT edit `types.ts`** — it was already generated correctly in Step 1. Key rules:\n- Import props from `./types` (auto-generated in Step 1)\n- Import storefront functions from `@ikas/bp-storefront`\n- Root export should use named + default export: `export function X({ ... }: Props) { ... }` + `export default X;`\n- Only wrap sub-components with `observer()` when they independently read MobX stores\n- Use optional chaining for all props: `props.title ?? \"Default\"`\n- Use `as unknown as boolean` cast for functions like `hasProductStock`, `isAddToCartEnabled`\n- **Sections MUST apply backgroundColor**: destructure `backgroundColor = \"#ffffff\"` and add `style={backgroundColor ? { backgroundColor } : undefined}` on the root `<section>` element\n\n### Step 3.5: Organize Props into Groups (if 5+ props)\n\nIf the component has 5 or more props, organize them into groups for better editor UX:\n```bash\nnpx ikas-component config add-prop-group --component \"HeroSection\" --id content --name \"Content\"\nnpx ikas-component config add-prop-group --component \"HeroSection\" --id appearance --name \"Appearance\"\nnpx ikas-component config update-prop --component \"HeroSection\" --prop title --group content\nnpx ikas-component config update-prop --component \"HeroSection\" --prop backgroundImage --group appearance\n```\n\n### Step 4: Write Styles\n\nEdit `src/components/{ComponentName}/styles.css`. Key rules:\n- Use class selectors only (`.my-class`), never bare element selectors\n- CSS is auto-scoped at build time — no manual namespacing needed\n- For sections: `width: 100%; padding: 64px 24px;` with inner max-width container\n\n### Step 5: Verify with Type Checking\n\nRun the lightweight type checker:\n```bash\nnpx ikas-component check --json\n```\n\nSuccess output:\n```json\n{\"success\": true, \"errors\": []}\n```\n\nError output:\n```json\n{\"success\": false, \"errorCount\": 2, \"errors\": [{\"file\": \"src/components/Hero/index.tsx\", \"line\": 15, \"column\": 3, \"code\": \"TS2339\", \"message\": \"Property 'title' does not exist on type 'Props'\"}]}\n```\n\n### Step 6: Fix Errors and Re-check\n\nFor each error:\n1. Read the file and line number from the error\n2. Fix the issue (common fixes below)\n3. Re-run `npx ikas-component check --json`\n\n**Common error fixes:**\n- `Property 'x' does not exist on type 'Props'` — Prop wasn't added via CLI. Run `npx ikas-component config add-prop`.\n- `Cannot find module '@ikas/bp-storefront'` — Normal in type-check if node_modules not fully installed. Focus on component-level errors.\n- `Type 'X' is not assignable to type 'Y'` — Check function signature with `get_function_doc()`.\n\n### Step 7: Full Build Validation\n\nOnce type checking passes, run the full build:\n```bash\nnpx ikas-component build\n```\n\nThis runs type checking + esbuild compilation + CSS scoping.\n\n### Quick Reference: CLI Commands\n\n| Command | Purpose |\n|---------|--------|\n| `npx ikas-component config add-component --name X --type section --props '[...]'` | **Primary** — create component with all props |\n| `npx ikas-component config add-component --name X --type section` | Create component with no props |\n| `npx ikas-component config add-prop --component X --name y --displayName Y --type TEXT` | Add a prop incrementally |\n| `npx ikas-component config update-prop --component X --prop y --required true` | Update a prop |\n| `npx ikas-component config remove-prop --component X --prop y` | Remove a prop |\n| `npx ikas-component config remove-component --name X` | Remove a component |\n| `npx ikas-component config list` | List all components and props |\n| `npx ikas-component check --json` | Type-check with JSON output |\n| `npx ikas-component build` | Full production build |\n\n### Quick Reference: MCP Tools\n\n| Tool | When to Use |\n|------|------------|\n| `get_section_template(type)` | Starting a new section — get starter code + CLI command |\n| `get_framework_guide(topic)` | Understanding patterns, pitfalls, architecture |\n| `get_function_doc(name)` | Looking up exact function signature |\n| `get_model_guide(type)` | Working with a model type (IkasProduct, IkasCart, etc.) |\n| `get_prop_types()` | Checking available prop types for ikas.config.json |\n| `search_docs(query)` | Finding relevant functions/docs by keyword |",
175
181
  "tags": [
176
182
  "ai",
177
183
  "workflow",
@@ -341,7 +347,7 @@
341
347
  "real-world-architecture": {
342
348
  "title": "Real-World Theme Architecture",
343
349
  "description": "How production themes are structured: page types, section composition, component reuse, and prop design patterns",
344
- "content": "## Real-World Theme Architecture\n\nThis guide describes how a production ikas theme is structured, based on analysis of real deployed themes.\n\n### Page Types\n\nA complete theme typically has these page types:\n\n| Page Type | Purpose | Common Sections |\n|-----------|---------|------------------|\n| `INDEX` | Home page | Header, Hero Banner, Featured Products, Categories, Footer |\n| `CATEGORY` | Category listing | Header, Product List, Footer |\n| `PRODUCT_DETAIL` | Product page | Header, Product Detail, Reviews, Related Products, Footer |\n| `BLOG` | Blog listing | Header, Blog List, Footer |\n| `BLOG` | Blog article | Header, Blog Post Detail, Footer |\n| `CART` | Shopping cart | Header, Cart Section, Footer |\n| `CHECKOUT` | Checkout flow | Minimal Header, Checkout Form |\n| `LOGIN` | Sign in | Header, Login Form, Footer |\n| `REGISTER` | Sign up | Header, Register Form, Footer |\n| `FORGOT_PASSWORD` | Password recovery | Header, Forgot Password Form, Footer |\n| `ACCOUNT` | Customer dashboard | Header, Account Section, Footer |\n| `SEARCH` | Search results | Header, Product List (search mode), Footer |\n| `CUSTOM` | Custom pages (About, Contact, FAQ) | Header, Custom Content, Footer |\n| `NOT_FOUND` | 404 page | Header, 404 Message, Footer |\n\n### Section Composition Pattern\n\nEvery page follows: **Header → Content Section(s) → Footer**\n\n- Header and Footer are shared across 36/37 pages (all except checkout)\n- Content sections are page-specific\n- Some sections are reused across multiple pages (FAQ on 10 pages, Rich Text on 9)\n\n### Section Reuse Strategy\n\nDesign sections to be reusable:\n\n| Section | Reuse Count | Strategy |\n|---------|-------------|----------|\n| Header | 36 pages | Single section, all navigation |\n| Footer | 36 pages | Single section, all links |\n| FAQ | 10 pages | Generic accordion, content via props |\n| Rich Text / HTML | 9 pages | Generic content block |\n| Product Detail | 1 page | Highly specialized |\n| Cart | 1 page | Highly specialized |\n\n### Component Hierarchy\n\nProduction sections have sub-components:\n\n```\nHeader Section (section)\n├── AnnouncementBar (component)\n├── NavigationBar (component)\n│ ├── Logo\n│ ├── NavLinks\n│ └── CartIcon / AccountIcon\n└── MobileMenu (component)\n\nProduct Detail Section (section)\n├── ImageGallery (component)\n├── VariantSelector (component)\n├── PriceDisplay (component)\n├── AddToCartButton (component)\n└── ProductDescription (component)\n```\n\n### Prop Design Patterns\n\nCommon prop patterns seen in production:\n\n1. **Content props**: `TEXT` for headings, descriptions, button labels\n2. **Style props**: `COLOR` for backgrounds, text colors, accents\n3. **Toggle props**: `BOOLEAN` for show/hide sections, features\n4. **Layout props**: `SELECT` for layout variants (grid/list, left/center/right)\n5. **Navigation props**: `LIST_OF_LINK` for editable nav menus\n6. **Data props**: `PRODUCT`, `PRODUCT_LIST`, `BLOG_LIST` for dynamic data\n7. **Media props**: `IMAGE` for logos, banners, icons\n\n### Responsive Design\n\nProduction themes target these breakpoints:\n- Desktop: 1200px+ (max-width container)\n- Tablet: 768px-1199px\n- Mobile: <768px\n\nCommon responsive patterns:\n```css\n.section { width: 100%; padding: 64px 24px; }\n.section-inner { max-width: 1200px; margin: 0 auto; }\n\n@media (max-width: 768px) {\n .section { padding: 32px 16px; }\n .grid { grid-template-columns: 1fr; }\n}\n```\n\n### Essential Sections Checklist\n\nEvery complete theme needs at minimum:\n- [ ] Header (with mobile menu)\n- [ ] Footer\n- [ ] Hero Banner / Home content\n- [ ] Product List (category page)\n- [ ] Product Detail\n- [ ] Cart\n- [ ] Login / Register / Forgot Password\n- [ ] Account (orders, addresses)\n- [ ] 404 Page\n- [ ] Contact Form (optional but common)\n- [ ] FAQ (optional but common)\n- [ ] Blog List + Blog Post (optional)",
350
+ "content": "## Real-World Theme Architecture\n\nThis guide describes how a production ikas theme is structured, based on analysis of real deployed themes.\n\n### Page Types\n\nA complete theme typically has these page types:\n\n| Page Type | Purpose | Common Sections |\n|-----------|---------|------------------|\n| `INDEX` | Home page | Header, Hero Banner, Featured Products, Categories, Footer |\n| `CATEGORY` | Category listing | Header, Product List, Footer |\n| `PRODUCT_DETAIL` | Product page | Header, Product Detail, Reviews, Related Products, Footer |\n| `BLOG` | Blog listing | Header, Blog List, Footer |\n| `BLOG` | Blog article | Header, Blog Post Detail, Footer |\n| `CART` | Shopping cart | Header, Cart Section, Footer |\n| `CHECKOUT` | Checkout flow | Minimal Header, Checkout Form |\n| `LOGIN` | Sign in | Header, Login Form, Footer |\n| `REGISTER` | Sign up | Header, Register Form, Footer |\n| `FORGOT_PASSWORD` | Password recovery | Header, Forgot Password Form, Footer |\n| `ACCOUNT` | Customer dashboard | Header, Account Section, Footer |\n| `SEARCH` | Search results | Header, Product List (search mode), Footer |\n| `CUSTOM` | Custom pages (About, Contact, FAQ) | Header, Custom Content, Footer |\n| `NOT_FOUND` | 404 page | Header, 404 Message, Footer |\n\n### Section Composition Pattern\n\nEvery page follows: **Header → Content Section(s) → Footer**\n\n- Header and Footer are shared across 36/37 pages (all except checkout)\n- Content sections are page-specific\n- Some sections are reused across multiple pages (FAQ on 10 pages, Rich Text on 9)\n\n### Section Reuse Strategy\n\nDesign sections to be reusable:\n\n| Section | Reuse Count | Strategy |\n|---------|-------------|----------|\n| Header | 36 pages | Single section, all navigation |\n| Footer | 36 pages | Single section, all links |\n| FAQ | 10 pages | Generic accordion, content via props |\n| Rich Text / HTML | 9 pages | Generic content block |\n| Product Detail | 1 page | Highly specialized |\n| Cart | 1 page | Highly specialized |\n\n### Component Hierarchy\n\nProduction sections have sub-components:\n\n```\nHeader Section (section)\n├── AnnouncementBar (component)\n├── NavigationBar (component)\n│ ├── Logo\n│ ├── NavLinks\n│ └── CartIcon / AccountIcon\n└── MobileMenu (component)\n\nProduct Detail Section (section)\n├── ImageGallery (component)\n├── VariantSelector (component)\n├── PriceDisplay (component)\n├── AddToCartButton (component)\n└── ProductDescription (component)\n```\n\n### Prop Design Patterns\n\nCommon prop patterns seen in production:\n\n1. **Content props**: `TEXT` for headings, descriptions, button labels\n2. **Style props**: `COLOR` for backgrounds, text colors, accents. **Every section MUST have a `backgroundColor` COLOR prop** (default `#ffffff`). Consider `textColor` for text directly on the background\n3. **Toggle props**: `BOOLEAN` for show/hide sections, features\n4. **Layout props**: `SELECT` for layout variants (grid/list, left/center/right)\n5. **Navigation props**: `LIST_OF_LINK` for editable nav menus\n6. **Data props**: `PRODUCT`, `PRODUCT_LIST`, `BLOG_LIST` for dynamic data\n7. **Media props**: `IMAGE` for logos, banners, icons\n\n### Responsive Design\n\nProduction themes target these breakpoints:\n- Desktop: 1200px+ (max-width container)\n- Tablet: 768px-1199px\n- Mobile: <768px\n\nCommon responsive patterns:\n```css\n.section { width: 100%; padding: 64px 24px; }\n.section-inner { max-width: 1200px; margin: 0 auto; }\n\n@media (max-width: 768px) {\n .section { padding: 32px 16px; }\n .grid { grid-template-columns: 1fr; }\n}\n```\n\n### Essential Sections Checklist\n\nEvery complete theme needs at minimum:\n- [ ] Header (with mobile menu)\n- [ ] Footer\n- [ ] Hero Banner / Home content\n- [ ] Product List (category page)\n- [ ] Product Detail\n- [ ] Cart\n- [ ] Login / Register / Forgot Password\n- [ ] Account (orders, addresses)\n- [ ] 404 Page\n- [ ] Contact Form (optional but common)\n- [ ] FAQ (optional but common)\n- [ ] Blog List + Blog Post (optional)",
345
351
  "tags": [
346
352
  "architecture",
347
353
  "theme",
@@ -352,6 +358,20 @@
352
358
  "responsive",
353
359
  "production"
354
360
  ]
361
+ },
362
+ "prop-groups": {
363
+ "title": "Prop Groups — Organizing Component Properties",
364
+ "description": "How to organize props into collapsible groups in the editor sidebar",
365
+ "content": "## Prop Groups\n\nProp groups organize a component's props into collapsible containers in the editor sidebar, making complex components easier to configure.\n\n### When to Use\n- Components with 5+ props\n- All section templates with multiple categories (content vs style vs data)\n- Any component where related props should be visually grouped\n\n### Config Format\n\nDefine `propGroups` on the component and assign props via `groupId`:\n\n```json\n{\n \"name\": \"HeroBanner\",\n \"type\": \"section\",\n \"props\": [\n { \"name\": \"heading\", \"type\": \"TEXT\", \"groupId\": \"content\", ... },\n { \"name\": \"subtitle\", \"type\": \"TEXT\", \"groupId\": \"content\", ... },\n { \"name\": \"bgColor\", \"type\": \"COLOR\", \"groupId\": \"style.colors\", ... },\n { \"name\": \"textColor\", \"type\": \"COLOR\", \"groupId\": \"style.colors\", ... },\n { \"name\": \"showBadge\", \"type\": \"BOOLEAN\", ... }\n ],\n \"propGroups\": [\n { \"id\": \"content\", \"name\": \"Content\", \"description\": \"Text and media\" },\n {\n \"id\": \"style\", \"name\": \"Style\",\n \"children\": [\n { \"id\": \"style.colors\", \"name\": \"Colors\" }\n ]\n }\n ]\n}\n```\n\n### Rules\n- `propGroups` and `groupId` are optional (backward-compatible)\n- Props without `groupId` appear ungrouped at root level\n- Groups can nest 1 level deep via `children`\n- Group IDs must be unique within a component (use kebab-case)\n\n### CLI Commands\n```bash\n# Create a group\nnpx ikas-component config add-prop-group --component \"Name\" --id content --name \"Content\"\n\n# Create a nested group\nnpx ikas-component config add-prop-group --component \"Name\" --id colors --name \"Colors\" --parent style\n\n# Add a prop to a group\nnpx ikas-component config add-prop --component \"Name\" --name title --displayName \"Title\" --type TEXT --group content\n\n# Move a prop to a different group\nnpx ikas-component config update-prop --component \"Name\" --prop title --group colors\n\n# Remove a group (props become ungrouped)\nnpx ikas-component config remove-prop-group --component \"Name\" --id content\n```\n\n### Common Patterns\n- Simple section: \"Content\" + \"Appearance\" groups\n- Complex section: \"Content\" + \"Style\" → (\"Colors\", \"Typography\") nested groups\n- Data-heavy section: \"Content\" + \"Data\" + \"Appearance\" groups",
366
+ "tags": [
367
+ "props",
368
+ "groups",
369
+ "organization",
370
+ "sidebar",
371
+ "config",
372
+ "propGroups",
373
+ "groupId"
374
+ ]
355
375
  }
356
376
  }
357
377
  }