CI and local validation

Clay does not run a hosted CI pipeline today. Validation happens through the local scripts in apps/specs/package.json and apps/backend/package.json, coordinated by turbo.json at the repo root. This page is the contract for what those scripts do and when to run them.
Treat every script on this page as a local gate. Before pushing, the same commands should pass on a developer machine. When a hosted CI lands, these are the commands it should run.

Local scripts

The specs package (@clay/specs) owns site authoring, validation, and deploy. Run these from apps/specs/ or via pnpm --filter @clay/specs <script>.
ScriptCommandPurpose
devpnpm devMintlify live preview at localhost:3000. Hot-reloads MDX changes while authoring.
buildpnpm buildExport the static site to .mintlify-export/. Produces a deployable bundle.
cf:deploypnpm cf:deployPublish .mintlify-export/ to the clay-specs Cloudflare Pages project.
deploypnpm deployAlias for cf:deploy.
validatepnpm validateRun Mintlify’s strict build validation. Frontmatter, navigation, and config are checked.
lintpnpm lintAlias for validate.
broken-linkspnpm broken-linksScan internal Mintlify links for breakage.
a11ypnpm a11yRun accessibility checks across the authored pages.
formatpnpm formatPrettier write across MDX, JSON, and category folders. Uses --ignore-path ../../.prettierignore.
format:checkpnpm format:checkPrettier check only. CI-friendly: same scope as format without writing.
cleanpnpm cleanRemove .mintlify-export/ and the zip artifact.

Backend scripts

The backend package (@clay/backend) owns OpenAPI generation, typechecking, and Worker deploy. Run these from apps/backend/ or via pnpm --filter @clay/backend <script>.
ScriptCommandPurpose
devpnpm devwrangler dev — start the Worker locally.
generatepnpm generateExport the live Hono app’s OpenAPI document to openapi/openapi.yaml. The client and Redocly lint depend on this output.
openapi:exportpnpm openapi:exportRun scripts/export-openapi.ts directly. generate is the public alias.
buildpnpm buildAlias for typecheck. The Worker itself is built by Wrangler on deploy.
deploypnpm deploywrangler deploy — publish the Worker.
lintpnpm lintAlias for openapi:check.
openapi:checkpnpm openapi:checkredocly lint openapi/openapi.yaml — lint the exported OpenAPI document.
typecheckpnpm typechecktsc --noEmit across apps/backend.
types:wranglerpnpm types:wranglerRefresh worker-configuration.d.ts from wrangler.toml.
formatpnpm formatPrettier write across src/, scripts/, and config files.
format:checkpnpm format:checkPrettier check across apps/backend sources.
cleanpnpm cleanRemove the generated openapi/ directory.

Workspace turbo tasks

turbo.json orchestrates the scripts above across packages. The most useful entry points:
1

pnpm typecheck

Runs typecheck everywhere. Backend and the generated client both depend on generate first, so OpenAPI export runs automatically.
2

pnpm lint

Runs lint everywhere. For @clay/backend this means Redocly against the freshly exported OpenAPI.
3

pnpm build

Runs build everywhere with ^build and ^generate as dependencies. The specs build exports the static site; the backend build typechecks.
4

pnpm generate

Runs the generate task everywhere. Backend exports OpenAPI; the client regenerates from it.
5

pnpm --filter @clay/specs cf:deploy

Publishes the specs bundle to Cloudflare Pages. Cached build output is reused.

Workspace-wide commands

The root package.json exposes a few commands that fan out across the workspace. They compose the package scripts through Turbo and Prettier.
CommandPurpose
pnpm devturbo run dev — runs every package’s dev script in parallel and watches for changes.
pnpm generateturbo run generate — backend exports OpenAPI, client regenerates the SDK, etc.
pnpm buildturbo run build — typecheck across packages plus the Next.js production build.
pnpm lintturbo run lint — Redocly on the backend OpenAPI document and Mintlify validate on the specs site.
pnpm typecheckturbo run typechecktsc --noEmit everywhere.
pnpm md:frontmatternode scripts/check-markdown-frontmatter.mjs — verify YAML frontmatter on every tracked *.md and *.mdx.
pnpm format:allPrettier write across the whole repo (every supported extension), respecting .prettierignore.
pnpm format:checkPrettier check across the whole repo. CI-friendly.
pnpm allThe full chain: generate && format && build && lint && typecheck. The “did everything pass?” command.
pnpm deploypnpm run build && turbo run deploy — publishes every deployable surface. Ask before running.

Deploy gate

A change is deployable when:
  1. pnpm typecheck succeeds across the workspace.
  2. pnpm lint succeeds across the workspace (Redocly + Mintlify validate).
  3. pnpm --filter @clay/specs format:check succeeds.
  4. pnpm --filter @clay/specs broken-links reports no broken internal links.
  5. pnpm --filter @clay/specs build produces a clean static export.
  6. pnpm md:frontmatter reports no frontmatter failures on tracked Markdown.
Do not run pnpm --filter @clay/specs deploy without explicit user authorization. The deploy script publishes to the live Cloudflare Pages project.

When a script fails

1

Read the failure top-down

Mintlify, Redocly, and tsc each report the first failure clearly. Fix the first error before chasing later ones — many later failures cascade.
2

Check input freshness

If typecheck or lint fails after a schema change, make sure pnpm generate has been run so openapi/openapi.yaml matches the live Hono app.
3

Clear the cache when in doubt

For turbo run issues, clear node_modules/.cache/turbo and rerun. For Mintlify preview issues, delete .mintlify and restart pnpm dev.
4

Reproduce with the narrowest command

Run the failing script directly inside the owning package before blaming the workspace orchestrator.

Testing policy

What counts as verification in Clay, and why there are no automated tests.

Workspace

The pnpm + Turborepo contracts that wire these scripts together.

Architecture

The app surfaces these CI scripts protect.

Decisions

ADRs that justify the choices behind this validation layout.