Skip to content

Authority Doc / Public V1 Toolchain

The Toolchain Contract defines how CoachMe code is installed, generated, validated, tested, built, and prepared for release.

This page is the Public V1 authority for development tools, package scripts, code generation, migrations, test commands, CI command shape, generated-file policy, dependency updates, mobile build tooling, and release-note tooling across the future CoachMe app monorepo.

AuthorityTypeScriptpnpm + TurboCodegenCIPublic V1

Note

This page does not define architecture rationale, environment secrets, REST semantics, privacy policy, observability, or final release approvals. It defines the toolchain used to produce implementation and release evidence.

Scope

This contract owns the baseline toolchain and stable command surface for the future CoachMe app monorepo, while adjacent authority pages own architecture, environment, API behavior, and release approvals.

This Contract Owns

  • Runtime and package manager versions.
  • Monorepo orchestration and workspace layout conventions.
  • Root package scripts and CI command names.
  • Lint, format, typecheck, package build, and local hook tools.
  • API code generation tools and generated client placement.
  • Database migration generation and application commands.
  • Test runner choices for unit, integration, web E2E, and mobile E2E.
  • Web, mobile, forms, styling, and client-cache toolchain defaults.
  • Runtime configuration validation tooling.
  • Generated-file commit policy.
  • CI provider and command-level merge expectations.
  • Dependency update automation and release-note tooling.
  • Observability package installation, build integration, source-map upload paths, exact locks, and update policy.

This Contract Does Not Own

  • Business architecture and bounded contexts, owned by technical-architecture-plan.
  • Environment inventory, secrets, deployment topology, backup, restore, and rollback, owned by environment-runbook.
  • REST route semantics, error envelopes, compatibility, and contract behavior, owned by api-contract-standard.
  • Final release approvals, coverage thresholds, app-store smoke tests, and launch evidence, owned by the Test And Release Gate.
  • Privacy, retention, incident handling, or security policy.
  • Provider decisions outside the tools needed to generate, build, or test the app.
  • Telemetry signal semantics, provider approval, topology, access grants, and retention owned by Observability, Integration, Environment, Roles, and Privacy.

Note

Secret detection and dependency-vulnerability checks are required by the Test And Release Gate. This contract owns their stable command surface and pinned scanner implementations.

Baseline

These toolchain decisions are locked for Public V1 so local development, generated contracts, CI, and release preparation all use the same foundation.

ConcernDecisionNotes
RuntimeNode.js 24 LTSLocal, CI, and production build images should align.
Package managerpnpm 10Use Corepack or equivalent pinning.
Monorepopnpm workspaces + TurborepoTurbo coordinates root scripts, caching, and affected work.
BackendNestJS modular monolithArchitecture rationale remains in the technical architecture plan.
WebNext.js App RouterCoach web and admin operations surface.
MobileTwo Expo appsCoach mobile and client/personal mobile.
Database accessDrizzle ORM + drizzle-kitSQL migrations are committed.
API validationNestJS DTO classes + class-validatorOpenAPI generated through @nestjs/swagger.
OpenAPI clientsopenapi-typescript + openapi-fetchGenerated clients live in packages/contracts.
Unit/integration testsVitestDefault test runner across API and shared packages.
Web E2EPlaywrightCoach web browser regression and smoke coverage.
Mobile E2EMaestroDefault choice for Public V1, revisitable if Expo constraints require it.
CIGitHub ActionsRequired PR checks run the stable root commands.
Mobile releaseEAS Build + EAS Submit + EAS UpdateOTA updates constrained to compatible JS/runtime changes.
FormattingPrettierFormatting only.
LintingESLint flat configCorrectness and framework rules.
Env validationZod per app/packageFail fast at startup and in CI.
Client server stateTanStack QueryShared pattern across coach web and both mobile apps.
FormsReact Hook Form + Zod resolversUsed for web and mobile forms.
Web stylingTailwind CSSPaired with shared design tokens.
Mobile stylingNativeWindPaired with shared design tokens.
Web UIshadcn/ui + Radix primitivesWrapped in CoachMe-owned packages/ui-web.
Mobile UICoachMe-owned React Native primitives + NativeWindImplemented in packages/ui-mobile.
Mobile navigationExpo RouterDefault for now, explicitly revisitable.
Git hooksHusky + lint-stagedChanged-file format/lint only.
Dependency updatesRenovateGrouped low-risk updates; deliberate Expo/React Native updates.
Release notesChangesetsPublishing disabled unless later enabled.
Shared package buildstsup + tsc --noEmittsup emits packages; TypeScript checks types.

Observability Packages And Source Maps

This contract owns how the Observability-selected package families enter builds and stay compatible.

Observability package families

ConcernPackage familyLock rule
Backend loggingpino and pino-http, integrated through CoachMe-owned Nest middleware.Exact lockfile versions; default request serializers remain disabled by application configuration.
Metrics only@opentelemetry/api, @opentelemetry/sdk-metrics, @opentelemetry/exporter-metrics-otlp-http, and @opentelemetry/resources.Exact compatible versions shared by API and workers; no tracing SDK or client instrumentation at Launch.
Semantic conventions@opentelemetry/semantic-conventions.Pin one exact version shared by API/workers and record it with metric/query evidence.
Errors@sentry/nestjs, @sentry/nextjs, and @sentry/react-native.Exact compatible versions coordinated with framework and Expo releases.

Backend And Web Symbolication

Generate and upload server source maps for one backend release; distinguish API and worker by runtime/service context. Upload Next.js server/client maps during staging/production builds and do not serve them publicly.

Mobile Symbolication

EAS/Sentry uploads bundle maps for coach mobile and client mobile with exact release/build/dist metadata. Local/test never upload. The upload token is a CI/build secret.

Note

A failed required source-map upload blocks staging/production promotion, while runtime Sentry unavailability remains non-blocking. Deliberate staging errors must symbolicate API, worker, coach web, coach mobile, and client mobile.

Monorepo Layout

The future app repository separates deployable applications from shared packages so build boundaries, generated contracts, and shared UI stay explicit.

Application Packages

  • apps/api for the NestJS API, workers, OpenAPI generation, and Drizzle migrations.
  • apps/web for the Next.js coach and admin web app.
  • apps/mobile-coach for the Expo coach mobile app.
  • apps/mobile-client for the Expo client/personal mobile app.

Shared Packages

  • packages/domain
  • packages/contracts
  • packages/mobile-core
  • packages/ui-web
  • packages/ui-mobile
  • packages/design-tokens
  • packages/config

Note

Package boundaries should remain meaningful. Shared packages should not become dumping grounds for feature-specific behavior.

Package Scripts

Root scripts are the stable developer and CI interface. Package-local scripts can evolve underneath them without changing the contract surface.

ScriptPurpose
pnpm devRun the main local development stack through Turbo.
pnpm buildBuild all buildable apps and packages.
pnpm lintRun ESLint.
pnpm formatRun Prettier in write mode.
pnpm format:checkRun Prettier in check mode.
pnpm typecheckRun TypeScript checks.
pnpm testRun Vitest.
pnpm test:watchRun Vitest in watch mode.
pnpm test:e2e:webRun Playwright web E2E and smoke tests.
pnpm test:e2e:mobileRun Maestro mobile E2E and smoke tests.
pnpm codegenGenerate OpenAPI spec and clients.
pnpm codegen:checkFail if generated contracts drift.
pnpm db:generateGenerate Drizzle SQL migrations.
pnpm db:migrateApply Drizzle migrations.
pnpm db:seedRun the app seed script; seed/fixture policy is owned by the Environment Runbook and Test And Release Gate.
pnpm db:studioRun Drizzle Studio for local inspection only.
pnpm env:checkValidate app and package environment schemas.
pnpm security:secretsRun the pinned Gitleaks configuration against the repository and relevant history.
pnpm security:dependenciesRun pnpm audit --audit-level high through the repository wrapper and fail on high or critical findings.
pnpm security:checkRun all required secret and dependency-vulnerability checks.
pnpm verifyRun the CI-equivalent local gate.

Note

The exact root script list can evolve, but root scripts remain the stable developer and CI interface. Package-local scripts are implementation details underneath this contract.

Code Quality

Formatting, linting, and local hooks stay fast and predictable so developers get quick feedback without moving CI-only work into pre-commit scripts.

  • ESLint uses flat config.
  • Prettier owns formatting.
  • lint-staged runs changed-file formatting and lint checks through Husky.
  • Pre-commit hooks must stay fast and must not run full tests, builds, Docker services, Playwright, Maestro, or migrations.
  • Heavy checks belong in pnpm verify and GitHub Actions.

Note

Stylelint is not part of the Public V1 baseline unless custom CSS grows enough to justify it.

TypeScript Builds

Package build rules keep shared code consumable across apps while preserving explicit boundaries between deployable surfaces and reusable packages.

  • TypeScript strict mode is the default unless a package has a documented exception.
  • tsc --noEmit is the canonical typecheck.
  • tsup builds shared packages that need emitted output.
  • Source-only packages are allowed only where the consuming framework requires it or where emitted output adds no value.
  • Package exports are explicit.
  • Shared packages must not import from apps.
  • Apps import from shared packages through package names, not fragile relative paths.

Note

Build boundaries are part of architecture discipline, not only bundler housekeeping.

API Codegen

Generated contracts follow a fixed server-to-client path so DTO changes, OpenAPI output, and client packages move together and can be checked for drift.

1. Define DTOs

NestJS controllers and DTO classes are the server source for OpenAPI generation.

Source

2. Validate requests

Runtime request validation uses class-validator through NestJS validation pipes.

Validate

3. Generate OpenAPI

@nestjs/swagger generates the OpenAPI document from controllers and DTO metadata.

Spec

4. Generate clients

openapi-typescript generates TypeScript types and openapi-fetch provides the shared fetch client foundation.

Client

5. Check drift

pnpm codegen:check fails CI when generated clients or OpenAPI output drift from source.

Gate

Note

REST semantics, compatibility, response envelopes, and error envelopes are owned by api-contract-standard.

Database Migrations

Database schema changes flow through committed SQL migrations so local work, CI, and promoted environments use the same migration history.

ConcernRule
Access layerDrizzle ORM is the database access layer.
Generate migrationpnpm db:generate runs drizzle-kit generate or the repo-equivalent wrapper.
Commit migrationGenerated SQL migrations are committed.
Apply migrationpnpm db:migrate applies migrations.
Local inspectionpnpm db:studio runs Drizzle Studio for local inspection only.
Prototype shortcutpush is allowed only for disposable local prototyping and never for CI, staging, or production.

Note

Seed and fixture policy belongs primarily to environment-runbook and the Test And Release Gate; this page owns the command names.

Testing

Runner ownership is fixed here so each test type has a clear default tool and adjacent authority pages can own the deeper protocol and release-gate requirements.

Test AreaRule
Unit and integrationVitest owns unit tests and most integration tests for backend and shared packages.
API integrationAPI integration tests can use PostgreSQL, Redis, MinIO, Keycloak test fixtures, and worker processes where required.
Web E2EPlaywright owns coach web browser smoke and E2E tests.
Mobile E2EMaestro owns mobile smoke and E2E flows for coach mobile and client mobile.
Contract testsContract tests compare generated clients, OpenAPI output, and representative API behavior.
Offline syncOffline sync tests follow offline-sync-protocol.
Events and outboxEvent and outbox tests follow event-and-outbox-standard.
Release gateFinal coverage, release smoke matrix, accessibility checks, RTL checks, and launch blockers belong to the Test And Release Gate.

Web Toolchain

The coach web stack uses a consistent set of framework, styling, data, and form tools so page models, interactive state, and shared UI stay aligned.

  • Next.js App Router is the coach web foundation.
  • Tailwind CSS is the web styling baseline.
  • shadcn/ui and Radix primitives are copied or wrapped into packages/ui-web.
  • Shared design tokens feed Tailwind configuration.
  • TanStack Query owns interactive client-side server state.
  • Next.js Server Components may fetch directly for page-level read models where that is cleaner.
  • React Hook Form + Zod resolvers own web form state and validation.
  • Playwright owns browser E2E and smoke tests.

Note

UI design rules belong in product and design docs. This page owns the technical toolchain.

Mobile Toolchain

The mobile stack keeps the two Expo apps aligned on shared primitives, shared infrastructure, and one release toolchain while leaving app-specific UI and flows to the applications.

Apps and Shared UI

  • Coach mobile lives in apps/mobile-coach.
  • Client and personal mobile lives in apps/mobile-client.
  • NativeWind and shared design tokens are the mobile styling baseline.
  • CoachMe-owned packages/ui-mobile is built from React Native primitives and NativeWind.
  • Expo Router is the default navigation layer for now.
  • TanStack Query owns mobile server state.
  • React Hook Form + Zod resolvers own mobile form state and validation.

Shared Core and Delivery

  • packages/mobile-core owns shared auth/session, API client setup, sync helpers, push helpers, localization/RTL helpers, and secure local integration wrappers.
  • Maestro is the default mobile E2E runner.
  • EAS Build, EAS Submit, and EAS Update are the mobile build and release toolchain.

Note

EAS Update can ship compatible JavaScript/runtime fixes. It must not be used for native dependency changes, permission changes, schema changes, contract-breaking changes, or changes that require a new binary.

Configuration Validation

Environment validation is a build and startup concern, not an optional runtime convention, so every consumer that reads configuration must prove its schema.

  • Each app or package that reads environment variables has a Zod schema.
  • pnpm env:check validates required environment schemas.
  • Startup fails fast when required runtime configuration is invalid.
  • Mobile build profiles validate public runtime config before EAS build.
  • The Environment Runbook owns the variable inventory and per-environment values.
  • The Toolchain Contract owns the validation pattern and script gate.

Generated Files

Committed generated assets are limited to files that form part of the contract or migration history, while build outputs and test artifacts stay disposable.

PolicyRule
CommitOpenAPI clients in packages/contracts when needed by consumers and CI drift checks.
CommitDrizzle SQL migrations.
Do not commit.next, dist, coverage output, Turbo cache, Expo build artifacts, and Playwright or Maestro test artifacts.
ExceptionA release process may later define a committed artifact bundle, but this contract does not require one for Public V1 planning.
GateCI fails when committed generated files do not match source.

CI And Merge

Merge readiness depends on stable root commands, with GitHub Actions enforcing the contract and the Test And Release Gate defining deeper thresholds and evidence.

  • Install dependencies with pnpm 10 and cache pnpm/Turbo appropriately.
  • Run pnpm format:check.
  • Run pnpm lint.
  • Run pnpm typecheck.
  • Run pnpm test.
  • Run pnpm codegen:check.
  • Run pnpm security:check.
  • Run migration checks when database code changes.
  • Run pnpm build.
  • Run Playwright smoke coverage once coach web flows exist.
  • Run Maestro smoke coverage once mobile apps and test flows exist.

Note

Exact required checks, thresholds, release-candidate gates, and app-store smoke evidence belong to the Test And Release Gate.

Updates And Releases

Dependency automation and release-note tooling are fixed at the contract level so routine updates and release communication follow one documented path.

Renovate

Renovate is the dependency update tool. Low-risk dev tooling updates can be grouped, major updates are separate, and Expo, React Native, EAS, mobile native dependencies, and framework major upgrades are reviewed deliberately.

Changesets

Changesets records release-note intent for app and package changes. Package publishing is disabled unless CoachMe later decides to publish shared packages.

Observability SDK Updates

Pino, Sentry, OpenTelemetry SDK major changes, and semantic-convention changes use separate Renovate changes. Re-run redaction, metric/query compatibility, startup, exporter, and source-map evidence. Updates cannot silently enable client OTel, Sentry logs, tracing, replay, profiling, screenshots, or performance tracing.

Release Notes

App release notes can be generated from changesets and release metadata once release automation exists.

Revisitable Decisions

This section separates defaults that can change with documented rationale from baseline choices that require a formal contract update before they move.

Revisitable With Recorded Rationale

  • Mobile E2E: Maestro remains the default unless Expo or EAS constraints make it impractical, in which case a replacement can be adopted through a documented toolchain update.
  • Mobile navigation: Expo Router remains the default unless direct React Navigation becomes the cleaner implementation choice for the mobile apps.
  • The exact root script list can evolve while root scripts stay the stable developer and CI contract.
  • Security scanner implementation may change through a documented Toolchain update while pnpm security:secrets, pnpm security:dependencies, and pnpm security:check remain the stable command contract.

Non-Revisitable Without Formal Contract Update

  • Node.js 24 LTS + pnpm 10 stay locked as the baseline runtime and package manager pair.
  • pnpm workspaces + Turborepo stay locked as the monorepo orchestration model.
  • Drizzle ORM + drizzle-kit stay locked for schema access and migration generation.
  • NestJS DTOs + class-validator + @nestjs/swagger stay locked for request validation and OpenAPI generation.
  • openapi-typescript + openapi-fetch stay locked for generated API clients.
  • Vitest + Playwright stay locked for unit, integration, and web E2E coverage.
  • GitHub Actions stays locked as the CI provider.
  • EAS Build + EAS Submit + EAS Update stay locked for mobile release flows.
  • Tailwind CSS + NativeWind + shared design tokens stay locked for styling foundations.
  • shadcn/ui + Radix primitives stay locked for web UI primitives.
  • CoachMe-owned mobile UI package stays locked for mobile UI ownership.
  • TanStack Query stays locked for client server-state management.
  • React Hook Form + Zod stay locked for form composition and validation.
  • Zod env validation stays locked for runtime configuration checks.
  • Husky + lint-staged stay locked for local changed-file hooks.
  • Renovate stays locked for dependency update automation.
  • Changesets stays locked for release-note workflow.
  • tsup + tsc --noEmit stay locked for shared package builds and type validation.

These documents own adjacent behavior, platform policy, and authority details that this toolchain contract references but does not redefine.

Workflow State Map

Cross-system workflow states and transitions.

Roles And Permissions

Role model and access boundaries.

API Contract Standard

REST semantics, error envelopes, and compatibility rules.

Event And Outbox Standard

Event publication, outbox handling, and integration guarantees.

Offline Sync Protocol

Sync behavior, conflict handling, and offline expectations.

Environment Runbook

Environment inventory, variables, and runtime operations.

Observability Plan

Owns signal semantics; this contract owns package, build, source-map, version-lock, and update mechanics.

Test And Release Gate

Release evidence, thresholds, and final approval gates.

Technical Architecture Plan

Architecture rationale and system decomposition.

Public V1 Scope Contract

Scope boundaries for the initial public product slice.

CoachMe internal planning documentation.