Quality Gates Overview
How linting, formatting, type checking, and pre-commit hooks enforce code quality before code reaches CI.
Quality gates are automated checks that run at two points in the development workflow: locally before each commit (via pre-commit hooks) and in CI before merge. Together they enforce formatting consistency, type safety, lint rules, and SDK boundary compliance across the monorepo.
The Four Gates
| Gate | Tool | Runs locally | Runs in CI | Blocks merge |
|---|---|---|---|---|
| Formatting | Prettier | On staged files (pre-commit) | pnpm format:check | Yes |
| Linting | ESLint (flat config) | On staged .ts/.tsx files (pre-commit) | pnpm turbo lint --affected | Yes |
| Type checking | TypeScript 5.9 strict | Manual (pnpm typecheck) | pnpm turbo typecheck --affected | Yes |
| SDK boundaries | ESLint no-restricted-imports | Same as linting | Same as linting | Yes |
Two additional static analysis tools -- dependency-cruiser (dependency graph validation) and Knip (dead code detection) -- also run in CI but are covered under Delivery -- Architecture Enforcement.
Execution Order
Pre-commit (local)
The pre-commit hook runs via Husky and lint-staged. It targets only staged files, keeping the feedback loop under a few seconds:
- ESLint with
--fixon staged.ts/.tsxfiles (grouped by package for correcttsconfig.jsonresolution) - Prettier with
--writeon all staged files matching supported extensions
CI (pnpm ci:check)
The ci:check script runs every gate in a fixed sequence. If any step fails, the remaining steps do not run:
pnpm format:check-- Prettier (check mode, no writes)pnpm lint-- ESLint via Turborepo (respects--affectedin CI)pnpm dep-cruise-- dependency-cruiser graph validationpnpm lint:dead-code-- Knip dead code detectionpnpm lint:duplication-- jscpd copy-paste detectionpnpm typecheck-- TypeScript via Turborepopnpm test-- Vitest via Turborepopnpm docs:update-detection-- flags stale user-facing docs
Steps 3--5 and 8 are architecture enforcement and documentation quality checks. See Delivery -- Architecture Enforcement and Delivery -- Pipeline for those topics.
Shared Configuration Packages
Quality gate configuration is centralized in two internal packages:
@repo/eslint-config
Provides three ESLint flat config presets and an SDK boundary restriction function:
| Export | Used by | Description |
|---|---|---|
./base | All presets | Core TypeScript rules, naming conventions, complexity limits, import sorting |
./library | packages/* | Extends base (identical today, reserved for library-specific rules) |
./next | apps/web | Extends base + Next.js rules |
./restrictions | All packages | restrictedImports(packageName) function for SDK boundaries |
@repo/typescript-config
Provides three tsconfig.json presets:
| Export | Used by | Description |
|---|---|---|
./base.json | All presets | Strict mode, noUncheckedIndexedAccess, verbatimModuleSyntax, ES2022 target |
./library.json | packages/* | Extends base, sets outDir/rootDir for library builds |
./nextjs.json | apps/web | Extends base, adds JSX/DOM support and the Next.js compiler plugin |
Pages in This Topic
ESLint Configuration
The full rule set: TypeScript strict rules, naming conventions, complexity limits, import sorting, SonarJS code smells, SDK boundary enforcement via no-restricted-imports, and per-package customization.
TypeScript Strictness
The tsconfig.json presets, what each strict flag does, how packages extend the base config, and why verbatimModuleSyntax is enabled.
Prettier Formatting
Prettier configuration, file type coverage, the Tailwind CSS plugin, and the .prettierignore exclusions.
Pre-commit Hooks
The Husky + lint-staged pipeline: how files are grouped by package, the custom ESLint wrapper script, and what happens on each commit.
Related Pages
- Delivery -- Architecture Enforcement -- dependency-cruiser, Knip, and jscpd (the structural analysis gates)
- Delivery -- Pipeline -- the full CI workflow including these gates
- Identity & Access -- Router Enforcement -- architecture tests that verify authorization patterns
ADR-012: CI/CD Pipeline -- Build, Test, Deploy
Decision record for the CI/CD pipeline structure, parallel jobs, local CI parity, and dependency automation.
ESLint Configuration
The shared ESLint flat config -- TypeScript strict rules, naming conventions, complexity limits, import sorting, code smell detection, and SDK boundary enforcement.