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 |
| 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.
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.
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.
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.
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).