@decocms/start 0.19.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.
Files changed (185) hide show
  1. package/.cursor/skills/deco-api-call-dedup/SKILL.md +443 -0
  2. package/.cursor/skills/deco-apps-architecture/SKILL.md +255 -0
  3. package/.cursor/skills/deco-apps-architecture/app-pattern.md +288 -0
  4. package/.cursor/skills/deco-apps-architecture/commerce-types.md +239 -0
  5. package/.cursor/skills/deco-apps-architecture/new-app-guide.md +268 -0
  6. package/.cursor/skills/deco-apps-architecture/scripts-codegen.md +148 -0
  7. package/.cursor/skills/deco-apps-architecture/shared-utils.md +181 -0
  8. package/.cursor/skills/deco-apps-architecture/vtex-deep-structure.md +253 -0
  9. package/.cursor/skills/deco-apps-architecture/website-app.md +169 -0
  10. package/.cursor/skills/deco-apps-vtex-porting/SKILL.md +189 -0
  11. package/.cursor/skills/deco-apps-vtex-porting/adaptation-patterns.md +335 -0
  12. package/.cursor/skills/deco-apps-vtex-porting/commerce-porting.md +155 -0
  13. package/.cursor/skills/deco-apps-vtex-porting/cookie-auth-patterns.md +148 -0
  14. package/.cursor/skills/deco-apps-vtex-porting/structure-map.md +234 -0
  15. package/.cursor/skills/deco-apps-vtex-porting/transform-mapping.md +99 -0
  16. package/.cursor/skills/deco-apps-vtex-porting/website-porting.md +194 -0
  17. package/.cursor/skills/deco-apps-vtex-review/SKILL.md +234 -0
  18. package/.cursor/skills/deco-async-rendering-architecture/SKILL.md +270 -0
  19. package/.cursor/skills/deco-async-rendering-site-guide/SKILL.md +417 -0
  20. package/.cursor/skills/deco-cms-layout-caching/SKILL.md +293 -0
  21. package/.cursor/skills/deco-cms-route-config/SKILL.md +388 -0
  22. package/.cursor/skills/deco-core-architecture/SKILL.md +185 -0
  23. package/.cursor/skills/deco-core-architecture/blocks.md +196 -0
  24. package/.cursor/skills/deco-core-architecture/deco-vs-deco-start.md +191 -0
  25. package/.cursor/skills/deco-core-architecture/engine.md +220 -0
  26. package/.cursor/skills/deco-core-architecture/hooks-components.md +157 -0
  27. package/.cursor/skills/deco-core-architecture/plugins-clients.md +136 -0
  28. package/.cursor/skills/deco-core-architecture/runtime.md +116 -0
  29. package/.cursor/skills/deco-core-architecture/site-usage.md +165 -0
  30. package/.cursor/skills/deco-e2e-testing/SKILL.md +372 -0
  31. package/.cursor/skills/deco-e2e-testing/discovery.md +337 -0
  32. package/.cursor/skills/deco-e2e-testing/scripts/scaffold.sh +81 -0
  33. package/.cursor/skills/deco-e2e-testing/selectors.md +175 -0
  34. package/.cursor/skills/deco-e2e-testing/templates/package.json +18 -0
  35. package/.cursor/skills/deco-e2e-testing/templates/playwright.config.ts +65 -0
  36. package/.cursor/skills/deco-e2e-testing/templates/scripts/baseline.ts +279 -0
  37. package/.cursor/skills/deco-e2e-testing/templates/scripts/run-e2e.ts +194 -0
  38. package/.cursor/skills/deco-e2e-testing/templates/specs/ecommerce-flow.spec.ts +612 -0
  39. package/.cursor/skills/deco-e2e-testing/templates/tsconfig.json +12 -0
  40. package/.cursor/skills/deco-e2e-testing/templates/utils/metrics-collector.ts +918 -0
  41. package/.cursor/skills/deco-e2e-testing/troubleshooting.md +602 -0
  42. package/.cursor/skills/deco-edge-caching/SKILL.md +316 -0
  43. package/.cursor/skills/deco-full-analysis/SKILL.md +898 -0
  44. package/.cursor/skills/deco-full-analysis/checklists/asset-optimization.md +251 -0
  45. package/.cursor/skills/deco-full-analysis/checklists/bug-fix.md +189 -0
  46. package/.cursor/skills/deco-full-analysis/checklists/cache-strategy.md +144 -0
  47. package/.cursor/skills/deco-full-analysis/checklists/dependency-update.md +150 -0
  48. package/.cursor/skills/deco-full-analysis/checklists/hydration-fix.md +191 -0
  49. package/.cursor/skills/deco-full-analysis/checklists/image-optimization.md +180 -0
  50. package/.cursor/skills/deco-full-analysis/checklists/loader-optimization.md +165 -0
  51. package/.cursor/skills/deco-full-analysis/checklists/seo-fix.md +183 -0
  52. package/.cursor/skills/deco-full-analysis/checklists/site-cleanup.md +281 -0
  53. package/.cursor/skills/deco-full-analysis/discovery.md +548 -0
  54. package/.cursor/skills/deco-incident-debugging/SKILL.md +378 -0
  55. package/.cursor/skills/deco-incident-debugging/headless-mode.md +510 -0
  56. package/.cursor/skills/deco-incident-debugging/learnings-index.md +227 -0
  57. package/.cursor/skills/deco-incident-debugging/triage-workflow.md +312 -0
  58. package/.cursor/skills/deco-islands-migration/SKILL.md +251 -0
  59. package/.cursor/skills/deco-loader-n-plus-1-detector/SKILL.md +275 -0
  60. package/.cursor/skills/deco-performance-audit/SKILL.md +530 -0
  61. package/.cursor/skills/deco-performance-audit/tools-reference.md +428 -0
  62. package/.cursor/skills/deco-performance-audit/workflow.md +457 -0
  63. package/.cursor/skills/deco-server-functions-invoke/SKILL.md +92 -0
  64. package/.cursor/skills/deco-server-functions-invoke/architecture.md +166 -0
  65. package/.cursor/skills/deco-server-functions-invoke/generator.md +122 -0
  66. package/.cursor/skills/deco-server-functions-invoke/problem.md +98 -0
  67. package/.cursor/skills/deco-server-functions-invoke/troubleshooting.md +110 -0
  68. package/.cursor/skills/deco-site-deployment/SKILL.md +396 -0
  69. package/.cursor/skills/deco-site-memory-debugging/SKILL.md +121 -0
  70. package/.cursor/skills/deco-site-memory-debugging/cdp-connection.md +222 -0
  71. package/.cursor/skills/deco-site-memory-debugging/memory-analysis.md +362 -0
  72. package/.cursor/skills/deco-site-patterns/SKILL.md +124 -0
  73. package/.cursor/skills/deco-site-patterns/app-composition.md +337 -0
  74. package/.cursor/skills/deco-site-patterns/client-patterns.md +341 -0
  75. package/.cursor/skills/deco-site-patterns/cms-wiring.md +230 -0
  76. package/.cursor/skills/deco-site-patterns/section-patterns.md +340 -0
  77. package/.cursor/skills/deco-site-scaling-tuning/SKILL.md +240 -0
  78. package/.cursor/skills/deco-site-scaling-tuning/analysis-scripts.md +267 -0
  79. package/.cursor/skills/deco-start-architecture/SKILL.md +218 -0
  80. package/.cursor/skills/deco-start-architecture/admin-protocol.md +156 -0
  81. package/.cursor/skills/deco-start-architecture/cms-resolution.md +201 -0
  82. package/.cursor/skills/deco-start-architecture/code-quality.md +158 -0
  83. package/.cursor/skills/deco-start-architecture/gap-analysis.md +129 -0
  84. package/.cursor/skills/deco-start-architecture/sdk-utilities.md +197 -0
  85. package/.cursor/skills/deco-start-architecture/worker-entry-caching.md +154 -0
  86. package/.cursor/skills/deco-startup-analysis/SKILL.md +248 -0
  87. package/.cursor/skills/deco-storefront-test-checklist/SKILL.md +369 -0
  88. package/.cursor/skills/deco-tanstack-hydration-fixes/SKILL.md +468 -0
  89. package/.cursor/skills/deco-tanstack-navigation/SKILL.md +681 -0
  90. package/.cursor/skills/deco-tanstack-search/SKILL.md +411 -0
  91. package/.cursor/skills/deco-tanstack-storefront-patterns/SKILL.md +1013 -0
  92. package/.cursor/skills/deco-to-tanstack-migration/SKILL.md +518 -0
  93. package/.cursor/skills/deco-to-tanstack-migration/references/codemod-commands.md +174 -0
  94. package/.cursor/skills/deco-to-tanstack-migration/references/commerce/README.md +78 -0
  95. package/.cursor/skills/deco-to-tanstack-migration/references/deco-framework/README.md +128 -0
  96. package/.cursor/skills/deco-to-tanstack-migration/references/gotchas.md +719 -0
  97. package/.cursor/skills/deco-to-tanstack-migration/references/imports/README.md +70 -0
  98. package/.cursor/skills/deco-to-tanstack-migration/references/platform-hooks/README.md +154 -0
  99. package/.cursor/skills/deco-to-tanstack-migration/references/signals/README.md +220 -0
  100. package/.cursor/skills/deco-to-tanstack-migration/references/vite-config/README.md +78 -0
  101. package/.cursor/skills/deco-to-tanstack-migration/templates/package-json.md +55 -0
  102. package/.cursor/skills/deco-to-tanstack-migration/templates/root-route.md +110 -0
  103. package/.cursor/skills/deco-to-tanstack-migration/templates/router.md +96 -0
  104. package/.cursor/skills/deco-to-tanstack-migration/templates/setup-ts.md +167 -0
  105. package/.cursor/skills/deco-to-tanstack-migration/templates/vite-config.md +122 -0
  106. package/.cursor/skills/deco-to-tanstack-migration/templates/worker-entry.md +67 -0
  107. package/.cursor/skills/deco-typescript-fixes/SKILL.md +178 -0
  108. package/.cursor/skills/deco-typescript-fixes/common-fixes.md +330 -0
  109. package/.cursor/skills/deco-typescript-fixes/strategy.md +148 -0
  110. package/.cursor/skills/deco-variant-selection-perf/SKILL.md +272 -0
  111. package/.cursor/skills/deco-vtex-fetch-cache/SKILL.md +225 -0
  112. package/.cursor/skills/find-skills/SKILL.md +133 -0
  113. package/.cursor/skills/incident-report/SKILL.md +179 -0
  114. package/.cursor/skills/incident-report/references/5-whys.md +75 -0
  115. package/.cursor/skills/incident-report/templates/client-report.md +187 -0
  116. package/.cursor/skills/incident-report/templates/internal-report.md +206 -0
  117. package/.cursor/skills/template-skill/SKILL.md +38 -0
  118. package/.github/workflows/release.yml +32 -0
  119. package/.releaserc.json +25 -0
  120. package/CLAUDE.md +135 -0
  121. package/GAP_ANALYSIS.md +224 -0
  122. package/GAP_ANALYSIS_V2.md +1013 -0
  123. package/biome.json +39 -0
  124. package/knip.json +5 -0
  125. package/package.json +87 -0
  126. package/scripts/generate-blocks.ts +69 -0
  127. package/scripts/generate-invoke.ts +378 -0
  128. package/scripts/generate-schema.ts +657 -0
  129. package/src/admin/cors.ts +29 -0
  130. package/src/admin/decofile.ts +72 -0
  131. package/src/admin/index.ts +24 -0
  132. package/src/admin/invoke.ts +163 -0
  133. package/src/admin/liveControls.ts +29 -0
  134. package/src/admin/meta.ts +70 -0
  135. package/src/admin/render.ts +205 -0
  136. package/src/admin/schema.ts +686 -0
  137. package/src/admin/setup.ts +44 -0
  138. package/src/cms/index.ts +59 -0
  139. package/src/cms/loader.ts +180 -0
  140. package/src/cms/registry.ts +162 -0
  141. package/src/cms/resolve.ts +1005 -0
  142. package/src/cms/sectionLoaders.ts +294 -0
  143. package/src/hooks/DecoPageRenderer.tsx +444 -0
  144. package/src/hooks/LazySection.tsx +109 -0
  145. package/src/hooks/LiveControls.tsx +108 -0
  146. package/src/hooks/SectionErrorFallback.tsx +85 -0
  147. package/src/hooks/index.ts +8 -0
  148. package/src/index.ts +5 -0
  149. package/src/matchers/builtins.ts +184 -0
  150. package/src/matchers/posthog.ts +154 -0
  151. package/src/middleware/decoState.ts +55 -0
  152. package/src/middleware/healthMetrics.ts +131 -0
  153. package/src/middleware/index.ts +80 -0
  154. package/src/middleware/liveness.ts +21 -0
  155. package/src/middleware/observability.ts +205 -0
  156. package/src/routes/adminRoutes.ts +83 -0
  157. package/src/routes/cmsRoute.ts +302 -0
  158. package/src/routes/components.tsx +34 -0
  159. package/src/routes/index.ts +15 -0
  160. package/src/sdk/analytics.ts +72 -0
  161. package/src/sdk/cacheHeaders.ts +268 -0
  162. package/src/sdk/cachedLoader.ts +206 -0
  163. package/src/sdk/clx.ts +3 -0
  164. package/src/sdk/cookie.ts +39 -0
  165. package/src/sdk/createInvoke.ts +57 -0
  166. package/src/sdk/csp.ts +59 -0
  167. package/src/sdk/env.ts +27 -0
  168. package/src/sdk/index.ts +63 -0
  169. package/src/sdk/instrumentedFetch.ts +137 -0
  170. package/src/sdk/invoke.ts +133 -0
  171. package/src/sdk/mergeCacheControl.ts +150 -0
  172. package/src/sdk/redirects.ts +217 -0
  173. package/src/sdk/requestContext.ts +184 -0
  174. package/src/sdk/serverTimings.ts +68 -0
  175. package/src/sdk/signal.ts +41 -0
  176. package/src/sdk/sitemap.ts +143 -0
  177. package/src/sdk/urlUtils.ts +117 -0
  178. package/src/sdk/useDevice.ts +82 -0
  179. package/src/sdk/useId.ts +7 -0
  180. package/src/sdk/useScript.ts +101 -0
  181. package/src/sdk/workerEntry.ts +703 -0
  182. package/src/sdk/wrapCaughtErrors.ts +107 -0
  183. package/src/types/index.ts +39 -0
  184. package/src/types/widgets.ts +13 -0
  185. package/tsconfig.json +13 -0
@@ -0,0 +1,288 @@
1
+ # The Deco App Pattern
2
+
3
+ Every Deco app follows the same structural pattern. This document describes each component.
4
+
5
+ ## Directory Layout
6
+
7
+ ```
8
+ {app-name}/
9
+ ├── mod.ts # App factory function
10
+ ├── manifest.gen.ts # Auto-generated block registry
11
+ ├── runtime.ts # Client-side invoke proxy
12
+ ├── middleware.ts # Per-request middleware (optional)
13
+ ├── actions/ # Server-side mutations
14
+ ├── loaders/ # Server-side data fetching
15
+ ├── hooks/ # Client-side hooks (Preact signals)
16
+ │ └── context.ts # Shared reactive state
17
+ ├── sections/ # CMS-editable UI sections
18
+ ├── handlers/ # HTTP request handlers
19
+ ├── components/ # Shared components
20
+ ├── utils/ # Internal utilities
21
+ │ ├── types.ts # API types
22
+ │ ├── client.ts # Typed HTTP client interface
23
+ │ └── transform.ts # API → schema.org mapping
24
+ ├── workflows/ # Background jobs
25
+ └── preview/ # Admin preview UI
26
+ ```
27
+
28
+ ## `mod.ts` — App Factory
29
+
30
+ The entry point. Exports a function that receives `Props` and returns an `App`.
31
+
32
+ ```typescript
33
+ import manifest, { Manifest } from "./manifest.gen.ts";
34
+ import { middleware } from "./middleware.ts";
35
+ import { type App, type AppContext as AC } from "@deco/deco";
36
+
37
+ export type AppContext = AC<ReturnType<typeof MyApp>>;
38
+
39
+ export interface Props {
40
+ account: string;
41
+ apiKey?: Secret;
42
+ salesChannel?: string;
43
+ platform: "myplatform";
44
+ }
45
+
46
+ export default function MyApp(props: Props) {
47
+ // Create typed HTTP clients
48
+ const api = createHttpClient<MyAPI>({ base: `https://${props.account}.api.com` });
49
+ const gql = createGraphqlClient({ endpoint: `https://${props.account}.api.com/graphql` });
50
+
51
+ const state = { ...props, api, gql };
52
+
53
+ const app: App<Manifest, typeof state> = {
54
+ state,
55
+ manifest,
56
+ middleware, // Optional
57
+ dependencies: [], // Other apps this depends on
58
+ };
59
+
60
+ return app;
61
+ }
62
+ ```
63
+
64
+ ### Key Concepts:
65
+ - **`state`** is available to all loaders/actions via `ctx` (AppContext)
66
+ - **`manifest`** registers all blocks (auto-generated)
67
+ - **`middleware`** runs before every request
68
+ - **`dependencies`** compose other apps (e.g., `website`, `workflows`)
69
+
70
+ ## `manifest.gen.ts` — Block Registry
71
+
72
+ Auto-generated by `deno task start`. Registers all discoverable blocks:
73
+
74
+ ```typescript
75
+ // DO NOT EDIT
76
+ import * as $$$0 from "./actions/cart/addItems.ts";
77
+ import * as $$$1 from "./loaders/productDetailsPage.ts";
78
+ import * as $$$$0 from "./sections/Analytics/Vtex.tsx";
79
+
80
+ const manifest = {
81
+ "actions": { "myapp/actions/cart/addItems.ts": $$$0 },
82
+ "loaders": { "myapp/loaders/productDetailsPage.ts": $$$1 },
83
+ "sections": { "myapp/sections/Analytics/Vtex.tsx": $$$$0 },
84
+ "name": "myapp",
85
+ "baseUrl": import.meta.url,
86
+ };
87
+ export type Manifest = typeof manifest;
88
+ export default manifest;
89
+ ```
90
+
91
+ ## `runtime.ts` — Client Invoke Proxy
92
+
93
+ Provides typed client-side invocations:
94
+
95
+ ```typescript
96
+ import { Manifest } from "./manifest.gen.ts";
97
+ import { proxy } from "@deco/deco/web";
98
+ export const invoke = proxy<Manifest>();
99
+
100
+ // Usage (client-side):
101
+ const cart = await invoke.myapp.loaders.cart();
102
+ const result = await invoke.myapp.actions.cart.addItems({ items: [...] });
103
+ ```
104
+
105
+ ## Actions Pattern
106
+
107
+ Server-side write operations. Each action is a single function:
108
+
109
+ ```typescript
110
+ // actions/cart/addItems.ts
111
+ import { AppContext } from "../../mod.ts";
112
+
113
+ export interface Props {
114
+ items: Array<{ id: string; quantity: number; seller: string }>;
115
+ }
116
+
117
+ const action = async (props: Props, req: Request, ctx: AppContext): Promise<OrderForm> => {
118
+ const { vcsDeprecated } = ctx;
119
+ // ... call VTEX API
120
+ return orderForm;
121
+ };
122
+
123
+ export default action;
124
+ ```
125
+
126
+ ### Action conventions:
127
+ - Receives `(props, req, ctx)` — Props are CMS-configurable
128
+ - Returns the modified resource
129
+ - Placed in `actions/{domain}/{operation}.ts`
130
+ - Cart actions return `OrderForm`
131
+ - Auth actions return `AuthResponse`
132
+
133
+ ## Loaders Pattern
134
+
135
+ Server-side read operations:
136
+
137
+ ```typescript
138
+ // loaders/productDetailsPage.ts
139
+ import { AppContext } from "../mod.ts";
140
+ import { ProductDetailsPage } from "../../commerce/types.ts";
141
+
142
+ export interface Props {
143
+ slug: string;
144
+ }
145
+
146
+ const loader = async (props: Props, req: Request, ctx: AppContext): Promise<ProductDetailsPage | null> => {
147
+ // Fetch from API, transform to schema.org
148
+ return { "@type": "ProductDetailsPage", product, breadcrumbList, seo };
149
+ };
150
+
151
+ export default loader;
152
+ ```
153
+
154
+ ### Loader conventions:
155
+ - Receives `(props, req, ctx)`
156
+ - Returns `null` for 404 cases
157
+ - Commerce loaders return `schema.org` types
158
+ - Placed in `loaders/{domain}/{operation}.ts`
159
+
160
+ ## Hooks Pattern (Preact/Signals)
161
+
162
+ Client-side reactive state using `@preact/signals`:
163
+
164
+ ### `context.ts` — Central State
165
+
166
+ ```typescript
167
+ import { IS_BROWSER } from "$fresh/runtime.ts";
168
+ import { signal } from "@preact/signals";
169
+ import { invoke } from "../runtime.ts";
170
+
171
+ const loading = signal<boolean>(true);
172
+ const context = {
173
+ cart: IS_BROWSER ? signal<OrderForm | null>(null) : { value: null },
174
+ user: IS_BROWSER ? signal<Person | null>(null) : { value: null },
175
+ };
176
+
177
+ // Serial queue with abort support
178
+ let queue = Promise.resolve();
179
+ let abort = () => {};
180
+ const enqueue = (cb: (signal: AbortSignal) => Promise<Partial<Context>>) => {
181
+ abort();
182
+ loading.value = true;
183
+ const controller = new AbortController();
184
+ queue = queue.then(async () => {
185
+ const result = await cb(controller.signal);
186
+ context.cart.value = result.cart || context.cart.value;
187
+ loading.value = false;
188
+ });
189
+ abort = () => controller.abort();
190
+ return queue;
191
+ };
192
+
193
+ // Initial load
194
+ if (IS_BROWSER) {
195
+ enqueue((signal) => invoke({ cart: invoke.myapp.loaders.cart() }, { signal }));
196
+ }
197
+
198
+ export const state = { ...context, loading, enqueue };
199
+ ```
200
+
201
+ ### `useCart.ts` — Domain Hook
202
+
203
+ ```typescript
204
+ import { state as storeState } from "./context.ts";
205
+ import { invoke } from "../runtime.ts";
206
+
207
+ const { cart, loading } = storeState;
208
+
209
+ const enqueue = (key) => (props) =>
210
+ storeState.enqueue((signal) =>
211
+ invoke({ cart: { key, props } }, { signal })
212
+ );
213
+
214
+ const state = {
215
+ cart,
216
+ loading,
217
+ addItems: enqueue("myapp/actions/cart/addItems.ts"),
218
+ updateItems: enqueue("myapp/actions/cart/updateItems.ts"),
219
+ // ...
220
+ };
221
+
222
+ export const useCart = () => state;
223
+ ```
224
+
225
+ ### Key Hook Concepts:
226
+ - **Serial queue** — mutations execute one at a time, latest aborts previous
227
+ - **`enqueue`** pattern — wraps `invoke` with abort control
228
+ - **Signals** — reactive primitives from `@preact/signals`
229
+ - All state flows through `context.ts`
230
+
231
+ ## Middleware Pattern
232
+
233
+ Runs before every request. Sets up shared context:
234
+
235
+ ```typescript
236
+ // middleware.ts
237
+ import { AppMiddlewareContext } from "./mod.ts";
238
+
239
+ export const middleware = (_props: unknown, req: Request, ctx: AppMiddlewareContext) => {
240
+ // Parse cookies, set segment in bag, etc.
241
+ const cookies = getCookies(req.headers);
242
+ setSegmentBag(cookies, req, ctx);
243
+ setISCookiesBag(cookies, ctx);
244
+ return ctx.next!();
245
+ };
246
+ ```
247
+
248
+ Uses `ctx.bag` for per-request shared state (segment, cookies, orderFormId).
249
+
250
+ ## Sections Pattern
251
+
252
+ CMS-renderable Preact components:
253
+
254
+ ```typescript
255
+ // sections/Analytics/Vtex.tsx
256
+ import { AppContext } from "../../mod.ts";
257
+
258
+ export interface Props {
259
+ trackingId?: string;
260
+ }
261
+
262
+ export default function VtexAnalytics(props: Props) {
263
+ return <script dangerouslySetInnerHTML={{ __html: `...` }} />;
264
+ }
265
+ ```
266
+
267
+ ## OpenAPI Codegen
268
+
269
+ For apps with OpenAPI specs:
270
+
271
+ 1. Place `{name}.openapi.json` in `utils/openapi/`
272
+ 2. Run `deno task start`
273
+ 3. Generated types appear in `{name}.openapi.gen.ts`
274
+ 4. Use with `createHttpClient<GeneratedType>()`
275
+
276
+ ## Commerce App Checklist
277
+
278
+ When building a new commerce integration:
279
+
280
+ - [ ] `utils/types.ts` — Define all API response types
281
+ - [ ] `utils/client.ts` — Define typed HTTP interface
282
+ - [ ] `utils/transform.ts` — Map API types → schema.org types
283
+ - [ ] `loaders/` — PDP, PLP, ProductList, Suggestions, Cart, User, Wishlist
284
+ - [ ] `actions/cart/` — addItems, updateItems, removeItems, updateCoupons
285
+ - [ ] `actions/authentication/` — signIn, logout, etc.
286
+ - [ ] `hooks/` — useCart, useUser, useWishlist, context
287
+ - [ ] `middleware.ts` — Cookie/segment handling
288
+ - [ ] `mod.ts` — App factory with clients
@@ -0,0 +1,239 @@
1
+ # Commerce Types — Schema.org Reference
2
+
3
+ The `commerce/types.ts` file (786 lines) defines the canonical data model for all Deco commerce apps. Every platform (VTEX, Shopify, Wake, Nuvemshop) transforms its native API responses into these types.
4
+
5
+ ## Core Hierarchy
6
+
7
+ ```
8
+ Thing
9
+ ├── Product (extends ProductLeaf)
10
+ │ └── ProductGroup (has hasVariant: ProductLeaf[])
11
+ ├── Offer
12
+ │ └── AggregateOffer (has offers: Offer[])
13
+ ├── BreadcrumbList (has itemListElement: ListItem<string>[])
14
+ ├── ImageObject
15
+ ├── VideoObject
16
+ ├── Brand
17
+ ├── Review
18
+ ├── Person
19
+ ├── Organization
20
+ ├── Place
21
+ └── ItemList
22
+ ```
23
+
24
+ ## Product Types
25
+
26
+ ### ProductLeaf
27
+ ```typescript
28
+ interface ProductLeaf extends Omit<Thing, "@type"> {
29
+ "@type": "Product";
30
+ category?: string; // "category > subcategory > ..."
31
+ productID: string; // Platform SKU ID
32
+ sku: string; // SKU code (same as productID in most cases)
33
+ gtin?: string; // EAN/GTIN barcode
34
+ releaseDate?: string; // ISO 8601
35
+ brand?: Brand;
36
+ offers?: AggregateOffer;
37
+ isVariantOf?: ProductGroup;
38
+ isSimilarTo?: Product[];
39
+ isAccessoryOrSparePartFor?: Product[];
40
+ isRelatedTo?: Product[];
41
+ additionalProperty?: PropertyValue[];
42
+ review?: Review[];
43
+ aggregateRating?: AggregateRating;
44
+ questions?: Question[];
45
+ }
46
+ ```
47
+
48
+ ### ProductGroup
49
+ ```typescript
50
+ interface ProductGroup extends Omit<Thing, "@type"> {
51
+ "@type": "ProductGroup";
52
+ productGroupID: string; // Platform product ID
53
+ hasVariant: ProductLeaf[];
54
+ model?: string;
55
+ additionalProperty?: PropertyValue[];
56
+ }
57
+ ```
58
+
59
+ ### Product = ProductLeaf & { isVariantOf?: ProductGroup }
60
+
61
+ ## Offer / AggregateOffer
62
+
63
+ ### Offer
64
+ ```typescript
65
+ interface Offer {
66
+ "@type": "Offer";
67
+ seller: string; // Seller ID (NOT name!)
68
+ sellerName?: string;
69
+ price: number;
70
+ priceCurrency?: string;
71
+ priceSpecification: UnitPriceSpecification[];
72
+ priceValidUntil?: string;
73
+ availability: ItemAvailability;
74
+ inventoryLevel?: QuantitativeValue;
75
+ itemCondition?: OfferItemCondition;
76
+ teasers?: Teasers[];
77
+ giftSkuIds?: string[];
78
+ hasMerchantReturnPolicy?: MerchantReturnPolicy;
79
+ }
80
+ ```
81
+
82
+ ### AggregateOffer
83
+ ```typescript
84
+ interface AggregateOffer {
85
+ "@type": "AggregateOffer";
86
+ priceCurrency: string;
87
+ highPrice: number;
88
+ lowPrice: number;
89
+ offerCount: number;
90
+ offers: Offer[];
91
+ }
92
+ ```
93
+
94
+ ### UnitPriceSpecification
95
+ ```typescript
96
+ interface UnitPriceSpecification {
97
+ "@type": "UnitPriceSpecification";
98
+ priceType: PriceTypeEnumeration; // "https://schema.org/ListPrice" | "https://schema.org/SalePrice" | etc.
99
+ priceComponentType?: PriceComponentTypeEnumeration;
100
+ price: number;
101
+ billingDuration?: number;
102
+ billingIncrement?: number;
103
+ name?: string;
104
+ }
105
+ ```
106
+
107
+ ## Page Types
108
+
109
+ ### ProductDetailsPage
110
+ ```typescript
111
+ interface ProductDetailsPage {
112
+ "@type": "ProductDetailsPage";
113
+ breadcrumbList: BreadcrumbList;
114
+ product: Product;
115
+ seo?: Seo;
116
+ }
117
+ ```
118
+
119
+ ### ProductListingPage
120
+ ```typescript
121
+ interface ProductListingPage {
122
+ "@type": "ProductListingPage";
123
+ breadcrumb: BreadcrumbList;
124
+ filters: Filter[];
125
+ products: Product[];
126
+ pageInfo: PageInfo;
127
+ sortOptions: SortOption[];
128
+ seo?: Seo;
129
+ pageTypes?: PageType[];
130
+ }
131
+ ```
132
+
133
+ ### PageInfo
134
+ ```typescript
135
+ interface PageInfo {
136
+ currentPage: number;
137
+ nextPage?: string;
138
+ previousPage?: string;
139
+ records?: number;
140
+ recordPerPage?: number;
141
+ pageTypes?: PageType[];
142
+ }
143
+ ```
144
+
145
+ ## Filter Types
146
+
147
+ ### FilterToggle
148
+ ```typescript
149
+ interface FilterToggle extends FilterBase {
150
+ "@type": "FilterToggle";
151
+ values: FilterToggleValue[];
152
+ quantity: number;
153
+ }
154
+ ```
155
+
156
+ ### FilterRange
157
+ ```typescript
158
+ interface FilterRange extends FilterBase {
159
+ "@type": "FilterRange";
160
+ values: FilterRangeValue; // { min: number, max: number }
161
+ }
162
+ ```
163
+
164
+ ## Navigation
165
+
166
+ ### SiteNavigationElement
167
+ ```typescript
168
+ interface SiteNavigationElement {
169
+ "@type": "SiteNavigationElement";
170
+ name?: string;
171
+ url?: string;
172
+ image?: ImageObject[];
173
+ children?: SiteNavigationElement[];
174
+ additionalType?: string;
175
+ }
176
+ ```
177
+
178
+ ## Analytics (GA4)
179
+
180
+ ### AnalyticsItem
181
+ ```typescript
182
+ interface AnalyticsItem {
183
+ item_id: string;
184
+ item_group_id?: string;
185
+ quantity: number;
186
+ coupon?: string;
187
+ price: number;
188
+ discount?: number;
189
+ index?: number;
190
+ item_name?: string;
191
+ item_variant?: string;
192
+ item_brand?: string;
193
+ item_url?: string;
194
+ affiliation?: string;
195
+ item_list_id?: string;
196
+ item_list_name?: string;
197
+ [key: `item_category${number | ""}`]: string;
198
+ }
199
+ ```
200
+
201
+ ### Event Types
202
+ - `AddToCartEvent` — items + value + currency
203
+ - `RemoveFromCartEvent` — items + value + currency
204
+ - `ViewItemEvent` — items + value + currency
205
+ - `ViewItemListEvent` — items + item_list_name
206
+ - `SelectItemEvent` — items + item_list_name
207
+ - `BeginCheckoutEvent` — items + value + coupon
208
+ - `AddShippingInfoEvent` — items + shipping_tier
209
+ - `ViewCartEvent` — items + value + currency
210
+ - `ViewPromotionEvent` — items + promotion_name
211
+ - `SelectPromotionEvent` — items + promotion_name
212
+ - `LoginEvent` — method
213
+ - `SearchEvent` — search_term
214
+
215
+ ## Availability Enum
216
+ ```typescript
217
+ type ItemAvailability =
218
+ | "https://schema.org/BackOrder"
219
+ | "https://schema.org/Discontinued"
220
+ | "https://schema.org/InStock"
221
+ | "https://schema.org/InStoreOnly"
222
+ | "https://schema.org/LimitedAvailability"
223
+ | "https://schema.org/OnlineOnly"
224
+ | "https://schema.org/OutOfStock"
225
+ | "https://schema.org/PreOrder"
226
+ | "https://schema.org/PreSale"
227
+ | "https://schema.org/SoldOut";
228
+ ```
229
+
230
+ ## Key Rules for Platform Implementors
231
+
232
+ 1. **`Offer.seller` MUST be the seller ID** (e.g., "1"), never the seller name
233
+ 2. **`Offer.sellerName`** is optional and holds the display name
234
+ 3. **Prices are in decimal** (not cents) — e.g., `199.90` not `19990`
235
+ 4. **`productID`** = platform SKU ID; **`ProductGroup.productGroupID`** = platform product ID
236
+ 5. **`Product.sku`** should equal `productID` — used for cart operations
237
+ 6. **Images** must be `ImageObject[]` with `url`, `alternateName`, `encodingFormat`
238
+ 7. **Breadcrumbs** use `ListItem<string>` with `position` (1-indexed) and `item` (URL)
239
+ 8. **Category strings** use ` > ` separator (e.g., `"Furniture > Chairs > Office"`)