@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,165 @@
|
|
|
1
|
+
# How a Deco Site Uses the Framework
|
|
2
|
+
|
|
3
|
+
Reference based on `deco-sites/osklenbr`, a production VTEX storefront using Fresh/Preact.
|
|
4
|
+
|
|
5
|
+
## Site Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
osklenbr/
|
|
9
|
+
|-- deno.json # Dependencies, tasks, import map
|
|
10
|
+
|-- fresh.config.ts # Fresh + Deco plugin registration
|
|
11
|
+
|-- manifest.gen.ts # Auto-generated manifest (site blocks)
|
|
12
|
+
|-- fresh.gen.ts # Auto-generated Fresh manifest (routes + islands)
|
|
13
|
+
|-- runtime.ts # Typed invoke client
|
|
14
|
+
|-- main.ts # Production entry: start(manifest, config)
|
|
15
|
+
|-- dev.ts # Dev entry: tailwind build + dotenv + Fresh dev
|
|
16
|
+
|
|
|
17
|
+
|-- apps/ # App registrations (site.ts, decohub.ts)
|
|
18
|
+
|-- sections/ # 117 UI sections (Preact components)
|
|
19
|
+
|-- islands/ # 99 interactive islands (Preact)
|
|
20
|
+
|-- loaders/ # 13 site-specific loaders
|
|
21
|
+
|-- actions/ # 4 site-specific actions
|
|
22
|
+
|-- routes/ # 2 routes (_app.tsx, proxy.ts)
|
|
23
|
+
|-- sdk/ # Client-side utilities
|
|
24
|
+
|-- components/ # Shared Preact components
|
|
25
|
+
|-- static/ # Static assets
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Configuration
|
|
29
|
+
|
|
30
|
+
### deno.json
|
|
31
|
+
|
|
32
|
+
Key imports: `$fresh/` (Fresh 1.7.3), `@deco/deco` (1.174.2), `apps/` (deco-cx/apps 0.139.0), `$store/` and `site/` (self-reference).
|
|
33
|
+
|
|
34
|
+
Tasks: `start` (production via deco.cx/run), `dev` (generate + Fresh dev), `gen` (manifest generation).
|
|
35
|
+
|
|
36
|
+
JSX: `react-jsx` with `preact` import source.
|
|
37
|
+
|
|
38
|
+
### fresh.config.ts
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { defineConfig } from "$fresh/server.ts";
|
|
42
|
+
import { plugins } from "deco/plugins/deco.ts";
|
|
43
|
+
import manifest from "./manifest.gen.ts";
|
|
44
|
+
|
|
45
|
+
export default defineConfig({
|
|
46
|
+
plugins: plugins({ manifest, htmx: false }),
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### runtime.ts
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { proxy } from "@deco/deco/web";
|
|
54
|
+
import type { Manifest } from "./manifest.gen.ts";
|
|
55
|
+
import type { Manifest as VTEXManifest } from "apps/vtex/manifest.gen.ts";
|
|
56
|
+
|
|
57
|
+
export const invoke = proxy<Manifest & VTEXManifest>();
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## App Registration (`apps/`)
|
|
61
|
+
|
|
62
|
+
### apps/site.ts
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import manifest, { Manifest } from "../manifest.gen.ts";
|
|
66
|
+
import { type App, type AppContext as AC } from "@deco/deco";
|
|
67
|
+
import commerce from "apps/commerce/mod.ts";
|
|
68
|
+
import std from "apps/compat/std/mod.ts";
|
|
69
|
+
|
|
70
|
+
export type AppContext = AC<ReturnType<typeof Site>>;
|
|
71
|
+
|
|
72
|
+
export default function Site(state: Props): App<
|
|
73
|
+
Manifest, Props, [typeof std, ReturnType<typeof commerce>]
|
|
74
|
+
> {
|
|
75
|
+
return {
|
|
76
|
+
state,
|
|
77
|
+
manifest,
|
|
78
|
+
dependencies: [std(state), commerce(state)],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Key pattern: site app bundles manifest + commerce dependencies. `AppContext` enables typed `ctx.invoke()`.
|
|
84
|
+
|
|
85
|
+
### apps/decohub.ts
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
export { default, Preview } from "apps/decohub/mod.ts";
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Execution Flow
|
|
92
|
+
|
|
93
|
+
### Production
|
|
94
|
+
```
|
|
95
|
+
main.ts -> fresh.gen.ts + fresh.config.ts -> start(manifest, config)
|
|
96
|
+
-> Fresh server starts
|
|
97
|
+
-> Deco plugin initializes
|
|
98
|
+
-> Loads DecofileProvider (CMS state)
|
|
99
|
+
-> Installs apps (site -> commerce -> vtex)
|
|
100
|
+
-> Registers all block resolvers
|
|
101
|
+
-> Mounts routes + middleware
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Dev
|
|
105
|
+
```
|
|
106
|
+
dev.ts -> Build Tailwind -> Load .env -> Fresh dev server -> Generate manifest -> Hot reload
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Manifest System
|
|
110
|
+
|
|
111
|
+
### manifest.gen.ts (Deco)
|
|
112
|
+
|
|
113
|
+
Contains loaders (13), sections (117), actions (4), matchers (1), apps (2). Keys formatted as `site/loaders/...`, `site/sections/...`.
|
|
114
|
+
|
|
115
|
+
### fresh.gen.ts (Fresh)
|
|
116
|
+
|
|
117
|
+
Contains routes (2) and islands (99). Generated by Fresh from the Deco plugin.
|
|
118
|
+
|
|
119
|
+
## Loader/Action Patterns
|
|
120
|
+
|
|
121
|
+
### Site Loader
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import { AppContext } from "site/apps/site.ts";
|
|
125
|
+
|
|
126
|
+
export default async function loader(
|
|
127
|
+
props: Props,
|
|
128
|
+
_req: Request,
|
|
129
|
+
ctx: AppContext,
|
|
130
|
+
): Promise<Store[]> {
|
|
131
|
+
// fetch data, transform, return
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Invoking Other Apps
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
export default async function loader(props: Props, _req: Request, ctx: AppContext) {
|
|
139
|
+
const products = await ctx.invoke(
|
|
140
|
+
"vtex/loaders/intelligentSearch/productListingPage.ts",
|
|
141
|
+
{ query: props.query, count: 12 },
|
|
142
|
+
);
|
|
143
|
+
return products;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Routes
|
|
148
|
+
|
|
149
|
+
`_app.tsx` is the global layout. Page routes are NOT file-based; they come from the CMS admin decofile.
|
|
150
|
+
|
|
151
|
+
## Migration Patterns for TanStack
|
|
152
|
+
|
|
153
|
+
| Fresh/Deco Pattern | TanStack Equivalent |
|
|
154
|
+
|--------------------|---------------------|
|
|
155
|
+
| `manifest.gen.ts` | Explicit exports from `@decocms/apps-start` |
|
|
156
|
+
| `runtime.ts` invoke proxy | Direct function imports + React Query |
|
|
157
|
+
| Islands | Regular React components |
|
|
158
|
+
| Fresh `<Partial>` | TanStack Router navigation |
|
|
159
|
+
| `useSection()` partial render | React state + React Query invalidation |
|
|
160
|
+
| `ctx.invoke("key", props)` | Direct function call: `loaderFn(props)` |
|
|
161
|
+
| `AppContext` | `configureVtex()` + env vars |
|
|
162
|
+
| Deco plugin | TanStack Start entry + `@decocms/start` |
|
|
163
|
+
| DecofileProvider | Admin API from `@decocms/start` |
|
|
164
|
+
| `@preact/signals` | `@tanstack/react-store` or React state |
|
|
165
|
+
| `Deno.env.get()` | `process.env` or `import.meta.env` |
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deco-e2e-testing
|
|
3
|
+
description: Implement end-to-end performance tests for any Deco e-commerce site with lazy section tracking, cache analysis, and observability. Use this skill when asked to set up e2e tests, create performance testing infrastructure, or test user journeys on a Deco/VTEX site.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Deco E2E Performance Testing Skill
|
|
7
|
+
|
|
8
|
+
This skill helps you implement comprehensive e2e performance tests for Deco e-commerce sites. It covers the full user journey: Home → PLP → PDP → Add to Cart, with **lazy section tracking**, **cache analysis**, and **device-specific reports**.
|
|
9
|
+
|
|
10
|
+
## When to Use This Skill
|
|
11
|
+
|
|
12
|
+
- Setting up e2e tests from scratch on a Deco site
|
|
13
|
+
- Creating performance testing infrastructure
|
|
14
|
+
- Testing cache performance (cold vs warm)
|
|
15
|
+
- Validating TTFB, FCP, and other Core Web Vitals
|
|
16
|
+
- **Debugging slow lazy sections** (`/deco/render` requests)
|
|
17
|
+
- **Analyzing page cache and CDN behavior**
|
|
18
|
+
- **Comparing performance across desktop/mobile**
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
1. **Discover site-specific values** (read `discovery.md`)
|
|
23
|
+
2. **Run scaffold script** or copy templates manually
|
|
24
|
+
3. **Configure selectors** for your site
|
|
25
|
+
4. **Add deno.json tasks** for easy test execution
|
|
26
|
+
5. **Run tests** and verify
|
|
27
|
+
|
|
28
|
+
## Workflow
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
1. Read discovery.md → Find site-specific selectors
|
|
32
|
+
2. Run scaffold.sh → Create test directory structure
|
|
33
|
+
3. Replace {{PLACEHOLDERS}} → Customize for site
|
|
34
|
+
4. Add deno.json tasks → Enable `deno task test:e2e`
|
|
35
|
+
5. npm install && deno task test:e2e → Verify tests work
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Directory Structure to Create
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
tests/e2e/
|
|
42
|
+
├── README.md
|
|
43
|
+
├── package.json
|
|
44
|
+
├── playwright.config.ts
|
|
45
|
+
├── tsconfig.json
|
|
46
|
+
├── specs/
|
|
47
|
+
│ └── ecommerce-flow.spec.ts
|
|
48
|
+
├── utils/
|
|
49
|
+
│ └── metrics-collector.ts
|
|
50
|
+
├── scripts/
|
|
51
|
+
│ └── baseline.ts
|
|
52
|
+
└── reports/ # gitignored
|
|
53
|
+
├── report-desktop-chrome.json
|
|
54
|
+
├── report-mobile-chrome.json
|
|
55
|
+
└── baselines/
|
|
56
|
+
|
|
57
|
+
scripts/
|
|
58
|
+
└── run-e2e.ts # Test runner with server management
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Test Flow
|
|
62
|
+
|
|
63
|
+
| Step | Page | Metrics |
|
|
64
|
+
|------|------|---------|
|
|
65
|
+
| 1 | Server Warmup | Liveness check, lazy import trigger |
|
|
66
|
+
| 2 | Homepage (cold cache) | TTFB, FCP, lazy sections, scroll |
|
|
67
|
+
| 3 | Homepage (warm cache) | Cache improvement |
|
|
68
|
+
| 4 | PLP (cold cache) | TTFB, products loaded, lazy sections |
|
|
69
|
+
| 5 | PLP (warm cache) | Cache improvement |
|
|
70
|
+
| 6 | PDP (cold cache) | TTFB, buy button, lazy sections |
|
|
71
|
+
| 7 | PDP (warm cache) | Cache improvement |
|
|
72
|
+
| 8 | Add to Cart | Response time |
|
|
73
|
+
| 9 | Minicart | Verification (with retry) |
|
|
74
|
+
|
|
75
|
+
## Key Features
|
|
76
|
+
|
|
77
|
+
### 1. Lazy Section Tracking
|
|
78
|
+
|
|
79
|
+
The test tracks all `/deco/render` requests (lazy-loaded sections) with:
|
|
80
|
+
- **Section name** extracted from `x-deco-section` header
|
|
81
|
+
- **Timing** with color-coded status (🟢 fast, 🟡 medium, 🔴 slow)
|
|
82
|
+
- **Cache status** (💾 HIT, ❌ MISS, ⏳ STALE)
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
🔄 Lazy Sections (14):
|
|
86
|
+
┌───────────────────────────────────────────────────────────
|
|
87
|
+
│ 🔴 Product/ProductShelf: L... 1182ms 💾 cached
|
|
88
|
+
│ 🔴 Product/ProductShelfGroup 1000ms 💾 cached
|
|
89
|
+
│ 🟢 Footer/Footer 13ms 💾 cached
|
|
90
|
+
└───────────────────────────────────────────────────────────
|
|
91
|
+
📊 Summary: 5 fast, 2 medium, 7 slow │ Total: 7121ms
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 2. Scroll-Based Lazy Loading
|
|
95
|
+
|
|
96
|
+
The test scrolls the page to trigger lazy sections and waits for them:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
// Scroll until footer is visible, waiting for pending renders
|
|
100
|
+
await collector.scrollPage(page, true) // full=true for homepage
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
This ensures all lazy sections are triggered and their performance is measured.
|
|
104
|
+
|
|
105
|
+
### 3. Device-Specific Reports
|
|
106
|
+
|
|
107
|
+
Tests run on both desktop and mobile with separate reports:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
reports/
|
|
111
|
+
├── report-desktop-chrome.json
|
|
112
|
+
├── report-mobile-chrome.json
|
|
113
|
+
├── report-latest-desktop.json
|
|
114
|
+
└── report-latest-mobile.json
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 4. Enhanced Report Structure
|
|
118
|
+
|
|
119
|
+
Reports include a summary for easy comparison:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"project": "desktop-chrome",
|
|
124
|
+
"timestamp": "2026-01-18T...",
|
|
125
|
+
"summary": {
|
|
126
|
+
"totalPages": 7,
|
|
127
|
+
"avgTTFB": 485,
|
|
128
|
+
"avgFCP": 892,
|
|
129
|
+
"totalLazyRenders": 32,
|
|
130
|
+
"totalLoaders": 12,
|
|
131
|
+
"cacheHits": 28,
|
|
132
|
+
"cacheMisses": 4,
|
|
133
|
+
"pages": [...]
|
|
134
|
+
},
|
|
135
|
+
"metrics": [...]
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 5. Deco Observability Headers
|
|
140
|
+
|
|
141
|
+
The test captures custom Deco headers for debugging:
|
|
142
|
+
- `x-deco-section` - Section component type and title
|
|
143
|
+
- `x-deco-page` - Matched page block name
|
|
144
|
+
- `x-deco-route` - Matched route template
|
|
145
|
+
|
|
146
|
+
## Critical: Server Warmup
|
|
147
|
+
|
|
148
|
+
**Deco/Fresh lazily loads imports on first request.** This causes artificially high latency for the first request after server start. The test must:
|
|
149
|
+
|
|
150
|
+
1. Wait for `/deco/_liveness` endpoint to return 200
|
|
151
|
+
2. Make a warmup request to trigger lazy imports
|
|
152
|
+
3. Only then start measuring performance
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
const LIVENESS_PATH = '/deco/_liveness'
|
|
156
|
+
|
|
157
|
+
async function waitForServerReady(baseUrl: string) {
|
|
158
|
+
// Step 1: Wait for liveness
|
|
159
|
+
for (let i = 0; i < 30; i++) {
|
|
160
|
+
const res = await fetch(`${baseUrl}/deco/_liveness`)
|
|
161
|
+
if (res.ok) break
|
|
162
|
+
await new Promise(r => setTimeout(r, 1000))
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Step 2: Warmup request to trigger lazy imports
|
|
166
|
+
await fetch(`${baseUrl}/?__d`)
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Key Configuration
|
|
171
|
+
|
|
172
|
+
The `SITE_CONFIG` object centralizes all site-specific values:
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
const SITE_CONFIG = {
|
|
176
|
+
// URLs
|
|
177
|
+
baseUrl: 'https://localhost--{sitename}.deco.site',
|
|
178
|
+
plpPath: '/category-path',
|
|
179
|
+
fallbackPdpPath: '/product-name-sku/p',
|
|
180
|
+
|
|
181
|
+
// Always use ?__d for Server-Timing headers
|
|
182
|
+
debugParam: '?__d',
|
|
183
|
+
|
|
184
|
+
// Deco framework endpoints
|
|
185
|
+
livenessPath: '/deco/_liveness',
|
|
186
|
+
|
|
187
|
+
// Selectors
|
|
188
|
+
productCard: '[data-deco="view-product"]',
|
|
189
|
+
productCardFallback: 'a:has-text("R$")',
|
|
190
|
+
buyButton: 'button:has-text("Comprar agora")',
|
|
191
|
+
buyButtonFallback: 'button:has-text("Comprar")',
|
|
192
|
+
minicartText: 'Produtos Adicionados',
|
|
193
|
+
|
|
194
|
+
// Sizes (fashion) or voltages (electronics)
|
|
195
|
+
sizes: ['P', 'M', 'G', 'GG'],
|
|
196
|
+
voltages: ['110V', '127V', '220V', 'Bivolt'],
|
|
197
|
+
|
|
198
|
+
// Thresholds (ms)
|
|
199
|
+
thresholds: {
|
|
200
|
+
coldTTFB: 5000,
|
|
201
|
+
warmTTFB: 2000,
|
|
202
|
+
homeTTFB: 3000,
|
|
203
|
+
homeWarmTTFB: 1500,
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
// Server warmup settings
|
|
207
|
+
warmup: {
|
|
208
|
+
livenessRetries: 30,
|
|
209
|
+
livenessRetryDelay: 1000,
|
|
210
|
+
warmupTimeout: 60000,
|
|
211
|
+
},
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## deno.json Integration
|
|
216
|
+
|
|
217
|
+
Add these tasks to the site's `deno.json`:
|
|
218
|
+
|
|
219
|
+
```json
|
|
220
|
+
{
|
|
221
|
+
"tasks": {
|
|
222
|
+
"test:e2e": "deno run -A scripts/run-e2e.ts",
|
|
223
|
+
"test:e2e:headed": "deno run -A scripts/run-e2e.ts --headed",
|
|
224
|
+
"test:e2e:install": "cd tests/e2e && npm install && npx playwright install chromium",
|
|
225
|
+
"test:e2e:baseline:save": "deno run -A tests/e2e/scripts/baseline.ts save",
|
|
226
|
+
"test:e2e:baseline:compare": "deno run -A tests/e2e/scripts/baseline.ts compare"
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## .gitignore Updates
|
|
232
|
+
|
|
233
|
+
Add to `.gitignore`:
|
|
234
|
+
|
|
235
|
+
```gitignore
|
|
236
|
+
# E2E test reports (generated artifacts)
|
|
237
|
+
tests/e2e/reports/report-*.json
|
|
238
|
+
tests/e2e/reports/test-results/
|
|
239
|
+
tests/e2e/reports/results.json
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Files in This Skill
|
|
243
|
+
|
|
244
|
+
| File | Purpose |
|
|
245
|
+
|------|---------|
|
|
246
|
+
| `SKILL.md` | This overview |
|
|
247
|
+
| `discovery.md` | How to find site-specific values |
|
|
248
|
+
| `templates/` | Ready-to-use test files |
|
|
249
|
+
| `templates/scripts/run-e2e.ts` | Test runner with server management |
|
|
250
|
+
| `templates/scripts/baseline.ts` | Baseline save/compare script |
|
|
251
|
+
| `selectors.md` | Platform-specific selector patterns |
|
|
252
|
+
| `troubleshooting.md` | Common issues and fixes |
|
|
253
|
+
| `scripts/scaffold.sh` | Auto-create test structure |
|
|
254
|
+
|
|
255
|
+
## Expected Output
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
══════════════════════════════════════════════════════════════════════
|
|
259
|
+
🖥️ Desktop (desktop-chrome)
|
|
260
|
+
══════════════════════════════════════════════════════════════════════
|
|
261
|
+
|
|
262
|
+
══════════════════════════════════════════════════════════════════════
|
|
263
|
+
🏠 HOMEPAGE (cold cache)
|
|
264
|
+
══════════════════════════════════════════════════════════════════════
|
|
265
|
+
📜 Scrolling to trigger lazy renders (full)...
|
|
266
|
+
⏳ Waiting for 1 pending render before next scroll...
|
|
267
|
+
✅ Footer visible after 47 scrolls
|
|
268
|
+
📜 Triggered 13 lazy renders
|
|
269
|
+
|
|
270
|
+
🟢 TTFB: 414ms 🟡 FCP: 1508ms │ 🌐 369 requests (11.7 MB)
|
|
271
|
+
|
|
272
|
+
⚡ Server Timing: 0ms total (1 loaders)
|
|
273
|
+
|
|
274
|
+
🔄 Lazy Sections (14):
|
|
275
|
+
┌───────────────────────────────────────────────────────────
|
|
276
|
+
│ 🔴 Product/ProductShelf: L... 1182ms 💾 cached
|
|
277
|
+
│ 🔴 Product/ProductShelfGroup 1000ms 💾 cached
|
|
278
|
+
│ 🟢 Content/SimpleText 18ms 💾 cached
|
|
279
|
+
│ 🟢 Footer/Footer 13ms 💾 cached
|
|
280
|
+
└───────────────────────────────────────────────────────────
|
|
281
|
+
📊 Summary: 5 fast, 2 medium, 7 slow │ Total: 7121ms
|
|
282
|
+
|
|
283
|
+
══════════════════════════════════════════════════════════════════════
|
|
284
|
+
📊 PERFORMANCE SUMMARY
|
|
285
|
+
══════════════════════════════════════════════════════════════════════
|
|
286
|
+
|
|
287
|
+
┌──────────────────┬─────────────┬─────────────┬────────┐
|
|
288
|
+
│ Page │ TTFB │ FCP │ Lazy │
|
|
289
|
+
├──────────────────┼─────────────┼─────────────┼────────┤
|
|
290
|
+
│ Homepage Cold │ 🟢 414ms │ 🟡 1508ms │ 14 │
|
|
291
|
+
│ Homepage Warm │ 🟢 485ms │ 🟢 560ms │ 4 │
|
|
292
|
+
│ PLP Cold │ 🟢 456ms │ 🟢 508ms │ 3 │
|
|
293
|
+
│ PDP Cold │ 🟢 459ms │ 🟢 520ms │ 4 │
|
|
294
|
+
└──────────────────┴─────────────┴─────────────┴────────┘
|
|
295
|
+
|
|
296
|
+
Legend: 🟢 Good 🟡 Needs Work 🔴 Poor
|
|
297
|
+
Thresholds: TTFB <500ms good, <800ms ok | FCP <1000ms good, <1800ms ok
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Baseline Comparison
|
|
301
|
+
|
|
302
|
+
Save performance baselines and compare future runs to detect regressions.
|
|
303
|
+
|
|
304
|
+
### Save a Baseline
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
deno task test:e2e:baseline:save
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Compare Against Baseline
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
deno task test:e2e:baseline:compare
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Regression Thresholds
|
|
317
|
+
|
|
318
|
+
| Metric | Threshold |
|
|
319
|
+
|--------|-----------|
|
|
320
|
+
| TTFB | +10% |
|
|
321
|
+
| FCP | +10% |
|
|
322
|
+
| LCP | +15% |
|
|
323
|
+
| CLS | +50% |
|
|
324
|
+
|
|
325
|
+
## Minicart Robustness
|
|
326
|
+
|
|
327
|
+
The minicart verification uses multiple selectors and retry logic:
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
async isMinicartOpen(): Promise<boolean> {
|
|
331
|
+
const selectors = [
|
|
332
|
+
`text=${SITE_CONFIG.minicartText}`,
|
|
333
|
+
'[data-testid="minicart"]',
|
|
334
|
+
'.minicart',
|
|
335
|
+
'[class*="minicart"]',
|
|
336
|
+
'[class*="cart-drawer"]',
|
|
337
|
+
]
|
|
338
|
+
|
|
339
|
+
// Retry with increasing timeout
|
|
340
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
341
|
+
const timeout = 2000 + (attempt * 1000)
|
|
342
|
+
for (const selector of selectors) {
|
|
343
|
+
const visible = await this.page.locator(selector).first()
|
|
344
|
+
.isVisible({ timeout }).catch(() => false)
|
|
345
|
+
if (visible) return true
|
|
346
|
+
}
|
|
347
|
+
await this.page.waitForTimeout(500)
|
|
348
|
+
}
|
|
349
|
+
return false
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## Integration with Deco Runtime
|
|
354
|
+
|
|
355
|
+
For full lazy section observability, ensure your deco runtime includes:
|
|
356
|
+
|
|
357
|
+
1. **x-deco-section header** in `/deco/render` responses
|
|
358
|
+
2. **x-deco-page header** with matched page block name
|
|
359
|
+
3. **x-deco-route header** with matched route template
|
|
360
|
+
|
|
361
|
+
These are set in:
|
|
362
|
+
- `deco/runtime/features/render.tsx` - Section name extraction
|
|
363
|
+
- `deco/runtime/routes/render.tsx` - Header setting
|
|
364
|
+
- `deco/runtime/middleware.ts` - Page/route headers
|
|
365
|
+
- `apps/website/handlers/fresh.ts` - Page block state
|
|
366
|
+
|
|
367
|
+
## Next Steps
|
|
368
|
+
|
|
369
|
+
1. Read `discovery.md` to learn how to find the correct selectors and paths
|
|
370
|
+
2. Check `selectors.md` for platform-specific patterns (VTEX, Shopify, VNDA)
|
|
371
|
+
3. See `troubleshooting.md` if tests fail
|
|
372
|
+
4. Use the MCP tools to search for related optimization patterns
|