Firestarter is a pre-built design system, CMS, and frontend for low to mid-tier client projects. It bridges the gap between bespoke builds and Squarespace/Framer sites for clients who deserve a real CMS and higher design quality.
The system ships a complete set of flexible components and page layouts designed and built to Firebelly’s internal standards. Duplicate the repo, customize design tokens (colors, type, spacing), add any unique components or page templates, and deploy.
Figma Design System → Storybook → Craft CMS (headless) → Next.js Frontend
| Layer | Tool | Purpose |
|---|---|---|
| Design | Figma | Design system source of truth |
| Components | Storybook | Component library with Figma tokens |
| CMS | Craft CMS 5 | Headless content management |
| Frontend | Next.js 16 | App Router, Server/Client Components |
/firestarter
├── /site # Next.js + Storybook
│ ├── .storybook/ # Storybook configuration
│ ├── src/
│ │ ├── app/ # Next.js App Router
│ │ ├── components/ # Components with co-located stories
│ │ ├── stories/ # Storybook default stories
│ │ ├── tokens/ # Design tokens from Figma
│ │ └── lib/ # Utilities and API helpers
│
├── /cms # Craft CMS (headless)
│ ├── config/ # Craft configuration
│ ├── templates/ # Twig templates (minimal)
│ └── web/ # Public directory
│
└── /docs # Project documentation
Design specs and implementation plans live in docs/design-specs/ and docs/implementation-plans/. Each changelog entry links to the relevant spec and plan for deeper context.
- Node.js (see
.nvmrcfor version) - DDEV (for local Craft development)
This repo uses a pnpm workspace — the root pnpm-workspace.yaml defines site as a workspace package. A single install from the root handles everything:
# Set correct Node version
nvm use
# Activate the pinned pnpm version
corepack enable
# Installs all dependencies (root + site workspace)
pnpm installThis installs Lefthook and Prettier at the root, site dependencies in /site, and automatically configures pre-commit hooks for formatting, type checking, and linting.
See cms/README.md for Craft setup instructions (DDEV, env file, install, license key).
The root provides proxy commands for the frontend workspace:
# Start Next.js at localhost:3000
pnpm dev
# Start Storybook at localhost:6006
pnpm storybook
# Rebuild design tokens
pnpm tokensThese proxy to the site workspace via pnpm --filter site. See site/README.md for full frontend setup, component structure, design tokens, and testing.
The frontend fetches content from Craft CMS via GraphQL. The integration includes:
- GraphQL data fetching —
site/src/lib/graphql/client.tswraps fetch with caching - Live preview — Editors see draft changes in Craft's preview iframe
- Cache revalidation — Webhook from Craft invalidates Next.js cache on publish
When an editor publishes content in Craft, a webhook POSTs to Next.js to purge the cached data so the next visitor sees fresh content.
1. Add environment variables to cms/.env:
REVALIDATION_SECRET=your-random-string
REVALIDATION_URL=http://host.docker.internal:3000/api/revalidate # local dev2. Configure the webhook in Craft CP → Settings → Webhooks:
| Field | Value |
|---|---|
| Name | Revalidate Next.js |
| Sender Class | craft\elements\Entry |
| Event Name | afterSave |
| URL | $REVALIDATION_URL |
| Method | POST |
| Headers | Content-Type: application/json |
3. Set the webhook payload (Twig template):
{% set entryUri = event.sender.uri %}
{% set revalidationSecret = getenv('REVALIDATION_SECRET') %}
{{
{
secret: revalidationSecret,
uri: entryUri
}|json_encode|raw
}}You can verify the webhook is working in Craft CP → Utilities → Webhooks, which shows request/response history. See docs/learnings/2026-01-27-on-demand-revalidation.md for details on how revalidation works under the hood.
Copy the example file and fill in values:
cd site
cp .env.example .env.local| Variable | Purpose |
|---|---|
CRAFT_URL |
Craft CMS URL (e.g., http://cms.ddev.site) |
REVALIDATION_SECRET |
Shared secret for webhook validation |
The CMS also needs REVALIDATION_SECRET in cms/.env (same value).
- Use HTTP (not HTTPS) for
CRAFT_URLlocally — Node rejects self-signed certs - To test Craft's live preview feature, you need HTTPS (the CP iframe won't load HTTP content). Run
pnpm dev --experimental-httpsand updatePRIMARY_SITE_URL=https://localhost:3000incms/.env. Revert to HTTP when done — webhooks won't work over HTTPS locally. - See
docs/learnings/2026-01-27-local-vs-production-config.mdfor details
Lefthook runs automated checks before each commit:
- Prettier — Auto-formats staged files and re-stages them
- TypeScript — Full project type check (
tsc --noEmit) - ESLint — Lints staged JS/TS files only
Jobs run in order. Prettier runs on all supported file types; TypeScript and ESLint only run on JS/TS files in /site.
To format the entire repo manually:
# Format all files
pnpm format
# Check without writing
pnpm format:checkTo lint the frontend manually:
# Check for errors
pnpm lint
# Auto-fix (includes import sorting)
pnpm lint --fixTo bypass hooks temporarily (use sparingly):
git commit --no-verify -m "message"- Client safety — CMS structured so clients can manage content without breaking layouts
- Off-the-shelf components — Most projects use existing components, few custom additions
- Clear separation — Frontend and CMS are distinct, self-contained directories
- Clone and go — New projects clone the repo; no complex setup or shared dependencies