Tooling

Turborepo

Turborepo orchestrates tasks across the monorepo with dependency-aware scheduling and caching.

Configuration (turbo.json)

{
  "tasks": {
    "build":     { "dependsOn": ["^build"], "outputs": ["dist/**"] },
    "lint":      { "dependsOn": ["^lint"], "outputs": [] },
    "typecheck": { "dependsOn": ["^typecheck"], "outputs": [] },
    "test":      { "outputs": [] },
    "dev":       { "cache": false, "persistent": true },
    "start":     { "cache": false },
    "clean":     { "cache": false }
  }
}
  • ^build means "build dependencies first" — ensures utils is built before apps.
  • build outputs (dist/**) are cached. Lint, typecheck, and test produce no file outputs but still cache their pass/fail status.
  • dev and start are not cached (cache: false).

--affected Flag

CI uses --affected to only run tasks on packages changed since the last commit on main:

pnpm lint --affected
pnpm typecheck --affected
pnpm test --affected

Environment Variables

turbo.json declares globalDependencies: ["**/.env"] so that changes to .env files invalidate the cache. The build task passes SENTRY_AUTH_TOKEN through to the build environment.

TypeScript

Shared Configs (@syntropy/tsconfig)

Three presets in packages/tsconfig/:

ConfigUse caseKey settings
base.jsonAll packagesES2022 target, ESNext modules, bundler resolution, strict mode
node-library.jsonInternal packagesExtends base + composite, declaration, declarationMap
react-app.jsonReact apps (Vite)Extends base + jsx: react-jsx, noEmit

Composite Builds

Internal packages like utils use node-library.json which enables composite: true. This allows:

  • Incremental builds — TypeScript only recompiles changed files
  • Declaration maps — consumers can "Go to Definition" into source .ts files
  • Project references — explicit dependency graph for the TypeScript compiler

Module Strategy

All packages use ESM exclusively:

  • "type": "module" in every package.json
  • "module": "ESNext" + "moduleResolution": "bundler" in tsconfig
  • "verbatimModuleSyntax": true — enforces explicit import type syntax

Biome / Ultracite

Ultracite provides zero-config Biome presets for formatting and linting.

Configuration (biome.json)

{
  "extends": ["ultracite/biome/core", "ultracite/biome/react"],
  "assist": {
    "actions": {
      "source": { "organizeImports": "on" }
    }
  }
}

Commands

CommandDescription
pnpm checkCheck for lint and formatting issues
pnpm fixAuto-fix all fixable issues
pnpm lint:fixRun biome check --fix . directly
pnpm formatRun biome format --write . directly

Lefthook

Lefthook manages Git hooks. Configuration in lefthook.yml:

pre-commit:
  jobs:
    - run: pnpm ultracite fix
      glob:
        - "**/*.{js,jsx,ts,tsx,json,jsonc,css}"
      stage_fixed: true
  • Runs Ultracite on staged files matching the glob pattern
  • stage_fixed: true — automatically re-stages files after auto-fix
  • Installed via the prepare script (lefthook install) on pnpm install

Vitest

Vitest is the test runner. No shared config file — each package runs vitest run via its test script.

  • Apps use --passWithNoTests to avoid failing when no tests exist yet
  • Test files follow the *.test.ts convention (co-located with source)

manypkg

manypkg validates dependency consistency across the monorepo.

pnpm check:deps   # Check for issues
pnpm fix:deps     # Auto-fix issues

The workspaceProtocol: "require" setting enforces that all internal dependencies use "workspace:*" — preventing packages from accidentally depending on a registry version of a sibling.