Testing policy

Clay does not run automated tests. Per ~/.claude/rules/no-testing.md, the project intentionally avoids a test framework: there is no vitest, jest, or playwright setup, and contributors should not add one without an explicit conversation. Verification happens through static analysis, format checks, build validation, and link integrity. Treat those scripts as the test suite.
When something is hard to verify with the scripts on this page, prefer extending a verification script over introducing a test framework.

Policy

1

No automated test framework

Clay ships without a unit, integration, or end-to-end test runner. The repo-wide rule lives at ~/.claude/rules/no-testing.md and applies to every workspace package.
2

Verification is scripts, not suites

What would normally be a test is expressed as a Mintlify script, a Redocly lint, a Prettier check, a tsc --noEmit, or a build artifact. Each is one command with a clear pass/fail.
3

Local gates are the contract

Before pushing, run the relevant subset locally. The hosted deploy gate, when it exists, runs the same commands.
4

Add a check, not a test

When behavior needs verification, author or extend a script on this page rather than reaching for a test framework.

What counts as verification

These are the commands that stand in for tests in Clay. Each one has a clear pass/fail and lives in an existing package script.
CheckCommandPurpose
Mintlify validatepnpm --filter @clay/specs validateStrict build validation. Catches missing frontmatter, broken docs.json references, and other structural issues before they reach the deployed site.
Mintlify broken linkspnpm --filter @clay/specs broken-linksScans internal Mintlify links for breakage. Run after any move or rename.
Mintlify accessibilitypnpm --filter @clay/specs a11yAccessibility checks across the authored pages. Pair with the consent and design-language contracts for full coverage.
Prettier checkpnpm --filter @clay/specs format:checkPrettier check without writing. CI-friendly equivalent of pnpm format.
Turbo typecheckpnpm typechecktsc --noEmit across the workspace. Backend depends on generate first, so OpenAPI export runs before the typecheck pass.
Redocly lintpnpm --filter @clay/backend openapi:checkredocly lint openapi/openapi.yaml. Catches structural problems in the exported OpenAPI document before the client regenerates from it.
Markdown frontmatterpnpm md:frontmatterVerifies YAML frontmatter on every *.md and *.mdx file outside docs/vendor/. Enforces the rules in scripts/check-markdown-frontmatter.mjs.
Workspace all chainpnpm allRuns generate, format, build, lint, and typecheck across the workspace in order. Use it as the “did everything pass?” check.

What is intentionally out of scope

The following are deliberately excluded from Clay today. Reach out before introducing any of them.
  • Unit tests — no vitest, jest, or equivalent. Business logic is verified by Zod schemas and TypeScript types.
  • Integration tests — no in-process database fixtures, no Worker test harness. The intended Hyperdrive boundary will change this calculus when code lands.
  • End-to-end tests — no Playwright or Detox setup. Mobile flows are verified visually against Expo.
  • Coverage tooling — no c8, istanbul, or codecov integration. Coverage metrics are not part of the contract.
  • Snapshot tests — no snapshot baselines. Visual style is governed by the Mintlify theme and the design-language pages.

Adding a check

When a behavior needs verification, extend an existing script before reaching for a test framework.
1

Find the owning package

Determine whether the check belongs in apps/specs, apps/backend, or a shared packages/* surface. Most authoring checks belong with the specs.
2

Add a script entry

Add the new command to the owning package.json under scripts. Use a focused, single-purpose name (format:check, openapi:check) rather than a generic verify.
3

Wire it into turbo.json if cross-package

If the check spans packages, add or update a turbo.json task so turbo run <task> fans it out correctly. Declare inputs and outputs so caching stays accurate.
4

Document it on this page

Add a Card entry under “What counts as verification” so the next contributor finds it.
5

Run it locally before pushing

A new check is incomplete until it has been run locally at least once and either passed or produced an actionable failure.
Keep checks orthogonal. One command, one purpose. If a script needs to do two things, split it into two scripts and document both.

CI and local validation

The full list of local scripts and Turborepo tasks that act as Clay’s CI gate.

Architecture

The app surfaces these verification scripts protect.

Decisions

ADRs that explain why the project skips a test framework.

Glossary

Shared vocabulary referenced by these checks.