@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,251 @@
1
+ # Asset Optimization Checklist
2
+
3
+ 17 learnings from real Deco sites. Check these during analysis.
4
+
5
+ ## Third-Party Scripts
6
+
7
+ ### 1. On-Demand Script Loading
8
+ **Check**: Are heavy scripts loaded on page load?
9
+
10
+ ```typescript
11
+ // Bad: Loads immediately
12
+ <script src="https://chat-widget.com/bundle.js" />
13
+
14
+ // Good: Load on interaction
15
+ function ChatButton() {
16
+ const [loaded, setLoaded] = useState(false);
17
+
18
+ const loadChat = () => {
19
+ if (!loaded) {
20
+ const script = document.createElement('script');
21
+ script.src = "https://chat-widget.com/bundle.js";
22
+ document.body.appendChild(script);
23
+ setLoaded(true);
24
+ }
25
+ };
26
+
27
+ return <button onClick={loadChat}>Chat</button>;
28
+ }
29
+ ```
30
+
31
+ ### 2. Route-Specific Script Injection
32
+ **Check**: Do scripts load on pages where they're not used?
33
+
34
+ ```typescript
35
+ // Good: Only load on relevant pages
36
+ const isCheckout = ctx.url.pathname.startsWith('/checkout');
37
+ const isPDP = ctx.url.pathname.includes('/p');
38
+
39
+ return (
40
+ <>
41
+ {isCheckout && <PaymentScript />}
42
+ {isPDP && <ReviewScript />}
43
+ </>
44
+ );
45
+ ```
46
+
47
+ ### 3. Script Localization
48
+ **Check**: Are external scripts hosted locally?
49
+ - Localize frequently used scripts to `/static`
50
+ - Improves reliability and performance
51
+ - Works offline
52
+
53
+ ```typescript
54
+ // Before: External
55
+ <script src="https://unpkg.com/htmx.org@1.9.10" />
56
+
57
+ // After: Local
58
+ <script src="/static/htmx-1.9.10.js" />
59
+ ```
60
+
61
+ ### 4. GTM Implementation
62
+ **Check**: Does GTM have noscript fallback?
63
+
64
+ ```html
65
+ <!-- Head -->
66
+ <script>(function(w,d,s,l,i){...})(window,document,'script','dataLayer','GTM-XXX');</script>
67
+
68
+ <!-- Body (required) -->
69
+ <noscript>
70
+ <iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXX" />
71
+ </noscript>
72
+ ```
73
+
74
+ ### 5. Third-Party Widget Removal
75
+ **Check**: Are there unused third-party widgets?
76
+ - Audit PDP for review widgets that can be lazy-loaded
77
+ - Remove chat widgets from pages where not needed
78
+ - Defer non-critical analytics
79
+
80
+ ## Section Optimization
81
+
82
+ ### 6. Lazy Section Loading
83
+ **Check**: Are heavy below-fold sections lazy?
84
+
85
+ ```json
86
+ {
87
+ "__resolveType": "website/sections/Rendering/Lazy.tsx",
88
+ "section": { "__resolveType": "site/sections/Product/Reviews.tsx" }
89
+ }
90
+ ```
91
+
92
+ Best candidates for lazy loading:
93
+ - Product shelves
94
+ - Reviews
95
+ - Similar products
96
+ - FAQ sections
97
+ - Instagram feeds
98
+
99
+ ### 7. Skeleton/Fallback Pattern
100
+ **Check**: Do async sections have loading states?
101
+
102
+ ```typescript
103
+ export function LoadingFallback() {
104
+ return (
105
+ <div class="animate-pulse">
106
+ <div class="h-8 bg-gray-200 rounded w-1/3 mb-4" />
107
+ <div class="grid grid-cols-4 gap-4">
108
+ {[...Array(4)].map(() => (
109
+ <div class="h-64 bg-gray-200 rounded" />
110
+ ))}
111
+ </div>
112
+ </div>
113
+ );
114
+ }
115
+ ```
116
+
117
+ ### 8. Video Section Handling
118
+ **Check**: Are video sections wrapped in Lazy/Deferred?
119
+ - Native video or iframes should NOT be lazy wrapped
120
+ - Causes interaction breakage
121
+ - Only lazy wrap if explicitly needed
122
+
123
+ ## Block Architecture
124
+
125
+ ### 9. Block Flattening
126
+ **Check**: Are there unnecessary PageInclude wrappers?
127
+
128
+ ```json
129
+ // Bad: Extra resolution overhead
130
+ {
131
+ "__resolveType": "website/sections/PageInclude.tsx",
132
+ "page": { "__resolveType": "Header-Block" }
133
+ }
134
+
135
+ // Good: Direct reference
136
+ {
137
+ "__resolveType": "$Header-Block"
138
+ }
139
+ ```
140
+
141
+ ## Migration
142
+
143
+ ### 10. Standard Library Migration
144
+ **Check**: Are there `deco-sites/std` imports?
145
+
146
+ ```typescript
147
+ // Bad: Legacy
148
+ import { Image } from "deco-sites/std/components/Image.tsx";
149
+
150
+ // Good: Modern
151
+ import { Image } from "apps/website/components/Image.tsx";
152
+ ```
153
+
154
+ Audit all imports and replace:
155
+ - `deco-sites/std` → `apps/`
156
+
157
+ ## Layout Stability
158
+
159
+ ### 11. Aspect Ratio Reservation
160
+ **Check**: Do images/videos cause CLS?
161
+
162
+ ```tsx
163
+ // Good: Reserve space
164
+ <div class="aspect-video relative">
165
+ <Image class="absolute inset-0 w-full h-full object-cover" />
166
+ </div>
167
+ ```
168
+
169
+ ## Security
170
+
171
+ ### 12. CSP Hardening
172
+ **Check**: Are CSP headers configured?
173
+
174
+ ```typescript
175
+ // In _middleware.ts
176
+ const cspHeader = [
177
+ "default-src 'self'",
178
+ "script-src 'self' 'unsafe-inline' https://www.googletagmanager.com",
179
+ "worker-src 'self'",
180
+ "frame-ancestors 'self'",
181
+ ].join("; ");
182
+
183
+ response.headers.set("Content-Security-Policy", cspHeader);
184
+ ```
185
+
186
+ ### 13. Service Worker Strategy
187
+ **Check**: Is Service Worker strategy optimal?
188
+
189
+ ```typescript
190
+ // Avoid: NetworkOnly as default (negates caching)
191
+ defaultStrategy: "NetworkOnly"
192
+
193
+ // Better: CacheFirst or StaleWhileRevalidate
194
+ defaultStrategy: "CacheFirst"
195
+ ```
196
+
197
+ ## Deno Configuration
198
+
199
+ ### 14. Deno Native Optimization
200
+ **Check**: Is `nodeModulesDir` enabled unnecessarily?
201
+
202
+ ```json
203
+ // deno.json - disable if not needed
204
+ {
205
+ "nodeModulesDir": false // Faster startup, less disk
206
+ }
207
+ ```
208
+
209
+ ### 15. Relative Path Invocation
210
+ **Check**: Are loaders using absolute URLs?
211
+
212
+ ```typescript
213
+ // Bad: Cross-domain overhead
214
+ fetch("https://mysite.com/live/invoke/...");
215
+
216
+ // Good: Relative path
217
+ fetch("/live/invoke/...");
218
+ ```
219
+
220
+ ## Quick Audit Commands
221
+
222
+ ```bash
223
+ # Find deco-sites/std imports
224
+ grep -r "deco-sites/std" sections/ loaders/ components/
225
+
226
+ # Find third-party scripts
227
+ grep -r '<script src="http' sections/ components/
228
+
229
+ # Find sections without LoadingFallback
230
+ for f in sections/**/*.tsx; do
231
+ grep -q "LoadingFallback" "$f" || echo "Missing fallback: $f"
232
+ done
233
+
234
+ # Check CSP headers
235
+ grep -r "Content-Security-Policy" routes/ _middleware.ts
236
+ ```
237
+
238
+ ## Asset Audit Table
239
+
240
+ Add this to AGENTS.md:
241
+
242
+ ```markdown
243
+ ## Third-Party Scripts
244
+
245
+ | Script | Pages | Load Strategy | Action |
246
+ |--------|-------|---------------|--------|
247
+ | GTM | All | Head | ✅ OK |
248
+ | Chat Widget | All | Eager | 🔴 Make lazy |
249
+ | Reviews | PDP | Eager | 🟡 Consider lazy |
250
+ | Payment | Checkout | Conditional | ✅ OK |
251
+ ```
@@ -0,0 +1,189 @@
1
+ # Bug Fix Checklist
2
+
3
+ 8 learnings from real Deco sites. Check these during analysis.
4
+
5
+ ## Defensive Coding
6
+
7
+ ### 1. Defensive Prop Handling
8
+ **Check**: Are CMS-configurable props accessed safely?
9
+
10
+ ```typescript
11
+ // Bad: Crashes on undefined
12
+ const title = props.title.toUpperCase();
13
+ const items = props.items.map(i => i.name);
14
+
15
+ // Good: Optional chaining
16
+ const title = props.title?.toUpperCase() ?? "";
17
+ const items = props.items?.map(i => i?.name) ?? [];
18
+ ```
19
+
20
+ CMS props can be:
21
+ - Undefined (not configured)
22
+ - Null (explicitly cleared)
23
+ - Empty arrays/strings
24
+
25
+ ### 2. Safe Request Parsing
26
+ **Check**: Are API routes handling malformed requests?
27
+
28
+ ```typescript
29
+ // Bad: Crashes on empty/malformed body
30
+ export async function handler(req: Request) {
31
+ const body = await req.json();
32
+ return Response.json({ ok: true });
33
+ }
34
+
35
+ // Good: Try-catch wrapper
36
+ export async function handler(req: Request) {
37
+ try {
38
+ const body = await req.json();
39
+ // ... process
40
+ } catch (e) {
41
+ return new Response("Bad Request", { status: 400 });
42
+ }
43
+ }
44
+ ```
45
+
46
+ ### 3. Current Product Exclusion
47
+ **Check**: Do "Related Products" shelves include current product?
48
+
49
+ ```typescript
50
+ // Good: Filter out current product
51
+ const relatedProducts = allProducts.filter(p => p.id !== currentProductId);
52
+ ```
53
+
54
+ ## Content Sanitization
55
+
56
+ ### 4. Protocol Upgrade Filter
57
+ **Check**: Does external content have `http://` links?
58
+
59
+ ```typescript
60
+ // Good: Upgrade to HTTPS
61
+ function sanitizeContent(html: string): string {
62
+ return html.replace(/http:\/\//g, 'https://');
63
+ }
64
+
65
+ // Apply to product descriptions, CMS content, etc.
66
+ <div dangerouslySetInnerHTML={{
67
+ __html: sanitizeContent(product.description)
68
+ }} />
69
+ ```
70
+
71
+ Mixed content blocks images, scripts, and iframes.
72
+
73
+ ### 5. UTM Injection Prevention
74
+ **Check**: Are empty links being processed?
75
+
76
+ ```typescript
77
+ // Bad: Crashes on empty href
78
+ document.querySelectorAll('a').forEach(link => {
79
+ const url = new URL(link.href); // Crashes if href is ""
80
+ url.searchParams.set('utm_source', 'site');
81
+ link.href = url.toString();
82
+ });
83
+
84
+ // Good: Validate first
85
+ document.querySelectorAll('a[href]').forEach(link => {
86
+ if (!link.href || link.href === '#') return;
87
+ try {
88
+ const url = new URL(link.href);
89
+ url.searchParams.set('utm_source', 'site');
90
+ link.href = url.toString();
91
+ } catch {}
92
+ });
93
+ ```
94
+
95
+ ## SEO & Indexing
96
+
97
+ ### 6. Soft Out-of-Stock Handling
98
+ **Check**: Do out-of-stock pages return 404?
99
+
100
+ ```typescript
101
+ // Bad: 404 for out-of-stock (loses SEO)
102
+ if (!product.available) {
103
+ return new Response("Not Found", { status: 404 });
104
+ }
105
+
106
+ // Good: 200 with unavailable state
107
+ if (!product.available) {
108
+ return renderUnavailablePage(product); // Status 200
109
+ }
110
+ ```
111
+
112
+ Out-of-stock products should:
113
+ - Return 200 status
114
+ - Show "unavailable" UI
115
+ - Keep structured data
116
+ - Maintain SEO value
117
+
118
+ ## UI Stability
119
+
120
+ ### 7. Smooth Image Transitions
121
+ **Check**: Do hover effects cause flickering?
122
+
123
+ ```css
124
+ /* Bad: Flicker on hover */
125
+ .product-card:hover .secondary-image {
126
+ display: block; /* Hidden class uses display:none */
127
+ }
128
+
129
+ /* Good: Opacity transition */
130
+ .product-card .secondary-image {
131
+ opacity: 0;
132
+ transition: opacity 0.3s;
133
+ }
134
+ .product-card:hover .secondary-image {
135
+ opacity: 1;
136
+ }
137
+ ```
138
+
139
+ Never combine `display: none` with opacity transitions.
140
+
141
+ ### 8. Pricing Consistency
142
+ **Check**: Is promotional logic duplicated?
143
+
144
+ ```typescript
145
+ // Bad: Different calculations in different places
146
+ // ProductCard.tsx
147
+ const price = product.price * 0.9;
148
+
149
+ // ProductDetails.tsx
150
+ const price = product.price - 10;
151
+
152
+ // Good: Centralized utility
153
+ // utils/pricing.ts
154
+ export function calculateFinalPrice(product: Product): number {
155
+ const promotion = getActivePromotion(product);
156
+ return applyPromotion(product.price, promotion);
157
+ }
158
+ ```
159
+
160
+ Centralize:
161
+ - Discount calculations
162
+ - Promotion logic
163
+ - Price formatting
164
+
165
+ ## Quick Audit Commands
166
+
167
+ ```bash
168
+ # Find unsafe prop access (no optional chaining)
169
+ grep -rn "props\.\w\+\." sections/ | grep -v "props\.\w\+?\."
170
+
171
+ # Find direct URL construction without try-catch
172
+ grep -rn "new URL" islands/ | grep -v "try"
173
+
174
+ # Find http:// in content
175
+ grep -r "http://" .deco/blocks/*.json | grep -v "https://"
176
+
177
+ # Find 404 responses
178
+ grep -r "status: 404" loaders/ sections/
179
+ ```
180
+
181
+ ## Common Bug Patterns
182
+
183
+ | Bug | Symptom | Fix |
184
+ |-----|---------|-----|
185
+ | Null prop access | White screen, error in console | Add optional chaining |
186
+ | Mixed content | Images not loading | Upgrade http to https |
187
+ | OOS 404 | SEO drops for seasonal items | Return 200 with unavailable UI |
188
+ | Duplicate pricing | Different prices across site | Centralize price logic |
189
+ | Flickering images | Visual glitch on hover | Use opacity not display |
@@ -0,0 +1,144 @@
1
+ # Cache Strategy Checklist
2
+
3
+ 7 learnings from real Deco sites. Check these during analysis.
4
+
5
+ ## Loader Caching
6
+
7
+ ### 1. Stale-While-Revalidate Pattern
8
+ **Check**: Do custom loaders have cache configuration?
9
+
10
+ ```typescript
11
+ // Good: Has caching
12
+ export const cache = "stale-while-revalidate";
13
+
14
+ export const cacheKey = (props: Props) =>
15
+ `${props.productId}-${props.locale}`;
16
+
17
+ export default async function loader(props: Props) {
18
+ // ...
19
+ }
20
+ ```
21
+
22
+ ### 2. Deterministic Cache Keys
23
+ **Check**: Are cache keys based on unique identifiers?
24
+
25
+ ```typescript
26
+ // Bad: Uses full URL (includes tracking params)
27
+ export const cacheKey = (props: Props, req: Request) => req.url;
28
+
29
+ // Good: Uses only relevant data
30
+ export const cacheKey = (props: Props) => {
31
+ const facets = [...(props.facets || [])].sort();
32
+ return `${props.query}-${facets.join(",")}`;
33
+ };
34
+ ```
35
+
36
+ **Common mistakes**:
37
+ - Including UTM parameters in cache key
38
+ - Including session/user-specific data
39
+ - Using unsorted arrays (order changes = cache miss)
40
+
41
+ ### 3. Loader Deduplication via Shared Blocks
42
+ **Check**: Are the same loaders configured inline in multiple places?
43
+
44
+ ```json
45
+ // Bad: Same loader inline in multiple pages
46
+ // pages-Home.json, pages-PLP.json, pages-PDP.json all have:
47
+ { "loader": { "productId": "..." } }
48
+
49
+ // Good: Reference shared block
50
+ { "__resolveType": "$live/loaders/Loader.tsx", "loader": "PDP-Main-Loader" }
51
+ ```
52
+
53
+ Benefits:
54
+ - Single cache entry for same data
55
+ - Easier to update
56
+ - Better hit rate
57
+
58
+ ## Rate Limiting
59
+
60
+ ### 4. Bot-Specific Rate Limiting
61
+ **Check**: Do bots and users share rate limits?
62
+
63
+ ```typescript
64
+ // In _middleware.ts
65
+ const isBot = req.headers.get("user-agent")?.includes("bot");
66
+
67
+ if (isBot) {
68
+ // Apply stricter rate limiting for bots
69
+ const botRateLimit = await checkBotRateLimit(ip);
70
+ if (botRateLimit.exceeded) {
71
+ return new Response("Too Many Requests", { status: 429 });
72
+ }
73
+ }
74
+ ```
75
+
76
+ ### 5. Granular Rate Limit Tracking
77
+ **Check**: Is rate limiting per-endpoint or global?
78
+ - Track rate limits per endpoint for critical paths
79
+ - Allow more requests to cached endpoints
80
+
81
+ ## SSR Caching
82
+
83
+ ### 6. SSR Promotion Fetching
84
+ **Check**: Is promotion data fetched client-side causing CLS?
85
+ - Fetch discount/promotion rules on server
86
+ - Prevents price flickering
87
+
88
+ ```typescript
89
+ // Good: Fetch on server
90
+ export default async function ProductCard({ product }: Props) {
91
+ const promotion = await fetchPromotion(product.id);
92
+ const finalPrice = applyPromotion(product.price, promotion);
93
+ return <Card price={finalPrice} />;
94
+ }
95
+ ```
96
+
97
+ ### 7. Related Products Caching
98
+ **Check**: Do related product loaders have cache?
99
+ - Often high-volume, low-change-rate
100
+ - Good candidate for aggressive caching
101
+
102
+ ```typescript
103
+ export const cache = "stale-while-revalidate";
104
+ export const cacheKey = (props: Props) => `related-${props.productId}`;
105
+ ```
106
+
107
+ ## Cache Audit Table
108
+
109
+ Add this to AGENTS.md:
110
+
111
+ ```markdown
112
+ ## Caching Inventory
113
+
114
+ | Loader | Cache | Cache Key | Priority |
115
+ |--------|-------|-----------|----------|
116
+ | `loaders/search/intelligentSearch.ts` | ❌ None | - | 🔴 High |
117
+ | `loaders/product/buyTogether.ts` | ✅ SWR | productId | - |
118
+ | `loaders/getUserGeolocation.ts` | ❌ None | - | 🟡 Medium |
119
+ | `vtex/loaders/categories/tree.ts` | ❌ None | - | 🔴 High |
120
+ ```
121
+
122
+ ## Quick Audit Commands
123
+
124
+ ```bash
125
+ # Find loaders without cache
126
+ grep -L "export const cache" loaders/**/*.ts
127
+
128
+ # Find loaders with cache but no cacheKey
129
+ grep -l "export const cache" loaders/**/*.ts | xargs grep -L "cacheKey"
130
+
131
+ # Find inline loaders in page blocks (should be shared)
132
+ grep -r '"loader":' .deco/blocks/pages-*.json | grep -v "__resolveType"
133
+ ```
134
+
135
+ ## Common Cache Durations
136
+
137
+ | Content Type | Strategy | TTL |
138
+ |--------------|----------|-----|
139
+ | Product details | SWR | 5 min |
140
+ | Category tree | SWR | 1 hour |
141
+ | Search results | SWR | 1 min |
142
+ | Reviews | SWR | 15 min |
143
+ | Static content | SWR | 1 day |
144
+ | User-specific | None | - |