@jay-framework/jay-stack-cli 0.15.4 → 0.15.6

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.
Files changed (36) hide show
  1. package/agent-kit-template/{INSTRUCTIONS.md → designer/INSTRUCTIONS.md} +11 -8
  2. package/agent-kit-template/{contracts-and-plugins.md → designer/contracts-and-plugins.md} +1 -0
  3. package/agent-kit-template/{jay-html-syntax.md → designer/jay-html-components.md} +89 -158
  4. package/agent-kit-template/designer/jay-html-styling.md +97 -0
  5. package/agent-kit-template/designer/jay-html-syntax.md +44 -0
  6. package/agent-kit-template/designer/jay-html-template-syntax.md +203 -0
  7. package/agent-kit-template/developer/INSTRUCTIONS.md +34 -0
  8. package/agent-kit-template/developer/cli-commands.md +228 -0
  9. package/agent-kit-template/developer/component-data.md +109 -0
  10. package/agent-kit-template/developer/component-refs.md +117 -0
  11. package/agent-kit-template/developer/component-state.md +140 -0
  12. package/agent-kit-template/developer/configuration.md +76 -0
  13. package/agent-kit-template/developer/page-components.md +103 -0
  14. package/agent-kit-template/developer/page-contracts.md +114 -0
  15. package/agent-kit-template/developer/project-structure.md +242 -0
  16. package/agent-kit-template/developer/render-results.md +112 -0
  17. package/agent-kit-template/developer/routing.md +161 -0
  18. package/agent-kit-template/developer/seo-guide.md +93 -0
  19. package/agent-kit-template/plugin/INSTRUCTIONS.md +40 -0
  20. package/agent-kit-template/plugin/actions-guide.md +125 -0
  21. package/agent-kit-template/plugin/component-context.md +103 -0
  22. package/agent-kit-template/plugin/component-data.md +109 -0
  23. package/agent-kit-template/plugin/component-refs.md +117 -0
  24. package/agent-kit-template/plugin/component-state.md +140 -0
  25. package/agent-kit-template/plugin/component-structure.md +174 -0
  26. package/agent-kit-template/plugin/contracts-guide.md +193 -0
  27. package/agent-kit-template/plugin/plugin-structure.md +194 -0
  28. package/agent-kit-template/plugin/render-results.md +112 -0
  29. package/agent-kit-template/plugin/seo-guide.md +93 -0
  30. package/agent-kit-template/plugin/services-guide.md +116 -0
  31. package/agent-kit-template/plugin/validation.md +101 -0
  32. package/dist/index.js +805 -61
  33. package/package.json +10 -10
  34. /package/agent-kit-template/{cli-commands.md → designer/cli-commands.md} +0 -0
  35. /package/agent-kit-template/{project-structure.md → designer/project-structure.md} +0 -0
  36. /package/agent-kit-template/{routing.md → designer/routing.md} +0 -0
@@ -0,0 +1,140 @@
1
+ # Component State Hooks
2
+
3
+ All hooks are used inside the interactive phase (the `withInteractive` constructor function). They provide reactive state management for client-side behavior.
4
+
5
+ ## createSignal
6
+
7
+ Creates a reactive getter/setter pair:
8
+
9
+ ```typescript
10
+ import { createSignal } from '@jay-framework/component';
11
+
12
+ const [count, setCount] = createSignal(0);
13
+
14
+ // Read
15
+ count(); // 0
16
+
17
+ // Write
18
+ setCount(5); // set to 5
19
+ setCount((n) => n + 1); // increment
20
+ ```
21
+
22
+ Can initialize from a getter (reactive dependency):
23
+
24
+ ```typescript
25
+ const [label, setLabel] = createSignal(() => 'Hello ' + props.name());
26
+ ```
27
+
28
+ ## createPatchableSignal
29
+
30
+ Creates a signal with JSON Patch support for fine-grained updates to complex objects:
31
+
32
+ ```typescript
33
+ import { createPatchableSignal } from '@jay-framework/component';
34
+ import { REPLACE } from '@jay-framework/json-patch';
35
+
36
+ const [data, setData, patchData] = createPatchableSignal({
37
+ label: 'Hello',
38
+ count: 0,
39
+ nested: { value: 42 },
40
+ });
41
+
42
+ // Patch a specific field
43
+ patchData({ op: REPLACE, path: ['label'], value: 'Updated' });
44
+
45
+ // Patch nested field
46
+ patchData({ op: REPLACE, path: ['nested', 'value'], value: 99 });
47
+ ```
48
+
49
+ See [component-data.md](component-data.md) for more on immutable data and patching.
50
+
51
+ ## createMemo
52
+
53
+ Creates a memoized computed value that recalculates only when dependencies change:
54
+
55
+ ```typescript
56
+ import { createMemo } from '@jay-framework/component';
57
+
58
+ const fullName = createMemo(() => `${firstName()} ${lastName()}`);
59
+
60
+ // Read
61
+ fullName(); // recomputes only when firstName() or lastName() change
62
+ ```
63
+
64
+ With initial value:
65
+
66
+ ```typescript
67
+ const total = createMemo((prev) => prev + latestValue(), 0);
68
+ ```
69
+
70
+ ## createEffect
71
+
72
+ Registers a side effect that runs on mount and when dependencies change. Optional cleanup function:
73
+
74
+ ```typescript
75
+ import { createEffect } from '@jay-framework/component';
76
+
77
+ createEffect(() => {
78
+ const handler = () => setWindowWidth(window.innerWidth);
79
+ window.addEventListener('resize', handler);
80
+ return () => window.removeEventListener('resize', handler); // cleanup
81
+ });
82
+ ```
83
+
84
+ Effects track reactive dependencies automatically:
85
+
86
+ ```typescript
87
+ createEffect(() => {
88
+ document.title = `${count()} items`; // reruns when count() changes
89
+ });
90
+ ```
91
+
92
+ ## createDerivedArray
93
+
94
+ Efficiently maps an array with smart caching. Only remaps items that actually changed:
95
+
96
+ ```typescript
97
+ import { createDerivedArray } from '@jay-framework/component';
98
+
99
+ const displayItems = createDerivedArray(
100
+ () => products(),
101
+ (item, index, length) => ({
102
+ name: item().name,
103
+ displayPrice: formatPrice(item().price),
104
+ isLast: index() === length() - 1,
105
+ }),
106
+ );
107
+
108
+ // Read the mapped array
109
+ displayItems();
110
+ ```
111
+
112
+ Key optimizations:
113
+
114
+ - Reuses mapped items when the source item hasn't changed
115
+ - Only tracks `index()` and `length()` if you actually call them
116
+ - Uses object identity (not deep equality) for cache hits
117
+
118
+ ## createEvent
119
+
120
+ Creates an event emitter for component-to-parent communication:
121
+
122
+ ```typescript
123
+ import { createEvent } from '@jay-framework/component';
124
+
125
+ const onChange = createEvent<{ value: number }>((emitter) => {
126
+ emitter.emit({ value: count() });
127
+ });
128
+ ```
129
+
130
+ ## useReactive
131
+
132
+ Gets the current reactive context for advanced use cases:
133
+
134
+ ```typescript
135
+ import { useReactive } from '@jay-framework/component';
136
+
137
+ const reactive = useReactive();
138
+ ```
139
+
140
+ Most components won't need this — prefer the higher-level hooks above.
@@ -0,0 +1,76 @@
1
+ # Configuration
2
+
3
+ ## .jay File
4
+
5
+ Optional YAML file at project root configuring the dev server:
6
+
7
+ ```yaml
8
+ devServer:
9
+ portRange:
10
+ - 3000
11
+ - 3100
12
+ pagesBase: ./src/pages
13
+ componentsBase: ./src/components
14
+ publicFolder: ./public
15
+ editorServer:
16
+ portRange:
17
+ - 3101
18
+ - 3200
19
+ ```
20
+
21
+ ### Key Fields
22
+
23
+ - `devServer.pagesBase` — Root directory for pages (default: `./src/pages`)
24
+ - `devServer.componentsBase` — Root directory for components
25
+ - `devServer.publicFolder` — Static assets directory
26
+ - `devServer.portRange` — Port range for the dev server
27
+
28
+ ## Plugin Configuration (config/)
29
+
30
+ The `config/` folder holds plugin configuration files generated by `jay-stack setup`:
31
+
32
+ ```
33
+ config/
34
+ ├── project.conf.yaml # Project name and metadata
35
+ └── wix-data.yaml # Plugin-specific config (auto-generated)
36
+ ```
37
+
38
+ Plugins create their config files here during setup. The location is configured via `configBase` in the `.jay` file (defaults to `./config`).
39
+
40
+ ## Project Init (src/init.ts)
41
+
42
+ The project can have an `init.ts` for project-level initialization:
43
+
44
+ ```typescript
45
+ import { makeJayInit, registerService } from '@jay-framework/fullstack-component';
46
+
47
+ export const init = makeJayInit()
48
+ .withServer(async () => {
49
+ // Register project-level services
50
+ registerService(MY_SERVICE, createMyService());
51
+
52
+ // Return data for client
53
+ return { locale: 'en-US' };
54
+ })
55
+ .withClient((data) => {
56
+ // Client-side init
57
+ console.log('Locale:', data.locale);
58
+ });
59
+ ```
60
+
61
+ Init runs after all plugin inits, in dependency order.
62
+
63
+ ## package.json Scripts
64
+
65
+ ```json
66
+ {
67
+ "scripts": {
68
+ "dev": "jay-stack-cli dev",
69
+ "validate": "jay-stack-cli validate",
70
+ "definitions": "jay-cli definitions src",
71
+ "build": "npm run definitions",
72
+ "setup": "jay-stack-cli setup",
73
+ "agent-kit": "jay-stack-cli agent-kit"
74
+ }
75
+ }
76
+ ```
@@ -0,0 +1,103 @@
1
+ # Page Components
2
+
3
+ A page component (`page.ts`) uses `makeJayStackComponent` to provide page-level data across rendering phases.
4
+
5
+ ## Basic Page Component
6
+
7
+ ```typescript
8
+ import { makeJayStackComponent, phaseOutput } from '@jay-framework/fullstack-component';
9
+ import type { HomePageContract } from './page.jay-contract.generated';
10
+
11
+ export const page = makeJayStackComponent<HomePageContract>()
12
+ .withSlowlyRender(async () => {
13
+ return phaseOutput({ heroTitle: 'Welcome', heroSubtitle: 'Build something great' }, {});
14
+ })
15
+ .withFastRender(async () => {
16
+ return phaseOutput({ featuredCount: 12 }, {});
17
+ });
18
+ ```
19
+
20
+ The export name must be `page` for page-level components.
21
+
22
+ ## Page Component with Params
23
+
24
+ For dynamic routes, use `withLoadParams` and access params via props:
25
+
26
+ ```typescript
27
+ export const page = makeJayStackComponent<ProductPageContract>()
28
+ .withServices(PRODUCTS_DB)
29
+ .withLoadParams(async function* (db) {
30
+ const products = await db.getAll();
31
+ yield products.map((p) => ({ slug: p.slug }));
32
+ })
33
+ .withSlowlyRender(async (props, db) => {
34
+ const product = await db.getBySlug(props.slug);
35
+ if (!product) return notFound('Product not found');
36
+ return phaseOutput(
37
+ { title: product.name, description: product.desc },
38
+ { productId: product.id },
39
+ );
40
+ })
41
+ .withFastRender(async (props, db) => {
42
+ const price = await db.getPrice(props.carryForward.productId);
43
+ return phaseOutput({ price, inStock: price > 0 }, {});
44
+ });
45
+ ```
46
+
47
+ ## Page Component with Interactive Phase
48
+
49
+ Add client-side interactivity:
50
+
51
+ ```typescript
52
+ export const page = makeJayStackComponent<ProductPageContract>()
53
+ .withServices(PRODUCTS_DB)
54
+ .withSlowlyRender(async (props, db) => {
55
+ // ... slow render
56
+ })
57
+ .withFastRender(async (props, db) => {
58
+ // ... fast render
59
+ })
60
+ .withInteractive(function ProductPage(props, refs) {
61
+ const [quantity, setQuantity] = createSignal(1);
62
+
63
+ refs.addToCart.onClick(async () => {
64
+ await addToCartAction({
65
+ productId: props.carryForward.productId,
66
+ quantity: quantity(),
67
+ });
68
+ });
69
+
70
+ refs.quantityInput.exec$((input) => {
71
+ input.addEventListener('change', (e) => {
72
+ setQuantity(parseInt((e.target as HTMLInputElement).value));
73
+ });
74
+ });
75
+
76
+ return {
77
+ render: () => ({
78
+ quantity: quantity(),
79
+ }),
80
+ };
81
+ });
82
+ ```
83
+
84
+ ## Combining with Headless Plugins
85
+
86
+ A page component handles page-level data. Plugin headless components handle their own data independently. Both render into the same page:
87
+
88
+ ```
89
+ src/pages/products/[slug]/
90
+ ├── page.jay-html # Template: binds to both page + plugin data
91
+ ├── page.jay-contract # Page-level contract (title, breadcrumbs, etc.)
92
+ ├── page.ts # Page component
93
+ ```
94
+
95
+ The jay-html template uses unprefixed bindings for page data and key-prefixed bindings for plugin data.
96
+
97
+ ## Builder API Reference
98
+
99
+ See the plugin [component-structure.md](../plugin/component-structure.md) for the full builder API: `.withProps()`, `.withServices()`, `.withContexts()`, phase rendering, and render results.
100
+
101
+ ## State Hooks Reference
102
+
103
+ See [component-state.md](component-state.md) for `createSignal`, `createMemo`, `createEffect`, and other hooks used in the interactive phase.
@@ -0,0 +1,114 @@
1
+ # Page Contracts
2
+
3
+ A page can have its own contract (`page.jay-contract`) defining page-level data, alongside headless plugin contracts.
4
+
5
+ ## When to Use a Page Contract
6
+
7
+ - The page has its own data that isn't provided by a plugin
8
+ - The page component (`page.ts`) renders data into ViewState
9
+ - You want type-safe bindings between the page component and its jay-html template
10
+
11
+ If the page only uses plugin headless components and has no page-level data, a page contract is optional.
12
+
13
+ ## Basic Page Contract
14
+
15
+ ```yaml
16
+ name: home-page
17
+ tags:
18
+ - tag: heroTitle
19
+ type: data
20
+ dataType: string
21
+ phase: slow
22
+ - tag: heroSubtitle
23
+ type: data
24
+ dataType: string
25
+ phase: slow
26
+ - tag: featuredCount
27
+ type: data
28
+ dataType: number
29
+ phase: fast
30
+ ```
31
+
32
+ Place as `page.jay-contract` next to `page.jay-html`:
33
+
34
+ ```
35
+ src/pages/
36
+ ├── page.jay-html
37
+ ├── page.jay-contract
38
+ └── page.ts
39
+ ```
40
+
41
+ ## Page Contract with Params
42
+
43
+ If the page has a dynamic route, declare `params` in the contract:
44
+
45
+ ```yaml
46
+ name: product-page
47
+ description: Product detail page
48
+ params:
49
+ slug: string
50
+ tags:
51
+ - tag: title
52
+ type: data
53
+ dataType: string
54
+ phase: slow
55
+ - tag: price
56
+ type: data
57
+ dataType: number
58
+ phase: fast+interactive
59
+ ```
60
+
61
+ The route must have matching dynamic segments:
62
+
63
+ ```
64
+ src/pages/products/[slug]/
65
+ ├── page.jay-html
66
+ ├── page.jay-contract
67
+ └── page.ts
68
+ ```
69
+
70
+ ## Page Contract with Props
71
+
72
+ Pages rarely use props (they're top-level), but page contracts can declare them for reusable page patterns:
73
+
74
+ ```yaml
75
+ name: category-page
76
+ props:
77
+ - name: categoryId
78
+ type: string
79
+ required: true
80
+ tags:
81
+ - tag: categoryName
82
+ type: data
83
+ dataType: string
84
+ ```
85
+
86
+ ## Combining with Plugin Contracts
87
+
88
+ A page can have both a page contract and headless plugin contracts. The page contract covers page-owned data; plugins cover their own domains:
89
+
90
+ ```html
91
+ <!-- page.jay-html -->
92
+ <html>
93
+ <head>
94
+ <script
95
+ type="application/jay-headless"
96
+ plugin="wix-stores"
97
+ contract="product-page"
98
+ key="product"
99
+ ></script>
100
+ </head>
101
+ <body>
102
+ <!-- Page contract data -->
103
+ <h1>{heroTitle}</h1>
104
+
105
+ <!-- Plugin contract data (prefixed with key) -->
106
+ <div>{product.name}</div>
107
+ <div>{product.price}</div>
108
+ </body>
109
+ </html>
110
+ ```
111
+
112
+ ## Contract Format Reference
113
+
114
+ See the plugin [contracts-guide.md](../plugin/contracts-guide.md) for the full contract format: tag types, phases, sub-contracts, async data, and validation rules.
@@ -0,0 +1,242 @@
1
+ # Project Structure
2
+
3
+ ## Directory Layout
4
+
5
+ A jay-stack project follows this structure:
6
+
7
+ ```
8
+ my-project/
9
+ ├── .jay # Dev server configuration (optional)
10
+ ├── package.json # Dependencies and scripts
11
+ ├── tsconfig.json # TypeScript config
12
+ ├── public/ # Static assets (images, fonts, etc.)
13
+ ├── config/ # Plugin configuration (generated by jay-stack setup)
14
+ │ ├── project.conf.yaml # Project metadata (name, etc.)
15
+ │ └── <plugin-name>.yaml # Plugin-specific config files
16
+ ├── src/
17
+ │ ├── pages/ # Pages (directory-based routing)
18
+ │ │ ├── page.jay-html # Homepage → /
19
+ │ │ ├── page.jay-contract # Homepage contract (optional)
20
+ │ │ ├── products/
21
+ │ │ │ ├── page.jay-html # Products list → /products
22
+ │ │ │ └── [slug]/
23
+ │ │ │ └── page.jay-html # Product detail → /products/:slug
24
+ │ │ └── cart/
25
+ │ │ └── page.jay-html # Cart → /cart
26
+ │ └── styles/
27
+ │ └── theme.css # Global theme stylesheet
28
+ └── agent-kit/ # Generated by jay-stack agent-kit
29
+ ├── INSTRUCTIONS.md
30
+ ├── materialized-contracts/ # Contracts and indexes
31
+ └── references/ # Plugin reference data (product catalogs, schemas)
32
+ └── <plugin-name>/ # Per-plugin discovery data
33
+ ```
34
+
35
+ ## What You Create
36
+
37
+ As an agent building pages, you typically create:
38
+
39
+ 1. **`src/pages/**/\*.jay-html`\*\* — Page templates (the main output)
40
+ 2. **`src/pages/**/\*.jay-contract`\*\* — Page-level contracts (when the page has its own data)
41
+ 3. **`src/styles/*.css`** — Theme stylesheet (one per project, reused across pages)
42
+
43
+ You do **not** need to create: `package.json`, `tsconfig.json`, `.jay`, `page.conf.yaml`, `src/init.ts`, server actions, or services — these are set up by the project scaffolding, the Figma plugin, or provided by plugins.
44
+
45
+ ## Styling
46
+
47
+ ### Global Theme (src/styles/)
48
+
49
+ Each project has a theme CSS file in `src/styles/` with CSS custom properties (design tokens):
50
+
51
+ ```css
52
+ :root {
53
+ /* Colors */
54
+ --bg-primary: #faf8f5;
55
+ --bg-card: #ffffff;
56
+ --text-primary: #2d2a26;
57
+ --text-secondary: #6b665e;
58
+ --accent: #c45c3e;
59
+ --accent-hover: #d4704f;
60
+ --border: #e8e4dd;
61
+
62
+ /* Typography */
63
+ --font-serif: 'Cormorant Garamond', Georgia, serif;
64
+ --font-sans: 'DM Sans', -apple-system, sans-serif;
65
+
66
+ /* Spacing & Layout */
67
+ --radius-md: 10px;
68
+ --radius-lg: 14px;
69
+ --container-max: 1400px;
70
+ --page-padding: 48px;
71
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.04);
72
+ --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.06);
73
+ }
74
+ ```
75
+
76
+ The theme provides reusable CSS classes for common UI patterns:
77
+
78
+ - **Layout**: `.container`, `.container-narrow`
79
+ - **Cards**: `.card`, `.card-elevated`
80
+ - **Buttons**: `.btn`, `.btn-primary`, `.btn-secondary`, `.btn-ghost`, `.btn-sm`, `.btn-lg`
81
+ - **Forms**: `.input`, `.select`, `.checkbox`
82
+ - **Badges**: `.badge`, `.badge-accent`, `.badge-success`, `.badge-error`
83
+ - **Typography**: `.page-title`, `.section-title`, `.label`
84
+ - **Product components**: `.product-card`, `.product-card-image`, `.product-card-content`, `.product-card-price`
85
+
86
+ ### Linking the Theme from Pages
87
+
88
+ Use a relative path from the page to the theme file:
89
+
90
+ ```html
91
+ <!-- From src/pages/page.jay-html (depth 1) -->
92
+ <link rel="stylesheet" href="../styles/theme.css" />
93
+
94
+ <!-- From src/pages/products/page.jay-html (depth 2) -->
95
+ <link rel="stylesheet" href="../../styles/theme.css" />
96
+
97
+ <!-- From src/pages/products/[slug]/page.jay-html (depth 3) -->
98
+ <link rel="stylesheet" href="../../../styles/theme.css" />
99
+ ```
100
+
101
+ ### Page-Specific Styles
102
+
103
+ Add page-specific styles in `<style>` tags within the jay-html `<head>`:
104
+
105
+ ```html
106
+ <head>
107
+ <link rel="stylesheet" href="../../styles/theme.css" />
108
+ <style>
109
+ .hero {
110
+ padding: 80px 0;
111
+ text-align: center;
112
+ }
113
+ .featured-grid {
114
+ display: grid;
115
+ grid-template-columns: repeat(3, 1fr);
116
+ gap: 24px;
117
+ }
118
+ </style>
119
+ </head>
120
+ ```
121
+
122
+ ### External Fonts
123
+
124
+ Import fonts in the theme CSS or via `<link>` in jay-html:
125
+
126
+ ```css
127
+ /* In theme.css */
128
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
129
+ ```
130
+
131
+ ### Responsive Design
132
+
133
+ Use media queries in the theme CSS or page-specific styles:
134
+
135
+ ```css
136
+ @media (max-width: 1024px) {
137
+ .product-page-layout {
138
+ grid-template-columns: 1fr;
139
+ }
140
+ }
141
+ @media (max-width: 768px) {
142
+ .products-grid {
143
+ grid-template-columns: 1fr;
144
+ }
145
+ }
146
+ ```
147
+
148
+ ## Configuration Files
149
+
150
+ ### config/ (Plugin Configuration)
151
+
152
+ The `config/` folder holds plugin configuration files, typically generated by `jay-stack setup`:
153
+
154
+ ```
155
+ config/
156
+ ├── project.conf.yaml # Project name and metadata
157
+ └── wix-data.yaml # Plugin-specific config (auto-generated by setup)
158
+ ```
159
+
160
+ Plugins create their config files here during setup. The location is configured via `configBase` in the `.jay` file (defaults to `./config`).
161
+
162
+ You generally don't need to create files here manually — plugins handle this via `jay-stack setup`. However, you may need to read these files to understand how a plugin is configured.
163
+
164
+ ### .jay (Dev Server Config)
165
+
166
+ Optional YAML file at project root:
167
+
168
+ ```yaml
169
+ devServer:
170
+ portRange:
171
+ - 3000
172
+ - 3100
173
+ pagesBase: ./src/pages
174
+ componentsBase: ./src/components
175
+ publicFolder: ./public
176
+ editorServer:
177
+ portRange:
178
+ - 3101
179
+ - 3200
180
+ ```
181
+
182
+ ### package.json (Scripts)
183
+
184
+ Standard scripts for jay-stack projects:
185
+
186
+ ```json
187
+ {
188
+ "scripts": {
189
+ "dev": "jay-stack-cli dev",
190
+ "validate": "jay-stack-cli validate",
191
+ "definitions": "jay-cli definitions src",
192
+ "build": "npm run definitions"
193
+ }
194
+ }
195
+ ```
196
+
197
+ ## Common Page Patterns
198
+
199
+ ### Product List / Search Page
200
+
201
+ Uses a product search contract with filters, sorting, and pagination:
202
+
203
+ ```
204
+ src/pages/products/
205
+ └── page.jay-html # Search input, filters sidebar, product grid, load more
206
+ ```
207
+
208
+ ### Product Detail Page (Dynamic Route)
209
+
210
+ Uses a product page contract with media gallery, options, and add-to-cart:
211
+
212
+ ```
213
+ src/pages/products/[slug]/
214
+ └── page.jay-html # Gallery, options, quantity, actions
215
+ ```
216
+
217
+ ### Category Page
218
+
219
+ Uses a category contract with product grid:
220
+
221
+ ```
222
+ src/pages/categories/[slug]/
223
+ └── page.jay-html # Category hero, product grid, load more
224
+ ```
225
+
226
+ ### Cart Page
227
+
228
+ Uses a cart contract with line items and checkout:
229
+
230
+ ```
231
+ src/pages/cart/
232
+ └── page.jay-html # Line items, quantity controls, summary, coupon, checkout
233
+ ```
234
+
235
+ ### Homepage
236
+
237
+ Combines multiple headless components:
238
+
239
+ ```
240
+ src/pages/
241
+ └── page.jay-html # Hero, featured products, categories, etc.
242
+ ```