Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .agents/skills/deco-v7-to-v8-migration/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Moves a v7 Deco site (@decocms/blocks 7.x with @decocms/tanstack or

# Deco v7 → v8 Migration

Moves a v7 site onto the next major in two parts: a script that does the mechanical, content-safe part in one pass, and a list of manual steps it prints. Proven on `deco-sites/storefront-tanstack` (Shopify, TanStack Start), `deco-sites/blog-tanstack` (TanStack Start), a Next.js App Router storefront on VTEX, a TanStack Start storefront on VTEX and a non-ejected FastStore storefront on VTEX (hundreds of saved blocks, private).
Moves a v7 site onto the next major in two parts: a script that does the mechanical, content-safe part in one pass, and a list of manual steps it prints. Proven on `deco-sites/storefront-tanstack` (Shopify, TanStack Start), `deco-sites/blog-tanstack` (TanStack Start), two Next.js App Router storefronts on VTEX (ejected FastStore), a TanStack Start storefront on VTEX and a non-ejected FastStore storefront on VTEX (hundreds of saved blocks, private).

The spec is the docs page **Migrating from v7** (`/next/renames-and-migrations`). When this skill and the docs disagree, the docs win.

Expand Down Expand Up @@ -69,12 +69,12 @@ The script prints **Done** and **Left to do**, grouped by step. Every "Left to d

## Manual steps (what the report leaves)

1. **Dependencies.** Depend on `@decocms/blocks@^8.1` and the v8 `@decocms/apps-<platform>` client. Remove `@decocms/tanstack`/`@decocms/nextjs`, `@decocms/blocks-admin`, `@decocms/blocks-cli`, `@decocms/apps-commerce`, `@decocms/apps-website` and `@decocms/apps-blog` once nothing imports them, and drop the v7 codegen from `build`. On Next.js, add `@decocms/blocks` to `transpilePackages` in `next.config`: the `8.1.0-next.*` prereleases publish TypeScript source (`exports` → `src/*.ts`), v7's `withDeco` wrapper used to add it, and without it a clean install fails `next build` with `Module parse failed: Unexpected token`.
1. **Dependencies.** Depend on `@decocms/blocks@^8.1` and the v8 `@decocms/apps-<platform>` client. Remove `@decocms/tanstack`/`@decocms/nextjs`, `@decocms/blocks-admin`, `@decocms/blocks-cli`, `@decocms/apps-commerce`, `@decocms/apps-website` and `@decocms/apps-blog` once nothing imports them, and drop the v7 codegen from `build`. On Next.js, check what the installed `@decocms/blocks` publishes: when its `exports` default to `dist/*.js` (`8.1.0-next.7` does), it needs no `transpilePackages` entry; a prerelease whose `exports` point at `src/*.ts` needs `@decocms/blocks` in `transpilePackages` (v7's `withDeco` wrapper used to add it), or a clean install fails `next build` with `Module parse failed: Unexpected token`.
2. **Render pages with `createCMS`.** Follow the framework guide (`/next/tanstack-start-descriptors`, `/next/nextjs`): `createCMS` over the content, `matchRoute`, one promise per block, a view registry. Delete the v7 setup files, admin routes and `/deco/*` handlers.
3. **Move framework code into the site** (`reference/gotchas.md`): edge cache, image, SEO/head, device detection, cookies, cart/user/wishlist flows, commerce loaders and converters.
4. **Replace `/deco/invoke`** with server functions (TanStack `createServerFn`) or Next server actions/route handlers. One exported server function per loader or action the browser called, and each call site imports the one it calls: `invoke.site.loaders.spin(props)` becomes `$siteLoadersSpin({ data: props })`. Don't rebuild the `invoke.x.y` tree or a string-keyed dispatcher over the commerce-loader map (see DO NOT); the server function calls its handler directly. Details in `reference/gotchas.md` (`/deco/invoke` → server functions).
5. **Fix the content `deco check` rejects**: fields no type declares, `.tsx`-named preview blocks, v7 app blocks (apps are code now), `requestToParam` blocks in string fields.
6. **Telemetry, analytics and previews**: the `telemetry` option of `createCMS` (`/next/telemetry`), with switches and rates in the `telemetry` section of `CMS.json`; `AnalyticsScript` with `const { analytics } = await cms.settings()` and `track` from `@decocms/blocks/analytics`; drafts through `await cms.draftPointer(request)` / `cms.draftCookie(request)`, which serve the release on hosts outside `preview.hosts` (list the dev host, `localhost`, too: v8 ignores `DECO_ALLOWED_PREVIEW_HOSTS`) (with no `previewHosts`, v7 allowed previews only on a TanStack site's `<site>.deco.site` and `<site>.deco-cx.workers.dev`, or nowhere; here every host may preview unless you list some, `/next/releases-and-drafts#allow-previews-per-host`). The report carries GTM/GA4 IDs over).
6. **Telemetry, analytics and previews**: the `telemetry` option of `createCMS` (`/next/telemetry`), with switches and rates in the `telemetry` section of `CMS.json`; `AnalyticsScript` with `const { analytics } = await cms.settings()` and `track` from `@decocms/blocks/analytics`; drafts through `await cms.draftPointer(request)` / `cms.draftCookie(request)`, which serve the release on hosts outside `preview.hosts` (list the dev server's host with its port too, e.g. `localhost:3000` for `next dev`, in both the code cap and `CMS.json`, and name each host you add for the product owner: v8 ignores `DECO_ALLOWED_PREVIEW_HOSTS`) (with no `previewHosts`, v7 allowed previews only on a TanStack site's `<site>.deco.site` and `<site>.deco-cx.workers.dev`, or nowhere; here every host may preview unless you list some, `/next/releases-and-drafts#allow-previews-per-host`). The report carries GTM/GA4 IDs over). If v7 sent no CMS telemetry, pointing `telemetry` at the site's existing collector is new traffic and cost there: list it as a behaviour change.

## Verify

Expand All @@ -91,6 +91,8 @@ Run it once more **without any local link** (a `decocms/blocks` checkout linked

**Probe drafts by hand** on the dev server and on a production build: `?__draft=<pointer>` on an allowed host renders the draft and sets the cookie, the cookie alone keeps the next page in the draft, a host outside `preview.hosts` and a malformed pointer get the release, `?__draft=off` clears the cookie. A parity harness can't catch a dead draft path when v7's was dead too: both sides render the release.

Grep the tree for v7 tooling in comments, docs and `.gitattributes` (`blocks-cli`, `meta.gen.json`, `sections.gen.ts`, `generate-schema`, `ts-morph`) and reword each to `deco schema` or the block map. Check that the claim still holds under `deco schema` (`/next/schema`) instead of renaming the tool: some v7 quirks are gone, and the comment should then say it was v7.

Then compare the migrated site with the v7 one page by page (a parity harness: SSR HTML, JSON-LD, analytics calls, cache headers, third-party requests). Compare the editor forms as well (v7 `meta.gen.json` vs v8 `schema.gen.json`): many differences are stale v7 files or v7 heuristics v8 drops on purpose, a few are CLI bugs to fix. Encode every difference the product owner approves as an explicit rule, never a blanket ignore. Keep explained-but-unapproved ones as `pending`, and have a strict compare fail on them (`reference/parity.md`).

## DO NOT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ FastStore's CMS pages are SSG and its CLI forbids `middleware`/`proxy` and `/api
## Preview hosts and draft sources

- `preview.hosts` in `CMS.json` must list the dev host (`localhost`) as well as the store's hosts, within the code cap in `createCMS({ preview })`. v8 ignores v7's `DECO_ALLOWED_PREVIEW_HOSTS`: remove it from env files and harness env too.
- Drafts need no site loader: `cms.forDraft` fetches the pointer itself, only from v7's preview API domains (`*.decocms.com` and the loopback hosts by default; `DECO_PREVIEW_API_DOMAINS` replaces the list, as in v7). Delete any draft-fetching loader the site kept from v7.
- Drafts need no site loader: `cms.forDraft` fetches the pointer itself, only from v7's preview API domains (`*.decocms.com` and the loopback hosts by default; `createCMS({ preview: { draftHosts } })` replaces the list. The SDK reads no environment variable, so v7's `DECO_PREVIEW_API_DOMAINS` is read by the site, if at all, and passed in). Delete any draft-fetching loader the site kept from v7.
- If the site keeps v7's policy that a draft that fails to load falls back to the release, write that down: the docs say a failed draft is an error.

## Content imported from FastStore's CMS
Expand Down
Loading
Loading