Get a clean clone running, know which commands to use, and follow the normal change path.

Reference Value
Subject Prerequisites, local commands, generated content, the fixture and the change workflow; for every contributor
Verified source apps/cms/package.json, unchanged since f40e8704; root package.json at 0461e045; apps/web/package.json at 9dc18495; AGENTS.md and .gitignore on main at 9480caab, checked 2026-11-07; the web build script and image change path re-checked on main at 0461e045, checked 2026-11-10
Support state Commands and publication behavior checked against main 950ba889; commands are read from maintained scripts and are not executed in this documentation pass

Prerequisites

Tool Version Source
Bun 1.4.4 .bun-version, packageManager
Node.js 22.23.4+ or 24.22.1+ engines sets >=22.23.4; AGENTS.md names both lines
Docker Only to run Directus locally apps/cms/Dockerfile

No credentials, CMS access or network content are needed for development, tests or builds.

Commands

Run from the repository root unless noted.

Command Does
bun install --frozen-lockfile Installs exactly what bun.lock pins, including the @yesid/* release tarballs
bun run dev Generates content from the fixture, then starts Vite on http://localhost:5173
bun run check Turbo check: CMS TypeScript plus web svelte-kit sync and the Svelte warnings gate
bun run test The test:changed selection self-test (scripts/test-changed.test.mjs), then Turbo test: web Vitest, CMS bun test, shared bun test
bun run build Turbo build: fixture export, vite build, a plain-Node SSR runtime check (scripts/check-ssr-runtime.mjs), the emitted page contract test (scripts/check-page-contracts.test.mjs), then the sitemap coverage test
bun run --cwd apps/web lint:design Design-system gates from @yesid/gates
bun run --cwd apps/web check:client-payload Gzip budgets for the root layout entry and payload; run after a build
bun run --cwd apps/web check:csp Validates the emitted Content-Security-Policy; run after a build
bun run --cwd apps/web test:e2e Playwright against a local preview on port 4173; install Chromium first with bunx playwright install chromium
bun run test:changed Fast local loop (#689): Vitest --changed against origin/main plus the impacted Playwright specs at one phone and one desktop project. A local accelerator, not a CI gate

Use bun run --cwd <dir> <script>. The form bun --cwd <dir> run <script> prints help and exits 0.

Generated content and the fixture

Every web dev, check, test and build script has a pre-hook that runs apps/cms/scripts/export-fallbacks.ts. It writes 21 ignored modules to apps/web/src/lib/content/ from packages/shared/fixtures/export-data.json. Never edit or commit those modules.

Need Command Notes
Live content locally bun run dev:op or bun run build:op Operator only: 1Password injects variables; build:op sets EXPORT_FALLBACKS_SOURCE=live. Set it explicitly for dev:op. Local live failure may fall back to cache
Live content from a local env file bun run dev:local-env Reads ignored apps/web/.env.local; live content requires an explicit EXPORT_FALLBACKS_SOURCE=live
Refresh the fixture bun apps/cms/scripts/trim-export-fixture.ts Builds a compact fixture from a live .cms-cache.json; commit only the fixture

Environment variable schemas are .env.example and apps/cms/.env.example. Resolved values go in ignored files or are injected; the Security and configuration page lists every name and target.

Run Directus locally (optional)

cp apps/cms/.env.example apps/cms/.env
docker build -t yesid-cms-local apps/cms
docker run --rm -p 8055:8055 --env-file apps/cms/.env yesid-cms-local

Give it a dedicated local database. Never point a local container at the production database.

Change workflow

flowchart LR
  B["Branch from main"] --> PR["PR to main"]
  PR --> V["Vercel preview<br/>fixture content"]
  PR --> C["Checks: gitleaks, ci<br/>(includes e2e), test, CodeQL"]
  C --> Q["Merge queue<br/>checks again on merge_group"]
  Q --> M["Squash merge"]
  M --> P["Vercel production<br/>live content"]
  M -. "CMS image" .-> R["Railway CMS deploy"]
Task Steps
Change copy or SEO text Edit in the CMS; publish through Publish site or the next successful production build from a merge to main
Add a blog post, project or service CMS only; detail routes already exist
Change layout, motion or behavior Edit apps/web/src/lib/components/<area>/, open a PR, check the preview
Add a page Route under src/routes/[[lang=locale]]/<page>/, a published site_pages row, a nav_links row, then Publish site after merge
Change a content shape Shared schema, CMS fetcher and emitter, fixture refresh, content catalog, SEO policy, consumer; see Content pipeline and contracts
Change an image Upload in the CMS, reference it and Publish site; the production build publishes raster images. Fixture builds show a placeholder for a new upload. New SVGs and pinned mirrors are a reviewed code change; see Operations and recovery
Bump the design system One PR that moves every @yesid/* URL to the same release

Pull requests target main. The repository is public for inspection but does not accept external code contributions (CONTRIBUTING.md).