|
1 | | -# Storefront — deco.cx template |
2 | | - |
3 | | -Welcome to your [deco.cx](https://deco.cx) site! |
| 1 | +# storefront-tanstack |
4 | 2 |
|
5 | | -## Usage |
| 3 | +A [deco.cx](https://deco.cx) storefront built on **TanStack Start + React 19 + Cloudflare Workers**, with Shopify as the commerce backend. |
6 | 4 |
|
7 | | -0 |
| 5 | +This is a **site repo** — it consumes the [`@decocms/start`](https://www.npmjs.com/package/@decocms/start) framework (CMS bridge, admin protocol, worker entry, edge caching) and [`@decocms/apps`](https://www.npmjs.com/package/@decocms/apps) (commerce loaders/actions). UI, sections, and routes live here. |
8 | 6 |
|
9 | | -1 - [Install deno](https://docs.deno.com/runtime/manual/getting_started/installation/) |
| 7 | +## Stack |
10 | 8 |
|
11 | | -2 - Run the command |
| 9 | +| Layer | Tech | |
| 10 | +|---|---| |
| 11 | +| Runtime | Cloudflare Workers (`nodejs_compat`) | |
| 12 | +| Framework | TanStack Start / TanStack Router | |
| 13 | +| UI | React 19 + React Compiler | |
| 14 | +| Styles | Tailwind CSS v4 + DaisyUI | |
| 15 | +| Build | Vite 7 | |
| 16 | +| Data | TanStack Query + TanStack Store, server functions | |
| 17 | +| Commerce | Shopify Storefront API (via `@decocms/apps/shopify`) | |
| 18 | +| CMS | Deco admin protocol (via `@decocms/start`) | |
| 19 | +| Deploy | Wrangler (Cloudflare Workers) | |
| 20 | + |
| 21 | +## Migrating a Deco Fresh storefront to this stack |
| 22 | + |
| 23 | +If you have an existing Deco storefront on the legacy **Fresh + Preact + Deno** stack, the [`@decocms/start`](https://github.com/decocms/deco-start) framework ships a migration CLI that takes you from a Fresh site to a working TanStack Start + Cloudflare Workers site in one pass — this repo is one of the outputs (see `MIGRATION_REPORT.md`). |
| 24 | + |
| 25 | +The script does six phases automatically: |
| 26 | + |
| 27 | +1. **Analyze** — scan source, detect Preact/Fresh/Deco patterns, GTM, commerce platform |
| 28 | +2. **Scaffold** — generate `package.json`, `tsconfig.json`, `vite.config.ts`, `wrangler.jsonc`, `src/server.ts`, `src/worker-entry.ts`, `src/router.tsx`, `src/setup.ts`, `src/cache-config.ts`, `src/routes/{__root,$,index,deco/*}`, `src/styles/app.css`, image components, `useCart` / `useUser` / `useWishlist` hooks, types |
| 29 | +3. **Transform** — rewrite imports (70+ rules), JSX attrs, Fresh APIs, Deno-isms, Tailwind v3 → v4 |
| 30 | +4. **Cleanup** — delete `islands/`, old routes, `deno.json`; move `static/` → `public/` |
| 31 | +5. **Report** — write `MIGRATION_REPORT.md` with manual review items |
| 32 | +6. **Verify** — 18+ smoke tests (zero old imports, scaffolded files exist) |
| 33 | + |
| 34 | +Your existing `src/sections/`, `src/components/`, and `.deco/blocks/` carry over unchanged. The script gets you to "builds clean with zero old imports" — manual work starts at platform hooks (`useCart`) and runtime tuning, tracked in `MIGRATION_NEXT_STEPS.md`. |
| 35 | + |
| 36 | +### Option A — drive the migration through an AI coding tool (recommended) |
| 37 | + |
| 38 | +`@decocms/start` ships an Agent Skill that primes Claude Code, Cursor, Codex, and other AI coding tools with the full 12-phase migration playbook plus the reference docs and templates. The skill knows what `@decocms/start` supports, runs the migration script for you, and flags anything that needs manual attention as it goes — so you stay in a conversation rather than juggling flags. |
| 39 | + |
| 40 | +Install the skill once: |
| 41 | + |
| 42 | +```sh |
| 43 | +npx skills add decocms/deco-start |
| 44 | +``` |
| 45 | + |
| 46 | +Open your Fresh site in your AI tool and prompt: |
| 47 | + |
| 48 | +> migrate this project to TanStack Start |
| 49 | +
|
| 50 | +The agent will analyze the site, run the migration phases, talk through anything ambiguous (CSP domains, site-specific loaders, GTM IDs, custom Fresh handlers), and stop on the manual-review items so you can answer in plain English instead of editing config by hand. |
| 51 | + |
| 52 | +See [`@decocms/start#migrating-from-freshpreactdeno`](https://github.com/decocms/deco-start#migrating-from-freshpreactdeno) for the full skill index. |
| 53 | + |
| 54 | +### Option B — run the migration script manually |
| 55 | + |
| 56 | +If you'd rather drive it yourself, the same logic is exposed as a CLI. From the **root of your existing Fresh site**, with nothing pre-installed: |
12 | 57 |
|
13 | 58 | ```sh |
14 | | -deno task start |
| 59 | +# Preview changes (no files written): |
| 60 | +npx -p @decocms/start deco-migrate --dry-run --verbose |
| 61 | + |
| 62 | +# Run the migration in place: |
| 63 | +npx -p @decocms/start deco-migrate |
| 64 | + |
| 65 | +# Migrate a different directory: |
| 66 | +npx -p @decocms/start deco-migrate --source ./my-site |
15 | 67 | ``` |
16 | 68 |
|
17 | | -This will install all dependencies and start your project. |
| 69 | +Flags: |
18 | 70 |
|
19 | | -Access `http://localhost:8000` to see your site. |
| 71 | +| Flag | Description | |
| 72 | +|---|---| |
| 73 | +| `--source <dir>` | Source directory (default: current directory) | |
| 74 | +| `--dry-run` | Preview changes without writing files | |
| 75 | +| `--verbose` | Show detailed output for every file | |
| 76 | +| `--help`, `-h` | Show help | |
20 | 77 |
|
21 | | -## Recommended extensions (VSCode) |
| 78 | +After it finishes: |
22 | 79 |
|
23 | | -- [Deno](https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno) |
| 80 | +```sh |
| 81 | +npm install |
| 82 | +npm run generate:blocks |
| 83 | +npm run generate:schema |
| 84 | +npx tsr generate |
| 85 | +npm run dev |
| 86 | +``` |
| 87 | + |
| 88 | +Then open `MIGRATION_REPORT.md` for the manual review checklist (CSP domains, site-specific loaders, GTM, etc.). |
| 89 | + |
| 90 | +### What's left after the script finishes |
24 | 91 |
|
25 | | -- [Tailwind IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) |
| 92 | +Open `MIGRATION_NEXT_STEPS.md` in this repo for the canonical follow-up checklist used during the migration of this site. The recurring patterns are: |
26 | 93 |
|
27 | | -## Dependencies |
| 94 | +- Replace `window.STOREFRONT.*` channels (USER, WISHLIST) with `src/platform/<domain>/` modules following the `cart/` shape: `*.types.ts`, `*.actions.ts` (`createServerFn`), `*.hooks.ts` (`useQuery` + `useMutation`), `*.<commerce>.ts` adapter, `index.ts` barrel. |
| 95 | +- Switch internal navigation from `<a href>` to `<Link preload="intent">` from `@tanstack/react-router`. |
| 96 | +- Group flat section `Props` into `*Config` sub-interfaces with JSDoc (see `src/sections/Product/ProductDetails.tsx`). |
| 97 | +- Add scoped skeletons via `useRouterState({ select: s => s.isLoading })` for the bits that actually change during a route transition. |
| 98 | +- Decompose god-components into narrow leaves so React Compiler can auto-memoize them. |
28 | 99 |
|
29 | | -Keep your dependencies updated by running: |
| 100 | +## Quick start |
| 101 | + |
| 102 | +Requires Node 20+ and `npm`. |
30 | 103 |
|
31 | 104 | ```sh |
32 | | -deno task update |
| 105 | +npm install |
| 106 | +npm run dev |
33 | 107 | ``` |
34 | 108 |
|
35 | | -## Help |
| 109 | +Open `http://localhost:5173`. |
| 110 | + |
| 111 | +## Scripts |
36 | 112 |
|
37 | | -- 📚 [Docs](https://www.deco.cx/docs/en/overview) |
| 113 | +| Script | What it does | |
| 114 | +|---|---| |
| 115 | +| `npm run dev` | Start Vite dev server | |
| 116 | +| `npm run dev:clean` | Wipe Vite/Wrangler/TanStack caches and start fresh | |
| 117 | +| `npm run build` | Generate blocks/schema/sections/loaders/routes, then `vite build` | |
| 118 | +| `npm run preview` | Preview the production build locally | |
| 119 | +| `npm run deploy` | `npm run build` then `wrangler deploy` | |
| 120 | +| `npm run typecheck` | `tsc --noEmit` | |
| 121 | +| `npm run format` / `format:check` | Prettier on `src/**/*.{ts,tsx}` | |
| 122 | +| `npm run knip` | Find unused exports/files | |
| 123 | +| `npm run tailwind:lint` / `tailwind:fix` | Lint/auto-fix Tailwind class usage | |
| 124 | +| `npm run generate:*` | Re-run a single codegen step (blocks, schema, sections, loaders, routes, invoke) | |
38 | 125 |
|
39 | | -- 🚨 [Troubleshooting](https://deco.cx/docs/en/reference/troubleshooting) |
| 126 | +## Project layout |
40 | 127 |
|
41 | | -- 🔤 [Glossary](https://deco.cx/glossary) |
| 128 | +``` |
| 129 | +src/ |
| 130 | +├── apps/ # Site app composition (apps/site.ts) |
| 131 | +├── routes/ # TanStack Router file routes (__root, $, index, deco/*, account, login) |
| 132 | +├── sections/ # CMS-rendered sections (Header, Footer, Product, Newsletter, …) |
| 133 | +├── components/ # UI components (header, minicart, product, search, ui, …) |
| 134 | +├── platform/ # Domain state — TanStack Query hooks + createServerFn actions |
| 135 | +│ ├── cart/ # cart.{types,actions,hooks,shopify}.ts |
| 136 | +│ ├── user/ |
| 137 | +│ └── wishlist/ |
| 138 | +├── loaders/ # Site-local CMS loaders (user, wishlist) |
| 139 | +├── actions/ # Site-local invoke handlers (wishlist/submit, shipping/simulate) |
| 140 | +├── hooks/ # useCart, useUser, useWishlist |
| 141 | +├── sdk/ # signal, clx, debounce, deviceServer, logger |
| 142 | +├── styles/app.css # Tailwind v4 entry |
| 143 | +├── setup.ts # Wires framework + apps + sections (called from worker entry) |
| 144 | +├── setup/ # Section-specific prop enrichment |
| 145 | +├── cache-config.ts # Edge cache profile overrides |
| 146 | +├── server.ts # TanStack Start server entry |
| 147 | +├── worker-entry.ts # Cloudflare Worker entry: admin protocol, CSP, segmentation, caching |
| 148 | +├── router.tsx # Router configuration |
| 149 | +├── runtime.ts # Runtime helpers |
| 150 | +├── context.ts # Site context |
| 151 | +└── server/cms/ # Generated: blocks.gen.ts, sections.gen.ts (do not edit by hand) |
| 152 | +``` |
| 153 | + |
| 154 | +## How rendering works |
| 155 | + |
| 156 | +1. A request hits `src/worker-entry.ts` → `createDecoWorkerEntry` (admin routes, edge cache, CSP, device segmentation). |
| 157 | +2. Non-admin requests fall through to the TanStack Start server entry (`src/server.ts`). |
| 158 | +3. The catch-all route (`src/routes/$.tsx`) calls the framework's CMS resolver, which loads the page's blocks via `src/server/cms/blocks.gen.ts`. |
| 159 | +4. Blocks resolve to sections under `src/sections/`. Sections receive props enriched by their loader and metadata from `applySectionConventions` in `setup.ts`. |
| 160 | +5. Commerce data (Shopify PDP, PLP, search, cart) comes from `@decocms/apps/shopify` loaders, wired via `autoconfigApps`. |
| 161 | + |
| 162 | +## Data fetching pattern |
| 163 | + |
| 164 | +Domain state (cart, user, wishlist) follows a single pattern under `src/platform/<domain>/`: |
| 165 | + |
| 166 | +``` |
| 167 | +<domain>.types.ts # platform-agnostic state shape |
| 168 | +<domain>.actions.ts # createServerFn wrappers (run on the worker) |
| 169 | +<domain>.hooks.ts # useQuery + useMutation |
| 170 | +<domain>.shopify.ts # adapter: Shopify response → state shape |
| 171 | +index.ts # barrel |
| 172 | +``` |
| 173 | + |
| 174 | +`src/routes/__root.tsx` prefetches cart + user in `beforeLoad` and seeds the QueryClient. The minicart drawer is mounted at root and driven by the `useCart()` hook. |
| 175 | + |
| 176 | +For navigation, use `<Link from="@tanstack/react-router" preload="intent">` on internal links — never plain `<a href>`. |
| 177 | + |
| 178 | +## Edge caching |
| 179 | + |
| 180 | +The worker entry applies Cloudflare edge cache profiles (defined in `@decocms/start/sdk/cacheHeaders`): |
| 181 | + |
| 182 | +| URL pattern | Profile | Edge TTL | |
| 183 | +|---|---|---| |
| 184 | +| `/` | static | 1 day | |
| 185 | +| `*/p` | product | 5 min | |
| 186 | +| `/s`, `?q=` | search | 60s | |
| 187 | +| `/cart`, `/checkout` | private | none | |
| 188 | +| Everything else | listing | 2 min | |
| 189 | + |
| 190 | +Override per-route in `src/cache-config.ts`. |
| 191 | + |
| 192 | +## Deployment |
| 193 | + |
| 194 | +Cloudflare Workers via Wrangler. Configuration is in `wrangler.jsonc` (entry: `src/worker-entry.ts`). |
| 195 | + |
| 196 | +```sh |
| 197 | +npm run deploy |
| 198 | +``` |
| 199 | + |
| 200 | +For Argo CD / Kubernetes deployment manifests see `deploy/`. |
| 201 | + |
| 202 | +## Migration artifacts |
| 203 | + |
| 204 | +This repo was itself produced by the migration flow above. Two generated docs are kept for reference: |
| 205 | + |
| 206 | +- `MIGRATION_REPORT.md` — files scaffolded / transformed / deleted, manual review items |
| 207 | +- `MIGRATION_NEXT_STEPS.md` — open follow-up work and canonical patterns to follow |
| 208 | + |
| 209 | +## Help |
42 | 210 |
|
43 | | -- 👥 [Discord](https://deco.cx/discord) |
| 211 | +- [deco.cx docs](https://www.deco.cx/docs/en/overview) |
| 212 | +- [Discord](https://deco.cx/discord) |
| 213 | +- Framework source: [`@decocms/start`](https://github.com/decocms/deco-start), [`@decocms/apps`](https://github.com/decocms/apps-start) |
44 | 214 |
|
45 | | -## Contributing |
46 | | -We are working on the instructions, for now feel free to contribute to this project. |
| 215 | +## License |
47 | 216 |
|
48 | | -Take a look on this ones: |
49 | | -- [deco](https://github.com/deco-cx/deco/) |
50 | | -- [apps](https://github.com/deco-cx/apps/) |
51 | | -. |
52 | | -. |
| 217 | +MIT |
0 commit comments