Skip to content

decocms/deco-start

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

563 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@decocms/start

npm version license

Framework layer for deco.cx storefronts on TanStack Start + React 19 + Cloudflare Workers.

@decocms/start is the npm package that storefronts depend on. It provides the CMS bridge, admin protocol, section registry, schema generation, edge caching, the Vite plugin, and a small SDK. It is not itself a storefront — it is what storefronts build on top of.

📖 Read the full documentation →


What's in the box

┌─────────────────────────────────────────────────┐
│   Site repo (your storefront)                    │  ← Components, sections, routes
├─────────────────────────────────────────────────┤
│   @decocms/apps  (commerce integrations)         │  ← VTEX, Shopify, Resend
├─────────────────────────────────────────────────┤
│   @decocms/start  (framework — this package)     │  ← CMS bridge, admin, caching
└─────────────────────────────────────────────────┘
              ↓ runs on ↓
   TanStack Start  +  React 19  +  Cloudflare Workers

@decocms/start exports cover four surfaces:

  • Worker entrycreateDecoWorkerEntry wraps your Cloudflare Worker with admin routes, edge cache, and asset bypass.
  • CMS bridgeloadCmsPage, resolveDecoPage, registerSectionLoaders, registerLayoutSections.
  • Admin protocolhandleMeta, handleDecofile, handleRender, handleInvoke.
  • SDKcreateCachedLoader, createInstrumentedFetch, createInvoke, decoVitePlugin, plus utilities (cookies, redirects, sitemap, A/B testing).

Full export reference: docs.deco.cx/v2/en/reference/package-exports.


Import Tiers

@decocms/start exposes three import tiers, each with a distinct dependency budget:

@decocms/start/core — framework-agnostic

CMS resolution, registry, blocks, matchers, schema, plain SDK utilities. Zero imports from @tanstack/*, next/*, or node:async_hooks. Safe to use from any host:

import {
  resolveDecoPage,
  loadCmsPagePure,
  registerSectionsSync,
  setBlocks,
} from "@decocms/start/core";

@decocms/start/tanstack — TanStack Start adapter

Routes, hooks, middleware, worker entry, vite plugin. The default for storefronts on Cloudflare Workers + TanStack Start.

import { loadCmsPage, cmsRouteConfig } from "@decocms/start/tanstack";

@decocms/start/next — Next.js (App Router) adapter

import {
  loadCmsPage,
  buildMatcherContextFromNext,
  handleDecoAdminRoute,
  DecoPage,
} from "@decocms/start/next";

// app/[[...path]]/page.tsx
export default DecoPage;

// app/(deco-admin)/[...path]/route.ts
import { handleDecoAdminRoute } from "@decocms/start/next";
export const GET = handleDecoAdminRoute;
export const POST = handleDecoAdminRoute;

For client-only components (no node:async_hooks in the bundle):

import { useDevice, signal } from "@decocms/start/next/client";

Caveat: Next.js Pages Router is not supported. App Router only.

@decocms/start/node — Node-only helpers

Disk-loading helpers that depend on node:fs. Not safe to import into client bundles. Use from server entry points only:

import { loadAllDecofileBlocks } from "@decocms/start/node";
import { setBlocks } from "@decocms/start/core";

// In a server-only setup file:
setBlocks(await loadAllDecofileBlocks(".deco/blocks"));

Caveat: these helpers depend on node:fs / node:path and must not appear in any module that ends up in a browser bundle. From Next.js, that means importing them only from server-only files (getServerSideProps/getStaticProps, App Router server components, route handlers, or non-route server utility modules) — never from a file ultimately imported by a client component.


Hello, World

A minimal v2 storefront has six files. Here they are.

package.json

{
  "name": "my-store",
  "type": "module",
  "scripts": {
    "dev": "vite dev",
    "build": "vite build",
    "deploy": "wrangler deploy"
  },
  "dependencies": {
    "@decocms/start": "^2.28.0",
    "@decocms/apps": "^1.11.0",
    "@tanstack/react-start": "^1.166.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  },
  "devDependencies": {
    "vite": "^6.0.0",
    "wrangler": "^4.72.0"
  }
}

vite.config.ts

import { defineConfig } from "vite";
import { cloudflare } from "@cloudflare/vite-plugin";
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import react from "@vitejs/plugin-react";
import decoVitePlugin from "@decocms/start/vite";

export default defineConfig({
  plugins: [
    cloudflare({ viteEnvironment: { name: "ssr" } }),
    tanstackStart({ server: { entry: "server" } }),
    react({ babel: { plugins: ["babel-plugin-react-compiler"] } }),
    decoVitePlugin(),
  ],
  resolve: {
    alias: { "~": "/src" },
    deduplicate: ["react", "react-dom", "@decocms/start", "@decocms/apps"],
  },
});

wrangler.jsonc

{
  "name": "my-store",
  "main": "./src/worker-entry.ts",
  "compatibility_date": "2026-02-14",
  "compatibility_flags": [
    "nodejs_compat",
    "no_handle_cross_request_promise_resolution"
  ],
  "assets": { "directory": "./dist/client" }
}

src/setup.ts

import { createSiteSetup } from "@decocms/start/setup";
import { applySectionConventions } from "@decocms/start/cms";

import blocks from "./server/cms/blocks.gen";
import sectionsGen from "./server/cms/sections.gen";
import meta from "./server/cms/meta.gen.json";

createSiteSetup({
  sections: import.meta.glob("./sections/**/*.tsx", { eager: true }),
  blocks,
  meta: () => meta,
  productionOrigins: ["https://my-store.com"],
});

applySectionConventions(sectionsGen);

src/worker-entry.ts

import "./setup";   // MUST be first

import { createDecoWorkerEntry } from "@decocms/start/sdk/workerEntry";
import {
  handleMeta,
  handleDecofile,
  handleRender,
  handleInvoke,
} from "@decocms/start/admin";
import serverEntry from "./server";

export default createDecoWorkerEntry(serverEntry, {
  admin: { handleMeta, handleDecofile, handleRender, handleInvoke },
});

src/routes/$.tsx

import { createFileRoute } from "@tanstack/react-router";
import { cmsRouteConfig } from "@decocms/start/routes";

export const Route = createFileRoute("/$")(
  cmsRouteConfig({ siteName: "my-store" }),
);

That is the entire skeleton. npm install, npm run dev, point admin.deco.cx at it, and you have a working CMS-driven site.

For commerce integrations (VTEX, Shopify) see @decocms/apps.


Migrating from Fresh / Preact / Deno

@decocms/start ships an Agent Skill that handles the migration for you. It works with Claude Code, Cursor, Codex, and any tool that supports skills.

npx skills add decocms/deco-start

Then, in your editor, point at your Fresh storefront and prompt:

migrate this project to TanStack Start

The skill runs the migration script, walks you through MIGRATION_REPORT.md, fixes typecheck/build errors interactively, and shows the diff before committing.

Or run the script directly

# from inside the v1 storefront directory
npx -p @decocms/start deco-migrate

The script runs seven phases (analyze → scaffold → transform → cleanup → report → verify → bootstrap), produces MIGRATION_REPORT.md with manual TODOs, and gets you to "compiles clean, builds clean".

Full migration playbook: docs.deco.cx/v2/en/migration/overview.


Documentation

The full v2 docs live at docs.deco.cx/v2:


Peer dependencies

{
  "@tanstack/react-start": ">=1.0.0",
  "@tanstack/store": ">=0.7.0",
  "@tanstack/react-query": ">=5.0.0",
  "react": "^19.0.0",
  "react-dom": "^19.0.0",
  "vite": ">=6.0.0"
}

OpenTelemetry is optional but recommended: @microlabs/otel-cf-workers >=1.0.0-rc.0, @opentelemetry/api >=1.9.0.


Development

npm run typecheck   # tsc --noEmit
npm run lint        # biome check
npm run check       # typecheck + lint + unused exports

This is a library — there is no dev server here. Consumer storefronts run their own vite dev.

Contributing? See CLAUDE.md for the architectural decisions, and MIGRATION_TOOLING_PLAN.md for the append-only history of the migration tooling.


License

MIT

About

Deco framework for TanStack Start - CMS bridge, admin protocol, hooks, schema generation

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors