@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,220 @@
1
+ # Resolution Engine (`engine/`)
2
+
3
+ The heart of Deco — resolves configuration objects (Resolvables) into runtime values using a pipeline of resolvers.
4
+
5
+ ## Core Concepts
6
+
7
+ ### Resolvable
8
+
9
+ An object with `__resolveType` that tells the engine which resolver to use:
10
+
11
+ ```typescript
12
+ interface Resolvable<T = unknown> {
13
+ __resolveType: string; // resolver key (e.g. "site/loaders/productList.ts")
14
+ [key: string]: unknown; // props passed to the resolver
15
+ }
16
+ ```
17
+
18
+ ### Resolver
19
+
20
+ A function that processes a Resolvable:
21
+
22
+ ```typescript
23
+ type Resolver<T = unknown> = (
24
+ parent: T, // resolved props from the Resolvable
25
+ context: ResolverContext
26
+ ) => T | Resolvable<T> | Promise<T | Resolvable<T>>;
27
+ ```
28
+
29
+ ### ResolverContext
30
+
31
+ ```typescript
32
+ interface ResolverContext {
33
+ resolvables: Record<string, Resolvable>; // decofile state
34
+ resolvers: Record<string, Resolver>; // all registered resolvers
35
+ resolve: (resolvable: Resolvable | string) => Promise<unknown>;
36
+ resolveChain: FieldResolver[]; // debug: resolution path
37
+ memo: Map<string, Promise<unknown>>; // memoization cache
38
+ runOnce: (key: string, fn: () => Promise<T>) => Promise<T>;
39
+ revision: string;
40
+ }
41
+ ```
42
+
43
+ ## Resolution Pipeline
44
+
45
+ ```
46
+ resolve(input)
47
+
48
+ ├─ string → resolveWithType(resolveType, {}, context)
49
+
50
+ └─ Resolvable → resolveAny()
51
+
52
+ └─ resolvePropsWithHints()
53
+
54
+ ├─ Extract __resolveType
55
+ ├─ Call onBeforeResolveProps (if defined)
56
+ ├─ Resolve each prop recursively (parallel)
57
+ └─ resolveWithType(__resolveType)
58
+
59
+ ├─ In resolvables? → resolveResolvable() [with memo]
60
+ ├─ In resolvers? → invokeResolverWithProps()
61
+ └─ Else → danglingRecover or DanglingReference error
62
+ ```
63
+
64
+ ### Key Functions (`engine/core/resolver.ts`)
65
+
66
+ | Function | Purpose |
67
+ |----------|---------|
68
+ | `resolve(input, ctx)` | Main entry — handles string refs and Resolvable objects |
69
+ | `resolveAny(obj, ctx)` | Resolves an arbitrary object, recursing into props |
70
+ | `resolvePropsWithHints(obj, ctx)` | Uses hint nodes to efficiently resolve only resolvable props |
71
+ | `resolveWithType(type, props, ctx)` | Resolves by looking up type in resolvables or resolvers |
72
+ | `resolveResolvable(id, ctx)` | Resolves a named resolvable with memoization |
73
+ | `invokeResolverWithProps(type, props, ctx)` | Calls the resolver function with resolved props |
74
+
75
+ ### Resolution Hints (`engine/core/hints.ts`)
76
+
77
+ Optimization to avoid scanning all props. `HintNode` trees mark which properties contain resolvables:
78
+
79
+ ```typescript
80
+ interface HintNode {
81
+ __resolveType?: boolean; // this object is a Resolvable
82
+ [prop: string]: HintNode; // nested hints
83
+ }
84
+ ```
85
+
86
+ `traverseAny()` builds hints from the decofile. The resolver only recurses into hinted paths.
87
+
88
+ ### Memoization
89
+
90
+ `resolveResolvable` memos results by `resolverIdFromResolveChain`. Same resolvable in the same resolution tree returns the cached promise.
91
+
92
+ ## Resolve Chain
93
+
94
+ A debug/tracing mechanism. Each resolution step appends a `FieldResolver`:
95
+
96
+ ```typescript
97
+ type FieldResolver =
98
+ | { type: "prop"; value: string } // accessing a property
99
+ | { type: "resolvable"; value: string } // resolving a named resolvable
100
+ | { type: "resolver"; value: string } // invoking a resolver
101
+ | { type: "dangling"; value: string } // unresolved reference
102
+ ```
103
+
104
+ Used for cache keys, tracing, and error reporting.
105
+
106
+ ## ReleaseResolver (`engine/core/mod.ts`)
107
+
108
+ Top-level coordinator:
109
+
110
+ ```typescript
111
+ function ReleaseResolver(
112
+ decofileProvider: DecofileProvider,
113
+ resolvers: Record<string, Resolver>,
114
+ options?: { danglingRecover?, overrides?, forceFresh? }
115
+ ): {
116
+ resolve: (resolvable | string) => Promise<unknown>;
117
+ state: () => ResolvableMap;
118
+ revision: () => string;
119
+ }
120
+ ```
121
+
122
+ - Gets `resolvables` and `revision` from the DecofileProvider
123
+ - Combines default resolvers + block resolvers + app resolvers
124
+ - Provides the top-level `resolve()` function used by the runtime
125
+
126
+ ## DecofileProvider (`engine/decofile/`)
127
+
128
+ Interface for state management (the decofile is the CMS state):
129
+
130
+ ```typescript
131
+ interface DecofileProvider {
132
+ state(): Record<string, Resolvable>; // current state
133
+ revision(): string; // version/etag
134
+ onChange(cb: () => void): void; // subscribe to changes
135
+ dispose?(): void;
136
+ }
137
+ ```
138
+
139
+ ### Implementations
140
+
141
+ | Provider | Source | Usage |
142
+ |----------|--------|-------|
143
+ | `newFsProvider` | Local filesystem (`.json`, `.jsonl`) | Dev mode |
144
+ | `jsonProvider` | In-memory JSON object | Testing, static |
145
+ | `realtimeProvider` | CMS websocket connection | Production |
146
+ | `fsFolderProvider` | `folder://` directory with individual files | Legacy |
147
+
148
+ ### State Lifecycle
149
+
150
+ 1. `DecofileProvider.state()` returns current `ResolvableMap`
151
+ 2. Engine creates `ReleaseResolver` with this state
152
+ 3. Provider emits `onChange()` when CMS publishes
153
+ 4. Engine reinstalls apps and rebuilds resolvers
154
+
155
+ ## Manifest System (`engine/manifest/`)
156
+
157
+ ### ManifestBuilder
158
+
159
+ Programmatically builds a manifest file:
160
+
161
+ ```typescript
162
+ interface ManifestData {
163
+ namespace: string;
164
+ imports: Record<string, string>; // import name → module path
165
+ manifest: Record<string, string[]>; // block type → keys
166
+ exports: Record<string, string>;
167
+ statements: string[];
168
+ }
169
+ ```
170
+
171
+ Key methods:
172
+ - `mergeWith(other)` — merge manifests from multiple apps
173
+ - `addValuesOnManifestKey(key, values)` — add blocks by type
174
+ - `build()` — generate the `.ts` file content
175
+
176
+ ### manifestGen
177
+
178
+ `decoManifestBuilder()` walks directories by block type, calling `withDefinition()` for each discovered module.
179
+
180
+ ### Default Resolvers (`engine/manifest/defaults.ts`)
181
+
182
+ Built-in resolvers available in every Deco instance:
183
+
184
+ | Resolver | Purpose |
185
+ |----------|---------|
186
+ | `state` | Returns raw resolvable value |
187
+ | `resolvables` | Access resolvables map |
188
+ | `resolvers` | Access resolvers map |
189
+ | `once` | Run-once resolver (memoized) |
190
+ | `resolveTypeSelector` | Dynamic __resolveType selection |
191
+ | `blockSelector` | Select block by type |
192
+ | `selectKeys` | Pick specific keys from resolved object |
193
+ | `mergeProps` | Deep-merge multiple resolved objects |
194
+ | `resolved` | Mark value as already resolved |
195
+ | `preview` | `Preview@{block}` namespace |
196
+ | `invoke` | `Invoke@{block}` namespace |
197
+
198
+ ## Schema System (`engine/schema/`)
199
+
200
+ Generates JSON Schema from TypeScript types at runtime:
201
+
202
+ | File | Purpose |
203
+ |------|---------|
204
+ | `schemeable.ts` | Core schema types (`Schemeable`) |
205
+ | `builder.ts` | Builds JSON Schema from scheemables |
206
+ | `parser.ts` | Parses TypeScript AST into scheemables |
207
+ | `merge.ts` | Merges schemas from multiple sources |
208
+ | `reader.ts` | Reads and caches module schemas |
209
+ | `transform.ts` | Schema transformations (refs, ids) |
210
+ | `lazy.ts` | Lazy schema loading for performance |
211
+
212
+ Used by the admin to generate forms for block props.
213
+
214
+ ## Import Map (`engine/importmap/`)
215
+
216
+ Builds Deno import maps for blocks:
217
+
218
+ - `buildImportMap(manifest)` — generates imports for each block
219
+ - `FuncAddr.build()` — creates `resolve://path?export=funcName` addresses
220
+ - Supports JSR (`jsr:`) and URL imports
@@ -0,0 +1,157 @@
1
+ # Hooks and Components
2
+
3
+ Server-side hooks and shared components provided by the Deco framework.
4
+
5
+ ## Hooks (`hooks/`)
6
+
7
+ ### useSection (`useSection.ts`)
8
+
9
+ Generates a URL for partial section rendering via `/deco/render`.
10
+
11
+ ```typescript
12
+ function useSection<TProps>(options: {
13
+ props?: Partial<TProps>; // new props for the section
14
+ href?: string; // target URL
15
+ }): string // returns URL to POST for partial render
16
+ ```
17
+
18
+ Used in section components to create interactive behavior without client-side JS:
19
+
20
+ ```tsx
21
+ function ProductShelf({ products, page = 0 }: Props) {
22
+ const nextPageUrl = useSection({ props: { page: page + 1 } });
23
+
24
+ return (
25
+ <div>
26
+ {products.map(p => <ProductCard product={p} />)}
27
+ <button hx-get={nextPageUrl} hx-target="closest section">
28
+ Load more
29
+ </button>
30
+ </div>
31
+ );
32
+ }
33
+ ```
34
+
35
+ Internals:
36
+ - Serializes `props`, `href`, `pathTemplate`, `resolveChain` into the URL
37
+ - Strips tracking query params (BLOCKED_QS: utm_*, gclid, fbclid, etc.)
38
+ - Supports `__cb` callback parameter
39
+
40
+ ### usePartialSection (`usePartialSection.ts`)
41
+
42
+ Fresh-specific: returns attributes for Fresh `<Partial>` navigation.
43
+
44
+ ```typescript
45
+ function usePartialSection<TProps>(options: {
46
+ props?: Partial<TProps>;
47
+ href?: string;
48
+ }): { "f-client-nav": true; "f-partial": string }
49
+ ```
50
+
51
+ Usage:
52
+ ```tsx
53
+ <button {...usePartialSection({ props: { page: 2 } })}>
54
+ Next Page
55
+ </button>
56
+ ```
57
+
58
+ ### useScript (`useScript.ts`)
59
+
60
+ Minifies a function and returns it as a script string or data URI.
61
+
62
+ ```typescript
63
+ // Returns minified script string
64
+ function useScript<Args>(fn: (...args: Args) => void, ...args: Args): string;
65
+
66
+ // Returns data:text/javascript,... URI
67
+ function useScriptAsDataURI<Args>(fn: (...args: Args) => void, ...args: Args): string;
68
+ ```
69
+
70
+ Usage:
71
+ ```tsx
72
+ <script dangerouslySetInnerHTML={{
73
+ __html: useScript((count) => {
74
+ document.getElementById("counter").textContent = String(count);
75
+ }, initialCount)
76
+ }} />
77
+ ```
78
+
79
+ Uses Terser for minification.
80
+
81
+ ### useDevice (`useDevice.ts`)
82
+
83
+ Returns the current device type from the server context.
84
+
85
+ ```typescript
86
+ function useDevice(): "desktop" | "mobile" | "tablet";
87
+ ```
88
+
89
+ Detection is done server-side via User-Agent header using `userAgent.ts`.
90
+
91
+ ### useSetEarlyHints (`useSetEarlyHints.ts`)
92
+
93
+ Adds `Link` headers for HTTP 103 Early Hints (preload/preconnect).
94
+
95
+ ```typescript
96
+ function useSetEarlyHints(links: Array<{
97
+ href: string;
98
+ as?: string;
99
+ rel?: string;
100
+ }>): void;
101
+ ```
102
+
103
+ ## Components (`components/`)
104
+
105
+ ### Section (`section.tsx`)
106
+
107
+ Core section rendering infrastructure:
108
+
109
+ | Export | Purpose |
110
+ |--------|---------|
111
+ | `withSection(Component)` | HOC wrapping component with context + error boundary |
112
+ | `SectionContext` | Preact context providing section ID, resolve chain |
113
+ | `getSectionID(resolveChain)` | Extracts unique section ID from resolve chain |
114
+ | `ErrorBoundary` | Catches render errors, shows fallback UI |
115
+ | `Framework` | Framework-agnostic section wrapper |
116
+
117
+ ### StubSection (`StubSection.tsx`)
118
+
119
+ Placeholder for dangling references (when a section's module is not found):
120
+
121
+ ```tsx
122
+ function StubSection({ component }: { component: string }) {
123
+ return <div>Section not found: {component}</div>;
124
+ }
125
+ ```
126
+
127
+ Used as `defaultDanglingRecover` for section blocks.
128
+
129
+ ### PreviewNotAvailable (`PreviewNotAvailable.tsx`)
130
+
131
+ Shown in admin when a block doesn't have a preview implementation.
132
+
133
+ ### LiveControls (`LiveControls.tsx`)
134
+
135
+ Injected into every page in edit mode. Provides:
136
+
137
+ - `__DECO_STATE` global with decofile state
138
+ - `DomInspector` for element selection
139
+ - Keyboard shortcuts (`Ctrl+Shift+E` for editor)
140
+ - `postMessage` bridge to admin iframe
141
+ - Script loads from `decoAssistantUrl`
142
+
143
+ ### JsonViewer (`JsonViewer.tsx`)
144
+
145
+ Renders JSON data using jQuery JSONView. Used in admin previews for loaders/actions.
146
+
147
+ ## Exports Map (`hooks/mod.ts`)
148
+
149
+ All hooks are re-exported from `@deco/deco/hooks`:
150
+
151
+ ```typescript
152
+ export { useSection } from "./useSection.ts";
153
+ export { usePartialSection } from "./usePartialSection.ts";
154
+ export { useScript, useScriptAsDataURI } from "./useScript.ts";
155
+ export { useDevice } from "./useDevice.ts";
156
+ export { useSetEarlyHints } from "./useSetEarlyHints.ts";
157
+ ```
@@ -0,0 +1,136 @@
1
+ # Plugins and Clients
2
+
3
+ ## Plugins (`plugins/`)
4
+
5
+ ### Deco Plugin (`plugins/deco.ts`)
6
+
7
+ The main Fresh plugin that integrates Deco into a Fresh app.
8
+
9
+ ```typescript
10
+ import { plugins } from "deco/plugins/deco.ts";
11
+
12
+ export default defineConfig({
13
+ plugins: plugins({
14
+ manifest,
15
+ htmx: false,
16
+ site: "mysite",
17
+ ErrorFallback,
18
+ useServer: true,
19
+ middlewares: [],
20
+ }),
21
+ });
22
+ ```
23
+
24
+ Internally wraps `runtime/fresh/plugin.tsx`. Registers routes (`/[...catchall]`, `/index`), island (`DispatchAsyncRender.tsx`), selects framework (Fresh or HTMX), injects middleware chain.
25
+
26
+ ### Fresh + Tailwind Plugin (`plugins/fresh.ts`)
27
+
28
+ Convenience that combines Tailwind CSS and Deco:
29
+
30
+ ```typescript
31
+ import { plugins } from "deco/plugins/fresh.ts";
32
+
33
+ export default defineConfig({
34
+ plugins: plugins({
35
+ manifest,
36
+ tailwind: { /* config */ },
37
+ }),
38
+ });
39
+ ```
40
+
41
+ Returns `[tailwindPlugin(config), decoPlugin(options)]`.
42
+
43
+ ### Styles Plugin (`plugins/styles.ts`)
44
+
45
+ Injects global CSS into `<head>` via `id="__DECO_GLOBAL_STYLES__"`.
46
+
47
+ ## Client-side Invoke (`clients/`)
48
+
49
+ ### withManifest (`clients/withManifest.ts`)
50
+
51
+ Creates a typed invoke client for calling server loaders/actions from the browser.
52
+
53
+ ```typescript
54
+ import { proxy } from "@deco/deco/web";
55
+ import type { Manifest } from "./manifest.gen.ts";
56
+
57
+ const invoke = proxy<Manifest>();
58
+
59
+ // Single invoke
60
+ const products = await invoke["site/loaders/productList.ts"]({ query: "shoes" });
61
+
62
+ // Batch invoke
63
+ const [products, categories] = await invoke({
64
+ "site/loaders/productList.ts": { query: "shoes" },
65
+ "site/loaders/categories.ts": {},
66
+ });
67
+ ```
68
+
69
+ Internals: `fetchWithProps(key, props)` POSTs to `/live/invoke/${key}`. Supports `text/event-stream` for streaming.
70
+
71
+ ### InvokeAwaiter (`clients/proxy.ts`)
72
+
73
+ Chainable proxy that builds invoke keys from property access:
74
+
75
+ ```typescript
76
+ const invoke = proxy<Manifest>();
77
+
78
+ // Equivalent calls:
79
+ invoke["site/loaders/productList.ts"](props);
80
+ invoke.site.loaders["productList.ts"](props);
81
+ ```
82
+
83
+ Uses JavaScript `Proxy` to build the key string from nested property access.
84
+
85
+ ### Stream Reading
86
+
87
+ ```typescript
88
+ import { readFromStream } from "@deco/deco/web";
89
+
90
+ const response = await invoke.streaming["site/loaders/feed.ts"]({});
91
+ for await (const chunk of readFromStream(response)) {
92
+ console.log(chunk);
93
+ }
94
+ ```
95
+
96
+ ### FormData Utils (`clients/formdata.ts`)
97
+
98
+ Converts between objects and FormData:
99
+
100
+ ```typescript
101
+ const formData = propsToFormData({ name: "John", address: { city: "SP" } });
102
+ // name=John, address.city=SP
103
+
104
+ const props = formDataToProps(formData);
105
+ // { name: "John", address: { city: "SP" } }
106
+ ```
107
+
108
+ ## Usage in Sites
109
+
110
+ ### runtime.ts Pattern
111
+
112
+ Every Deco site has a `runtime.ts`:
113
+
114
+ ```typescript
115
+ import { proxy } from "@deco/deco/web";
116
+ import type { Manifest } from "./manifest.gen.ts";
117
+ import type { Manifest as VTEXManifest } from "apps/vtex/manifest.gen.ts";
118
+
119
+ export const invoke = proxy<Manifest & VTEXManifest>();
120
+ ```
121
+
122
+ Merges site + VTEX manifests for typed invocation.
123
+
124
+ ### Client Usage
125
+
126
+ ```typescript
127
+ import { invoke } from "../runtime.ts";
128
+
129
+ const products = await invoke.vtex.loaders.intelligentSearch.productListingPage({
130
+ query: "shoes",
131
+ page: 0,
132
+ count: 12,
133
+ });
134
+ ```
135
+
136
+ The invoke proxy builds the key from the property chain, POSTs to `/live/invoke/{key}`, and returns parsed JSON.
@@ -0,0 +1,116 @@
1
+ # Runtime (`runtime/`)
2
+
3
+ The runtime handles HTTP requests, routing, rendering, and the invoke API. Built on Hono with Fresh or HTMX rendering.
4
+
5
+ ## Entry Point: Deco class (`runtime/mod.ts`)
6
+
7
+ ```typescript
8
+ class Deco {
9
+ constructor(options: DecoOptions);
10
+ handler(): Deno.ServeHandler;
11
+ render(params): Promise<string>;
12
+ meta(): { schema, manifest };
13
+ styles(): string;
14
+ dispose(): void;
15
+ }
16
+ ```
17
+
18
+ ## Request Flow (`runtime/handler.tsx`)
19
+
20
+ ```
21
+ Hono App
22
+ |-- Middleware: bindings (sets RENDER_FN, GLOBALS)
23
+ |-- Middleware: liveness (/deco/_liveness probes)
24
+ |-- Middleware: statebuilder (prepareState, debug, echo)
25
+ |-- Middleware: observability (OpenTelemetry trace/span)
26
+ |-- Middleware: main (CORS, Cache-Control, segment)
27
+ |
28
+ |-- GET /styles.css -> tailwind CSS
29
+ |-- GET /live/_meta -> schema + manifest
30
+ |-- GET /deco/meta -> alias for _meta
31
+ |-- ALL /live/release -> release info
32
+ |-- ALL /.decofile/reload -> trigger state reload
33
+ |-- GET /live/inspect/:block -> block inspector
34
+ |-- POST /live/invoke -> batch invoke
35
+ |-- ALL /live/invoke/* -> single invoke by key
36
+ |-- ALL /live/previews -> preview index
37
+ |-- ALL /live/previews/* -> block preview
38
+ |-- POST /deco/render -> partial section render
39
+ |-- ALL /live/workflows/run -> trigger workflow
40
+ |-- ALL * (catch-all) -> page handler (entrypoint)
41
+ ```
42
+
43
+ ## Middleware Chain
44
+
45
+ ### 1. Bindings
46
+ Sets `RENDER_FN` (framework render function) and `GLOBALS` (error handler, dev flag).
47
+
48
+ ### 2. Liveness (`runtime/middlewares/liveness.ts`)
49
+ Health probe at `/deco/_liveness` returning memory, uptime, requestCount, requestInflight.
50
+
51
+ ### 3. State Builder
52
+ Creates resolve/invoke functions scoped to the request. Sets `state.deco` with DecoRuntimeState.
53
+
54
+ ### 4. Observability
55
+ OpenTelemetry spans per request with `http.method`, `http.url`, `http.status_code`, `deco.site` attributes.
56
+
57
+ ### 5. Main
58
+ CORS headers, Cache-Control, segment cookie handling, custom response headers from flags.
59
+
60
+ ## Key Routes
61
+
62
+ ### Invoke (`/live/invoke/*`)
63
+ Single-key invocation: `POST /live/invoke/site/loaders/productList.ts` with JSON body.
64
+
65
+ ### Batch Invoke (`/live/invoke`)
66
+ Multiple invocations in one request with a multi-key JSON body.
67
+
68
+ ### Render (`/deco/render`)
69
+ Partial section rendering used by `useSection` hook. Receives `props`, `href`, `pathTemplate`, `resolveChain`.
70
+
71
+ ### Entrypoint (`*` catch-all)
72
+ 1. Resolves `./routes/[...catchall].tsx` via `state.resolve`
73
+ 2. Handler processes request
74
+ 3. Calls `ctx.render(PageData)` for HTML output
75
+
76
+ ## Rendering
77
+
78
+ ### PageData
79
+ Contains `page` (resolved sections), `routerInfo` (URL, params), `loadingMode`.
80
+
81
+ ### Section Rendering
82
+ Each section gets: SectionContext, ErrorBoundary, `withSection` HOC, framework-specific partial support.
83
+
84
+ ## Frameworks
85
+
86
+ | Framework | Islands | Partials | Usage |
87
+ |-----------|---------|----------|-------|
88
+ | Fresh | Preact islands | `<Partial>` + `f-partial` | Standard Deco sites |
89
+ | HTMX | None (no JS) | `hx-get/hx-swap` | Lightweight alternative |
90
+
91
+ ### Fresh (`runtime/fresh/`)
92
+ - `plugin.ts` / `plugin.tsx` for Fresh plugin registration
93
+ - `Bindings.tsx` provides `<Partial>`, `<Head>`
94
+ - `islands/DispatchAsyncRender.tsx` for lazy section loading via IntersectionObserver
95
+
96
+ ### HTMX (`runtime/htmx/`)
97
+ - `Renderer.tsx` uses `renderToString(Preact)` for full server rendering
98
+ - No islands, no client-side hydration
99
+ - Uses `hx-get`, `hx-trigger`, `hx-target`, `hx-swap`
100
+
101
+ ## Caching (`runtime/caches/`)
102
+
103
+ | Cache | Purpose |
104
+ |-------|---------|
105
+ | `lru.ts` | In-memory LRU (weak references) |
106
+ | `redis.ts` | Redis-backed cache |
107
+ | `tiered.ts` | LRU then Redis then origin |
108
+ | `fileSystem.ts` | Disk-based cache |
109
+
110
+ ## Fetch Instrumentation (`runtime/fetch/`)
111
+
112
+ | File | Purpose |
113
+ |------|---------|
114
+ | `mod.ts` | Main fetch wrapper with logging + caching |
115
+ | `fetchLog.ts` | Logs fetch calls to OpenTelemetry |
116
+ | `fetchCache.ts` | HTTP cache (respects Cache-Control) |