@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.
- package/.cursor/skills/deco-api-call-dedup/SKILL.md +443 -0
- package/.cursor/skills/deco-apps-architecture/SKILL.md +255 -0
- package/.cursor/skills/deco-apps-architecture/app-pattern.md +288 -0
- package/.cursor/skills/deco-apps-architecture/commerce-types.md +239 -0
- package/.cursor/skills/deco-apps-architecture/new-app-guide.md +268 -0
- package/.cursor/skills/deco-apps-architecture/scripts-codegen.md +148 -0
- package/.cursor/skills/deco-apps-architecture/shared-utils.md +181 -0
- package/.cursor/skills/deco-apps-architecture/vtex-deep-structure.md +253 -0
- package/.cursor/skills/deco-apps-architecture/website-app.md +169 -0
- package/.cursor/skills/deco-apps-vtex-porting/SKILL.md +189 -0
- package/.cursor/skills/deco-apps-vtex-porting/adaptation-patterns.md +335 -0
- package/.cursor/skills/deco-apps-vtex-porting/commerce-porting.md +155 -0
- package/.cursor/skills/deco-apps-vtex-porting/cookie-auth-patterns.md +148 -0
- package/.cursor/skills/deco-apps-vtex-porting/structure-map.md +234 -0
- package/.cursor/skills/deco-apps-vtex-porting/transform-mapping.md +99 -0
- package/.cursor/skills/deco-apps-vtex-porting/website-porting.md +194 -0
- package/.cursor/skills/deco-apps-vtex-review/SKILL.md +234 -0
- package/.cursor/skills/deco-async-rendering-architecture/SKILL.md +270 -0
- package/.cursor/skills/deco-async-rendering-site-guide/SKILL.md +417 -0
- package/.cursor/skills/deco-cms-layout-caching/SKILL.md +293 -0
- package/.cursor/skills/deco-cms-route-config/SKILL.md +388 -0
- package/.cursor/skills/deco-core-architecture/SKILL.md +185 -0
- package/.cursor/skills/deco-core-architecture/blocks.md +196 -0
- package/.cursor/skills/deco-core-architecture/deco-vs-deco-start.md +191 -0
- package/.cursor/skills/deco-core-architecture/engine.md +220 -0
- package/.cursor/skills/deco-core-architecture/hooks-components.md +157 -0
- package/.cursor/skills/deco-core-architecture/plugins-clients.md +136 -0
- package/.cursor/skills/deco-core-architecture/runtime.md +116 -0
- package/.cursor/skills/deco-core-architecture/site-usage.md +165 -0
- package/.cursor/skills/deco-e2e-testing/SKILL.md +372 -0
- package/.cursor/skills/deco-e2e-testing/discovery.md +337 -0
- package/.cursor/skills/deco-e2e-testing/scripts/scaffold.sh +81 -0
- package/.cursor/skills/deco-e2e-testing/selectors.md +175 -0
- package/.cursor/skills/deco-e2e-testing/templates/package.json +18 -0
- package/.cursor/skills/deco-e2e-testing/templates/playwright.config.ts +65 -0
- package/.cursor/skills/deco-e2e-testing/templates/scripts/baseline.ts +279 -0
- package/.cursor/skills/deco-e2e-testing/templates/scripts/run-e2e.ts +194 -0
- package/.cursor/skills/deco-e2e-testing/templates/specs/ecommerce-flow.spec.ts +612 -0
- package/.cursor/skills/deco-e2e-testing/templates/tsconfig.json +12 -0
- package/.cursor/skills/deco-e2e-testing/templates/utils/metrics-collector.ts +918 -0
- package/.cursor/skills/deco-e2e-testing/troubleshooting.md +602 -0
- package/.cursor/skills/deco-edge-caching/SKILL.md +316 -0
- package/.cursor/skills/deco-full-analysis/SKILL.md +898 -0
- package/.cursor/skills/deco-full-analysis/checklists/asset-optimization.md +251 -0
- package/.cursor/skills/deco-full-analysis/checklists/bug-fix.md +189 -0
- package/.cursor/skills/deco-full-analysis/checklists/cache-strategy.md +144 -0
- package/.cursor/skills/deco-full-analysis/checklists/dependency-update.md +150 -0
- package/.cursor/skills/deco-full-analysis/checklists/hydration-fix.md +191 -0
- package/.cursor/skills/deco-full-analysis/checklists/image-optimization.md +180 -0
- package/.cursor/skills/deco-full-analysis/checklists/loader-optimization.md +165 -0
- package/.cursor/skills/deco-full-analysis/checklists/seo-fix.md +183 -0
- package/.cursor/skills/deco-full-analysis/checklists/site-cleanup.md +281 -0
- package/.cursor/skills/deco-full-analysis/discovery.md +548 -0
- package/.cursor/skills/deco-incident-debugging/SKILL.md +378 -0
- package/.cursor/skills/deco-incident-debugging/headless-mode.md +510 -0
- package/.cursor/skills/deco-incident-debugging/learnings-index.md +227 -0
- package/.cursor/skills/deco-incident-debugging/triage-workflow.md +312 -0
- package/.cursor/skills/deco-islands-migration/SKILL.md +251 -0
- package/.cursor/skills/deco-loader-n-plus-1-detector/SKILL.md +275 -0
- package/.cursor/skills/deco-performance-audit/SKILL.md +530 -0
- package/.cursor/skills/deco-performance-audit/tools-reference.md +428 -0
- package/.cursor/skills/deco-performance-audit/workflow.md +457 -0
- package/.cursor/skills/deco-server-functions-invoke/SKILL.md +92 -0
- package/.cursor/skills/deco-server-functions-invoke/architecture.md +166 -0
- package/.cursor/skills/deco-server-functions-invoke/generator.md +122 -0
- package/.cursor/skills/deco-server-functions-invoke/problem.md +98 -0
- package/.cursor/skills/deco-server-functions-invoke/troubleshooting.md +110 -0
- package/.cursor/skills/deco-site-deployment/SKILL.md +396 -0
- package/.cursor/skills/deco-site-memory-debugging/SKILL.md +121 -0
- package/.cursor/skills/deco-site-memory-debugging/cdp-connection.md +222 -0
- package/.cursor/skills/deco-site-memory-debugging/memory-analysis.md +362 -0
- package/.cursor/skills/deco-site-patterns/SKILL.md +124 -0
- package/.cursor/skills/deco-site-patterns/app-composition.md +337 -0
- package/.cursor/skills/deco-site-patterns/client-patterns.md +341 -0
- package/.cursor/skills/deco-site-patterns/cms-wiring.md +230 -0
- package/.cursor/skills/deco-site-patterns/section-patterns.md +340 -0
- package/.cursor/skills/deco-site-scaling-tuning/SKILL.md +240 -0
- package/.cursor/skills/deco-site-scaling-tuning/analysis-scripts.md +267 -0
- package/.cursor/skills/deco-start-architecture/SKILL.md +218 -0
- package/.cursor/skills/deco-start-architecture/admin-protocol.md +156 -0
- package/.cursor/skills/deco-start-architecture/cms-resolution.md +201 -0
- package/.cursor/skills/deco-start-architecture/code-quality.md +158 -0
- package/.cursor/skills/deco-start-architecture/gap-analysis.md +129 -0
- package/.cursor/skills/deco-start-architecture/sdk-utilities.md +197 -0
- package/.cursor/skills/deco-start-architecture/worker-entry-caching.md +154 -0
- package/.cursor/skills/deco-startup-analysis/SKILL.md +248 -0
- package/.cursor/skills/deco-storefront-test-checklist/SKILL.md +369 -0
- package/.cursor/skills/deco-tanstack-hydration-fixes/SKILL.md +468 -0
- package/.cursor/skills/deco-tanstack-navigation/SKILL.md +681 -0
- package/.cursor/skills/deco-tanstack-search/SKILL.md +411 -0
- package/.cursor/skills/deco-tanstack-storefront-patterns/SKILL.md +1013 -0
- package/.cursor/skills/deco-to-tanstack-migration/SKILL.md +518 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/codemod-commands.md +174 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/commerce/README.md +78 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/deco-framework/README.md +128 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/gotchas.md +719 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/imports/README.md +70 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/platform-hooks/README.md +154 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/signals/README.md +220 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/vite-config/README.md +78 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/package-json.md +55 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/root-route.md +110 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/router.md +96 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/setup-ts.md +167 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/vite-config.md +122 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/worker-entry.md +67 -0
- package/.cursor/skills/deco-typescript-fixes/SKILL.md +178 -0
- package/.cursor/skills/deco-typescript-fixes/common-fixes.md +330 -0
- package/.cursor/skills/deco-typescript-fixes/strategy.md +148 -0
- package/.cursor/skills/deco-variant-selection-perf/SKILL.md +272 -0
- package/.cursor/skills/deco-vtex-fetch-cache/SKILL.md +225 -0
- package/.cursor/skills/find-skills/SKILL.md +133 -0
- package/.cursor/skills/incident-report/SKILL.md +179 -0
- package/.cursor/skills/incident-report/references/5-whys.md +75 -0
- package/.cursor/skills/incident-report/templates/client-report.md +187 -0
- package/.cursor/skills/incident-report/templates/internal-report.md +206 -0
- package/.cursor/skills/template-skill/SKILL.md +38 -0
- package/.github/workflows/release.yml +32 -0
- package/.releaserc.json +25 -0
- package/CLAUDE.md +135 -0
- package/GAP_ANALYSIS.md +224 -0
- package/GAP_ANALYSIS_V2.md +1013 -0
- package/biome.json +39 -0
- package/knip.json +5 -0
- package/package.json +87 -0
- package/scripts/generate-blocks.ts +69 -0
- package/scripts/generate-invoke.ts +378 -0
- package/scripts/generate-schema.ts +657 -0
- package/src/admin/cors.ts +29 -0
- package/src/admin/decofile.ts +72 -0
- package/src/admin/index.ts +24 -0
- package/src/admin/invoke.ts +163 -0
- package/src/admin/liveControls.ts +29 -0
- package/src/admin/meta.ts +70 -0
- package/src/admin/render.ts +205 -0
- package/src/admin/schema.ts +686 -0
- package/src/admin/setup.ts +44 -0
- package/src/cms/index.ts +59 -0
- package/src/cms/loader.ts +180 -0
- package/src/cms/registry.ts +162 -0
- package/src/cms/resolve.ts +1005 -0
- package/src/cms/sectionLoaders.ts +294 -0
- package/src/hooks/DecoPageRenderer.tsx +444 -0
- package/src/hooks/LazySection.tsx +109 -0
- package/src/hooks/LiveControls.tsx +108 -0
- package/src/hooks/SectionErrorFallback.tsx +85 -0
- package/src/hooks/index.ts +8 -0
- package/src/index.ts +5 -0
- package/src/matchers/builtins.ts +184 -0
- package/src/matchers/posthog.ts +154 -0
- package/src/middleware/decoState.ts +55 -0
- package/src/middleware/healthMetrics.ts +131 -0
- package/src/middleware/index.ts +80 -0
- package/src/middleware/liveness.ts +21 -0
- package/src/middleware/observability.ts +205 -0
- package/src/routes/adminRoutes.ts +83 -0
- package/src/routes/cmsRoute.ts +302 -0
- package/src/routes/components.tsx +34 -0
- package/src/routes/index.ts +15 -0
- package/src/sdk/analytics.ts +72 -0
- package/src/sdk/cacheHeaders.ts +268 -0
- package/src/sdk/cachedLoader.ts +206 -0
- package/src/sdk/clx.ts +3 -0
- package/src/sdk/cookie.ts +39 -0
- package/src/sdk/createInvoke.ts +57 -0
- package/src/sdk/csp.ts +59 -0
- package/src/sdk/env.ts +27 -0
- package/src/sdk/index.ts +63 -0
- package/src/sdk/instrumentedFetch.ts +137 -0
- package/src/sdk/invoke.ts +133 -0
- package/src/sdk/mergeCacheControl.ts +150 -0
- package/src/sdk/redirects.ts +217 -0
- package/src/sdk/requestContext.ts +184 -0
- package/src/sdk/serverTimings.ts +68 -0
- package/src/sdk/signal.ts +41 -0
- package/src/sdk/sitemap.ts +143 -0
- package/src/sdk/urlUtils.ts +117 -0
- package/src/sdk/useDevice.ts +82 -0
- package/src/sdk/useId.ts +7 -0
- package/src/sdk/useScript.ts +101 -0
- package/src/sdk/workerEntry.ts +703 -0
- package/src/sdk/wrapCaughtErrors.ts +107 -0
- package/src/types/index.ts +39 -0
- package/src/types/widgets.ts +13 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Dependency Update Checklist
|
|
2
|
+
|
|
3
|
+
3 learnings from real Deco sites. Check these during analysis.
|
|
4
|
+
|
|
5
|
+
## Framework Updates
|
|
6
|
+
|
|
7
|
+
### 1. Deco Platform Upgrade
|
|
8
|
+
**Check**: Is the site on latest Deco version?
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
// deno.json - check versions
|
|
12
|
+
{
|
|
13
|
+
"imports": {
|
|
14
|
+
"@deco/deco": "jsr:@deco/deco@1.x.x", // Check for latest
|
|
15
|
+
"@deco/dev": "jsr:@deco/dev@x.x.x"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**How to check latest**:
|
|
21
|
+
- Visit https://jsr.io/@deco/deco
|
|
22
|
+
- Compare with current version in deno.json
|
|
23
|
+
|
|
24
|
+
**Benefits of updating**:
|
|
25
|
+
- Performance patches
|
|
26
|
+
- Bug fixes for image handling
|
|
27
|
+
- New features
|
|
28
|
+
- Security updates
|
|
29
|
+
|
|
30
|
+
### 2. Apps Version Alignment
|
|
31
|
+
**Check**: Are deco and apps versions synchronized?
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
// deno.json
|
|
35
|
+
{
|
|
36
|
+
"imports": {
|
|
37
|
+
"@deco/deco": "jsr:@deco/deco@1.100.0",
|
|
38
|
+
"apps/": "https://cdn.jsdelivr.net/gh/deco-cx/apps@0.60.0/"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Alignment matters because**:
|
|
44
|
+
- Breaking changes may affect compatibility
|
|
45
|
+
- Feature parity between framework and apps
|
|
46
|
+
- Image optimization improvements
|
|
47
|
+
|
|
48
|
+
**Check release notes**:
|
|
49
|
+
- https://github.com/deco-cx/deco/releases
|
|
50
|
+
- https://github.com/deco-cx/apps/releases
|
|
51
|
+
|
|
52
|
+
### 3. Deco 2.0 Migration
|
|
53
|
+
**Check**: Is the site on Deco 2.0?
|
|
54
|
+
|
|
55
|
+
**Deco 2.0 benefits**:
|
|
56
|
+
- Partytown integration
|
|
57
|
+
- Optimized Apps architecture
|
|
58
|
+
- Better performance defaults
|
|
59
|
+
- Improved developer experience
|
|
60
|
+
|
|
61
|
+
**Signs of old architecture**:
|
|
62
|
+
- Using `deco-sites/std` imports
|
|
63
|
+
- Old loader patterns
|
|
64
|
+
- Missing Fresh 1.7+ features
|
|
65
|
+
|
|
66
|
+
## Update Process
|
|
67
|
+
|
|
68
|
+
### Pre-Update Checklist
|
|
69
|
+
|
|
70
|
+
1. **Backup**: Commit current state
|
|
71
|
+
2. **Test**: Run e2e tests before update
|
|
72
|
+
3. **Review**: Check release notes for breaking changes
|
|
73
|
+
4. **Staging**: Test update in staging environment
|
|
74
|
+
|
|
75
|
+
### Update Commands
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Check current versions
|
|
79
|
+
grep -E "@deco/deco|apps/" deno.json
|
|
80
|
+
|
|
81
|
+
# Update deno.json imports manually
|
|
82
|
+
# Then run:
|
|
83
|
+
deno cache --reload main.ts
|
|
84
|
+
|
|
85
|
+
# Test the update
|
|
86
|
+
deno task dev
|
|
87
|
+
deno task test:e2e
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Post-Update Checklist
|
|
91
|
+
|
|
92
|
+
- [ ] Site builds successfully
|
|
93
|
+
- [ ] Dev server starts
|
|
94
|
+
- [ ] Key pages load (Home, PDP, PLP)
|
|
95
|
+
- [ ] E2E tests pass
|
|
96
|
+
- [ ] No console errors
|
|
97
|
+
- [ ] Images loading correctly
|
|
98
|
+
|
|
99
|
+
## Version Compatibility Matrix
|
|
100
|
+
|
|
101
|
+
| Deco Version | Apps Version | Fresh | Notes |
|
|
102
|
+
|--------------|--------------|-------|-------|
|
|
103
|
+
| 1.100+ | 0.60+ | 1.7+ | Current stable |
|
|
104
|
+
| 1.90-1.99 | 0.55-0.59 | 1.6+ | Stable |
|
|
105
|
+
| <1.90 | <0.55 | 1.5 | Consider upgrade |
|
|
106
|
+
|
|
107
|
+
## Quick Audit Commands
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Show current versions
|
|
111
|
+
grep -E '"@deco|"apps/' deno.json
|
|
112
|
+
|
|
113
|
+
# Check for deco-sites/std (legacy)
|
|
114
|
+
grep -r "deco-sites/std" sections/ loaders/ components/
|
|
115
|
+
|
|
116
|
+
# Check Fresh version
|
|
117
|
+
grep '\$fresh' deno.json
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Dependency Audit Table
|
|
121
|
+
|
|
122
|
+
Add this to AGENTS.md:
|
|
123
|
+
|
|
124
|
+
```markdown
|
|
125
|
+
## Dependencies
|
|
126
|
+
|
|
127
|
+
| Package | Current | Latest | Action |
|
|
128
|
+
|---------|---------|--------|--------|
|
|
129
|
+
| @deco/deco | 1.95.0 | 1.102.0 | 🟡 Consider update |
|
|
130
|
+
| apps/ | 0.58.0 | 0.62.0 | 🟡 Consider update |
|
|
131
|
+
| Fresh | 1.7.3 | 1.7.3 | ✅ Up to date |
|
|
132
|
+
| Preact | 10.23.1 | 10.23.1 | ✅ Up to date |
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## When to Update
|
|
136
|
+
|
|
137
|
+
**Update immediately**:
|
|
138
|
+
- Security vulnerabilities
|
|
139
|
+
- Critical bug fixes affecting your site
|
|
140
|
+
- Required for new features you need
|
|
141
|
+
|
|
142
|
+
**Update with planning**:
|
|
143
|
+
- Major version bumps
|
|
144
|
+
- Architecture changes
|
|
145
|
+
- When you have time to test thoroughly
|
|
146
|
+
|
|
147
|
+
**Delay if**:
|
|
148
|
+
- In the middle of a sprint
|
|
149
|
+
- Before major sales events
|
|
150
|
+
- No clear benefit
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Hydration Fix Checklist
|
|
2
|
+
|
|
3
|
+
9 learnings from real Deco sites. Check these during analysis.
|
|
4
|
+
|
|
5
|
+
## SDK & Script Race Conditions
|
|
6
|
+
|
|
7
|
+
### 1. SDK Initialization Guard
|
|
8
|
+
**Check**: Do components assume SDK is ready?
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
// Bad: Race condition
|
|
12
|
+
const { cart } = useCart(); // May be undefined
|
|
13
|
+
|
|
14
|
+
// Good: Wait for SDK
|
|
15
|
+
async function waitForSDK() {
|
|
16
|
+
while (!window.__STOREFRONT_SDK__) {
|
|
17
|
+
await new Promise(r => setTimeout(r, 50));
|
|
18
|
+
}
|
|
19
|
+
return window.__STOREFRONT_SDK__;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const sdk = await waitForSDK();
|
|
23
|
+
const cart = sdk.cart;
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Script Dependency Synchronization
|
|
27
|
+
**Check**: Do components wait for external scripts?
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// Good: Wait for HTMX
|
|
31
|
+
function waitFor(check: () => boolean, timeout = 5000): Promise<void> {
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
if (check()) return resolve();
|
|
34
|
+
const start = Date.now();
|
|
35
|
+
const interval = setInterval(() => {
|
|
36
|
+
if (check()) { clearInterval(interval); resolve(); }
|
|
37
|
+
if (Date.now() - start > timeout) { clearInterval(interval); reject(); }
|
|
38
|
+
}, 50);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
await waitFor(() => window.htmx !== undefined);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 3. Safe Browser API Access
|
|
46
|
+
**Check**: Are `window`/`document` accessed during SSR?
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
// Bad: Crashes on SSR
|
|
50
|
+
const width = window.innerWidth;
|
|
51
|
+
|
|
52
|
+
// Good: Check for browser
|
|
53
|
+
import { IS_BROWSER } from "$fresh/runtime.ts";
|
|
54
|
+
|
|
55
|
+
const width = IS_BROWSER ? window.innerWidth : 1024;
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Unique IDs
|
|
59
|
+
|
|
60
|
+
### 4. Deterministic useId
|
|
61
|
+
**Check**: Are there hydration mismatches with IDs?
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// Bad: Random IDs cause mismatch
|
|
65
|
+
const id = Math.random().toString(36);
|
|
66
|
+
|
|
67
|
+
// Good: Deterministic based on props
|
|
68
|
+
function useStableId(prefix: string, index: number) {
|
|
69
|
+
return `${prefix}-${index}`;
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Or use a custom deterministic ID generator if `useId()` causes issues.
|
|
74
|
+
|
|
75
|
+
## External Widgets
|
|
76
|
+
|
|
77
|
+
### 5. Onload Script Guard
|
|
78
|
+
**Check**: Are external widgets manipulated before load?
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
// Bad: Widget may not exist
|
|
82
|
+
document.querySelector('.hubspot-form').style.display = 'block';
|
|
83
|
+
|
|
84
|
+
// Good: Wait for load
|
|
85
|
+
script.onload = () => {
|
|
86
|
+
const widget = document.querySelector('.hubspot-form');
|
|
87
|
+
if (widget) widget.style.display = 'block';
|
|
88
|
+
};
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 6. MutationObserver for Third-Party Widgets
|
|
92
|
+
**Check**: Do third-party widgets need conditional styling?
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// Good: Watch for widget insertion
|
|
96
|
+
const observer = new MutationObserver((mutations) => {
|
|
97
|
+
const widget = document.querySelector('.review-widget');
|
|
98
|
+
if (widget) {
|
|
99
|
+
widget.classList.add('loaded');
|
|
100
|
+
observer.disconnect();
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## HTML Content
|
|
108
|
+
|
|
109
|
+
### 7. HTML Repair Utility
|
|
110
|
+
**Check**: Is `dangerouslySetInnerHTML` used with external content?
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// Bad: Broken HTML causes hydration errors
|
|
114
|
+
<div dangerouslySetInnerHTML={{ __html: product.description }} />
|
|
115
|
+
|
|
116
|
+
// Good: Sanitize and repair
|
|
117
|
+
import DOMPurify from "dompurify";
|
|
118
|
+
|
|
119
|
+
function repairHtml(html: string): string {
|
|
120
|
+
// Close unclosed tags, fix nesting
|
|
121
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
122
|
+
return DOMPurify.sanitize(doc.body.innerHTML);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
<div dangerouslySetInnerHTML={{ __html: repairHtml(product.description) }} />
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Lazy Loading
|
|
129
|
+
|
|
130
|
+
### 8. Deferred Portal Rendering
|
|
131
|
+
**Check**: Are heavy drawers rendered on mount?
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// Good: Lazy render minicart/menu
|
|
135
|
+
import { createPortal } from "preact/compat";
|
|
136
|
+
|
|
137
|
+
function Minicart() {
|
|
138
|
+
const [show, setShow] = useState(false);
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<>
|
|
142
|
+
<button onClick={() => setShow(true)}>Cart</button>
|
|
143
|
+
{show && createPortal(<MinicartContent />, document.body)}
|
|
144
|
+
</>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 9. Interaction-based Lazy Hydration
|
|
150
|
+
**Check**: Are heavy navigation menus loaded eagerly?
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
// Good: Load drawer content on first interaction
|
|
154
|
+
function Header() {
|
|
155
|
+
const [menuLoaded, setMenuLoaded] = useState(false);
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<button
|
|
159
|
+
onMouseEnter={() => setMenuLoaded(true)}
|
|
160
|
+
onClick={() => setMenuLoaded(true)}
|
|
161
|
+
>
|
|
162
|
+
Menu
|
|
163
|
+
</button>
|
|
164
|
+
{menuLoaded && <MegaMenu />}
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Quick Audit Commands
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Find direct window/document access
|
|
173
|
+
grep -rn "window\." islands/ | grep -v "IS_BROWSER"
|
|
174
|
+
grep -rn "document\." islands/ | grep -v "IS_BROWSER"
|
|
175
|
+
|
|
176
|
+
# Find dangerouslySetInnerHTML usage
|
|
177
|
+
grep -r "dangerouslySetInnerHTML" sections/ islands/
|
|
178
|
+
|
|
179
|
+
# Find Math.random in components (ID generation)
|
|
180
|
+
grep -r "Math.random" sections/ islands/ components/
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Common Hydration Issues
|
|
184
|
+
|
|
185
|
+
| Symptom | Likely Cause | Fix |
|
|
186
|
+
|---------|--------------|-----|
|
|
187
|
+
| "Text content mismatch" | Date/time formatting | Use consistent timezone |
|
|
188
|
+
| "Expected server HTML" | `useDevice()` for layout | Use CSS media queries |
|
|
189
|
+
| "Hydration failed" | Random IDs | Use deterministic IDs |
|
|
190
|
+
| White flash | Script race condition | Add SDK initialization guard |
|
|
191
|
+
| Missing styles | CSS-in-JS during SSR | Use Tailwind or static CSS |
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Image Optimization Checklist
|
|
2
|
+
|
|
3
|
+
18 learnings from real Deco sites. Check these during analysis.
|
|
4
|
+
|
|
5
|
+
## LCP (Largest Contentful Paint)
|
|
6
|
+
|
|
7
|
+
### 1. LCP Image Prioritization
|
|
8
|
+
**Check**: Does the LCP image have correct attributes?
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
// Good: LCP image
|
|
12
|
+
<Image
|
|
13
|
+
src={bannerUrl}
|
|
14
|
+
loading="eager" // NOT "lazy"
|
|
15
|
+
fetchPriority="high" // Prioritize network fetch
|
|
16
|
+
decoding="sync" // Don't defer decoding
|
|
17
|
+
preload // Add link preload header
|
|
18
|
+
/>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 2. Banner Carousel First Item
|
|
22
|
+
**Check**: Is the first carousel item prioritized?
|
|
23
|
+
- First banner: `loading="eager"`, `fetchPriority="high"`
|
|
24
|
+
- Other banners: `loading="lazy"`
|
|
25
|
+
|
|
26
|
+
### 3. PLP First Products
|
|
27
|
+
**Check**: Are the first 4-6 product images prioritized?
|
|
28
|
+
```tsx
|
|
29
|
+
{products.map((p, i) => (
|
|
30
|
+
<Image
|
|
31
|
+
loading={i < 6 ? "eager" : "lazy"}
|
|
32
|
+
fetchPriority={i < 4 ? "high" : "auto"}
|
|
33
|
+
/>
|
|
34
|
+
))}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 4. Full-width Hero Optimization
|
|
38
|
+
**Check**: Do LCP banners have restrictive styles?
|
|
39
|
+
- Use `w-full` without max-width constraints
|
|
40
|
+
- Avoid padding that causes layout shift
|
|
41
|
+
|
|
42
|
+
### 5. Preload Background Images
|
|
43
|
+
**Check**: Are CSS background images preloaded?
|
|
44
|
+
```tsx
|
|
45
|
+
// In section, add preload header
|
|
46
|
+
ctx.response.headers.append(
|
|
47
|
+
"Link",
|
|
48
|
+
`<${imageUrl}>; rel="preload"; as="image"; fetchpriority="high"`
|
|
49
|
+
);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Image Component
|
|
53
|
+
|
|
54
|
+
### 6. Use Deco Image Component
|
|
55
|
+
**Check**: Are all images using `<Image />`?
|
|
56
|
+
- Enables automatic CDN optimization
|
|
57
|
+
- Requires explicit `width` and `height`
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
// Good
|
|
61
|
+
import { Image } from "apps/website/components/Image.tsx";
|
|
62
|
+
<Image src={url} width={300} height={200} />
|
|
63
|
+
|
|
64
|
+
// Bad
|
|
65
|
+
<img src={url} />
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 7. Platform Standard Optimization
|
|
69
|
+
**Check**: Are custom URL parsers used instead of standard?
|
|
70
|
+
- Use `getOptimizedMediaUrl` from apps/website
|
|
71
|
+
- Don't parse VTEX image URLs manually
|
|
72
|
+
|
|
73
|
+
### 8. URL Sanitization
|
|
74
|
+
**Check**: Do image URLs contain special characters?
|
|
75
|
+
- Sanitize URLs from external APIs
|
|
76
|
+
- Remove characters like `§` that break optimization
|
|
77
|
+
|
|
78
|
+
## Special Cases
|
|
79
|
+
|
|
80
|
+
### 9. SVG Handling
|
|
81
|
+
**Check**: Are SVGs going through image optimization?
|
|
82
|
+
- SVGs don't need raster optimization
|
|
83
|
+
- Use wrapper to bypass proxy for SVGs
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
// Skip optimization for SVG
|
|
87
|
+
if (src.endsWith('.svg')) {
|
|
88
|
+
return <img src={src} {...props} />;
|
|
89
|
+
}
|
|
90
|
+
return <Image src={src} {...props} />;
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 10. Animated WebP/GIF
|
|
94
|
+
**Check**: Are animated images becoming static?
|
|
95
|
+
- Disable optimization for animated WebP/GIF
|
|
96
|
+
- Check `animate` flag in VTEX URLs
|
|
97
|
+
|
|
98
|
+
### 11. VTEX Image Resizing
|
|
99
|
+
**Check**: Are VTEX images using correct dimensions?
|
|
100
|
+
```typescript
|
|
101
|
+
// Transform VTEX image URL
|
|
102
|
+
function getVtexImageUrl(url: string, width: number, height: number) {
|
|
103
|
+
return url.replace(/\-\d+\-\d+/, `-${width}-${height}`);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Responsive Images
|
|
108
|
+
|
|
109
|
+
### 12. CSS-based Responsiveness
|
|
110
|
+
**Check**: Is `useDevice()` used for responsive images?
|
|
111
|
+
- Prefer `<picture>` and CSS media queries
|
|
112
|
+
- Avoids hydration mismatches
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
// Good: CSS-based
|
|
116
|
+
<picture>
|
|
117
|
+
<source media="(max-width: 768px)" srcSet={mobileUrl} />
|
|
118
|
+
<Image src={desktopUrl} />
|
|
119
|
+
</picture>
|
|
120
|
+
|
|
121
|
+
// Avoid: JS-based
|
|
122
|
+
const device = useDevice();
|
|
123
|
+
return device === "mobile" ? <MobileImg /> : <DesktopImg />;
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 13. Breakpoint Precision
|
|
127
|
+
**Check**: Do responsive breakpoints overlap?
|
|
128
|
+
- Use non-overlapping breakpoints
|
|
129
|
+
- Prevent loading wrong image size
|
|
130
|
+
|
|
131
|
+
### 14. Sizes Attribute
|
|
132
|
+
**Check**: Do images have `sizes` attribute?
|
|
133
|
+
```tsx
|
|
134
|
+
<Image
|
|
135
|
+
sizes="(max-width: 768px) 100vw, 50vw"
|
|
136
|
+
/>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Layout Stability
|
|
140
|
+
|
|
141
|
+
### 15. Aspect Ratio Reservation
|
|
142
|
+
**Check**: Do images cause CLS?
|
|
143
|
+
- Wrap in containers with `aspect-ratio`
|
|
144
|
+
- Or use fixed dimensions
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
<div class="aspect-video">
|
|
148
|
+
<Image class="object-cover w-full h-full" />
|
|
149
|
+
</div>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 16. Object-Fit for Banners
|
|
153
|
+
**Check**: Do banners crop marketing text?
|
|
154
|
+
- Use `object-fit: contain` for text-heavy banners
|
|
155
|
+
- Use `object-fit: cover` for full-bleed images
|
|
156
|
+
|
|
157
|
+
## UI Patterns
|
|
158
|
+
|
|
159
|
+
### 17. CSS-Based Peek Animation
|
|
160
|
+
**Check**: Are scroll animations JS-based?
|
|
161
|
+
- Prefer CSS keyframes for "product peeking" hints
|
|
162
|
+
- Reduces TBT
|
|
163
|
+
|
|
164
|
+
### 18. LCP Isolation
|
|
165
|
+
**Check**: Is LCP element in a complex section?
|
|
166
|
+
- Isolate LCP into standalone section
|
|
167
|
+
- Reduces render blocking
|
|
168
|
+
|
|
169
|
+
## Quick Audit Commands
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Find images without width/height
|
|
173
|
+
grep -r "<img" sections/ components/ | grep -v "width"
|
|
174
|
+
|
|
175
|
+
# Find images using native img instead of Image component
|
|
176
|
+
grep -rn "<img src" sections/ islands/
|
|
177
|
+
|
|
178
|
+
# Find useDevice in image components
|
|
179
|
+
grep -r "useDevice" sections/ | grep -i image
|
|
180
|
+
```
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Loader Optimization Checklist
|
|
2
|
+
|
|
3
|
+
33 learnings from real Deco sites. Check these during analysis.
|
|
4
|
+
|
|
5
|
+
## Critical Patterns
|
|
6
|
+
|
|
7
|
+
### 1. Lazy Section Wrapping
|
|
8
|
+
**Check**: Are below-fold sections with heavy loaders wrapped in `Lazy`?
|
|
9
|
+
- BuyTogether, ProductShelf, Reviews, SimilarProducts
|
|
10
|
+
- Any section that fetches data and isn't above the fold
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
// Good: Wrapped in Lazy
|
|
14
|
+
{
|
|
15
|
+
"__resolveType": "website/sections/Rendering/Lazy.tsx",
|
|
16
|
+
"section": { "__resolveType": "site/sections/Product/BuyTogether.tsx" }
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 2. AbortController Timeout
|
|
21
|
+
**Check**: Do external API calls have timeout protection?
|
|
22
|
+
- Reviews APIs, recommendation APIs, third-party services
|
|
23
|
+
- Add `AbortController` with reasonable timeout (5-10s)
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// Good: Has timeout
|
|
27
|
+
const controller = new AbortController();
|
|
28
|
+
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
29
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 3. Client-Side Data Fetching for Below-Fold
|
|
33
|
+
**Check**: Are PDP loaders blocking on below-fold content?
|
|
34
|
+
- Move `fetchSimilars`, `fetchReviews`, `fetchRelated` to client-side islands
|
|
35
|
+
- Don't block SSR on non-critical data
|
|
36
|
+
|
|
37
|
+
### 4. Remove Sync Product Loaders from Header
|
|
38
|
+
**Check**: Does Header have product loaders that block render?
|
|
39
|
+
- Headers should be fast and static
|
|
40
|
+
- Move product data to islands or separate sections
|
|
41
|
+
|
|
42
|
+
## VTEX-Specific
|
|
43
|
+
|
|
44
|
+
### 5. Simulation Behavior
|
|
45
|
+
**Check**: Is VTEX simulation set correctly?
|
|
46
|
+
|
|
47
|
+
| Setting | Use Case |
|
|
48
|
+
|---------|----------|
|
|
49
|
+
| `skip` | Maximum performance, no real-time pricing |
|
|
50
|
+
| `only1P` | Balanced - first-party simulation only |
|
|
51
|
+
| `default` | Full simulation (slower) |
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
// In VTEX loader config
|
|
55
|
+
simulationBehavior: "only1P" // or "skip" for PLPs
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 6. Intelligent Search Migration
|
|
59
|
+
**Check**: Are you using legacy loaders?
|
|
60
|
+
- Replace `deco-sites/std` loaders with `vtex/loaders/intelligentSearch`
|
|
61
|
+
- Replace legacy cross-selling with Intelligent Search
|
|
62
|
+
|
|
63
|
+
### 7. Legacy Loader Fallback
|
|
64
|
+
**Check**: Do category paths fail to resolve?
|
|
65
|
+
- If Intelligent Search fails, try Legacy VTEX loader as fallback
|
|
66
|
+
|
|
67
|
+
## Loader Architecture
|
|
68
|
+
|
|
69
|
+
### 8. Loader Deduplication via Blocks
|
|
70
|
+
**Check**: Are common loaders duplicated across pages?
|
|
71
|
+
- Use shared loader blocks instead of inline configurations
|
|
72
|
+
- Centralizes PDP/PLP loaders for cache deduplication
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
// Good: Reference shared block
|
|
76
|
+
{ "__resolveType": "$live/loaders/Loader.tsx", "loader": "PDP-Main-Loader" }
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 9. Loader Simplification
|
|
80
|
+
**Check**: Are there redundant loaders?
|
|
81
|
+
- Remove loaders that only pass through data already available
|
|
82
|
+
- Avoid manual `fetch` calls when standard loaders exist
|
|
83
|
+
|
|
84
|
+
### 10. Cascading Fallback Search
|
|
85
|
+
**Check**: Do recommendation loaders return empty?
|
|
86
|
+
- Implement fallback: Subcategory → Category → Global
|
|
87
|
+
- Prevents empty shelves
|
|
88
|
+
|
|
89
|
+
## Performance Patterns
|
|
90
|
+
|
|
91
|
+
### 11. Batch and Debounce
|
|
92
|
+
**Check**: Are there high-frequency small API calls?
|
|
93
|
+
- Batch review/stock/rating calls into single loader
|
|
94
|
+
- Use client-side debouncing
|
|
95
|
+
|
|
96
|
+
### 12. API Result Limiting
|
|
97
|
+
**Check**: Do loaders fetch too much data?
|
|
98
|
+
- Always apply limits to review/comment loaders
|
|
99
|
+
- Use pagination for large datasets
|
|
100
|
+
|
|
101
|
+
### 13. Concurrent Batch Fetching
|
|
102
|
+
**Check**: Are multi-item lookups sequential?
|
|
103
|
+
```typescript
|
|
104
|
+
// Bad: Sequential
|
|
105
|
+
for (const id of ids) { await fetch(id); }
|
|
106
|
+
|
|
107
|
+
// Good: Parallel
|
|
108
|
+
await Promise.all(ids.map(id => fetch(id)));
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 14. Cursor Pagination
|
|
112
|
+
**Check**: Do infinite scroll lists use offset pagination?
|
|
113
|
+
- Use cursor-based pagination for better scaling
|
|
114
|
+
|
|
115
|
+
## Custom Loaders
|
|
116
|
+
|
|
117
|
+
### 15. Global Signal Caching
|
|
118
|
+
**Check**: Do multiple components make the same API call?
|
|
119
|
+
- Use global signals or shared cache
|
|
120
|
+
- Prevents duplicate cashback/loyalty requests
|
|
121
|
+
|
|
122
|
+
### 16. Retail API Integration
|
|
123
|
+
**Check**: Are personalization APIs using correct session IDs?
|
|
124
|
+
- Extract visitor/session ID from cookies correctly
|
|
125
|
+
|
|
126
|
+
### 17. External API Loaders
|
|
127
|
+
**Check**: Do loaders have proper error handling?
|
|
128
|
+
- Use `ctx.invoke` instead of raw `fetch` where possible
|
|
129
|
+
- Add timeout and retry logic
|
|
130
|
+
|
|
131
|
+
### 18. Slug Normalization
|
|
132
|
+
**Check**: Do collection URLs work consistently?
|
|
133
|
+
- Normalize slugs and database keys using same logic
|
|
134
|
+
|
|
135
|
+
## Section Optimization
|
|
136
|
+
|
|
137
|
+
### 19. Section Deferral
|
|
138
|
+
**Check**: Are heavy non-LCP sections deferred?
|
|
139
|
+
- Complex headers/footers can use Lazy rendering
|
|
140
|
+
- Balance against UX
|
|
141
|
+
|
|
142
|
+
### 20. Skeleton Fallbacks
|
|
143
|
+
**Check**: Do async sections have loading states?
|
|
144
|
+
```typescript
|
|
145
|
+
export function LoadingFallback() {
|
|
146
|
+
return <div class="skeleton h-64 w-full" />;
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 21. Deferred Tab Loading
|
|
151
|
+
**Check**: Do tabbed components load all tabs on server?
|
|
152
|
+
- Use `isDeferred` and `asResolved` to load only active tab
|
|
153
|
+
|
|
154
|
+
## Quick Audit Commands
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Find loaders without cache
|
|
158
|
+
grep -L "export const cache" loaders/**/*.ts
|
|
159
|
+
|
|
160
|
+
# Find sections not wrapped in Lazy
|
|
161
|
+
grep -r "__resolveType.*sections" .deco/blocks/pages-*.json | grep -v "Lazy"
|
|
162
|
+
|
|
163
|
+
# Find fetch calls in loaders (should use ctx.invoke)
|
|
164
|
+
grep -r "await fetch" loaders/
|
|
165
|
+
```
|