Development

Prerequisites

  • Node.js 24+ (see .node-version or CI config)
  • pnpm 10+ (automatically activated via corepack enable)

Getting Started

# Enable pnpm via corepack (one-time)
corepack enable

# Install dependencies
pnpm install

# Start all apps in dev mode
pnpm dev

Dev URLs:

AppURL
Frontendhttp://localhost:5173

Common Commands

Run from the repository root:

CommandDescription
pnpm devStart all apps in watch mode
pnpm buildBuild everything (respects dependency order)
pnpm testRun all tests
pnpm lintLint all packages
pnpm typecheckType-check all packages
pnpm fixAuto-fix lint and formatting (Ultracite/Biome)
pnpm check:depsVerify workspace dependency consistency
pnpm fix:depsAuto-fix dependency inconsistencies

To target a specific package, use Turborepo's --filter:

pnpm build --filter=@syntropy/frontend
pnpm test --filter=@syntropy/utils

Adding a New App

  1. Create the app directory:

    mkdir -p apps/my-app/src
    
  2. Create apps/my-app/package.json:

    {
      "name": "@syntropy/my-app",
      "version": "0.1.0",
      "private": true,
      "type": "module",
      "scripts": {
        "build": "tsc",
        "dev": "tsx watch src/index.ts",
        "start": "node dist/index.js",
        "clean": "rm -rf dist",
        "lint": "biome check .",
        "typecheck": "tsc --noEmit",
        "test": "vitest run --passWithNoTests"
      },
      "devDependencies": {
        "@syntropy/tsconfig": "workspace:*",
        "typescript": "catalog:"
      }
    }
    
  3. Create apps/my-app/tsconfig.json extending a shared config:

    {
      "extends": "@syntropy/tsconfig/base.json",
      "compilerOptions": {
        "outDir": "dist",
        "rootDir": "src"
      },
      "include": ["src"]
    }
    
  4. Run pnpm install to link the new workspace package.

  5. If the app should be deployed, update:

    • Dockerfile (add build output COPY and turbo prune target)
    • scripts/entrypoint.sh (add a new case entry)
    • Kubernetes values files

Adding a New Package

  1. Create the package directory:

    mkdir -p packages/my-package/src
    
  2. Create packages/my-package/package.json:

    {
      "name": "@syntropy/my-package",
      "version": "0.1.0",
      "private": true,
      "type": "module",
      "main": "./dist/index.js",
      "types": "./dist/index.d.ts",
      "exports": {
        ".": {
          "types": "./dist/index.d.ts",
          "import": "./dist/index.js"
        }
      },
      "scripts": {
        "build": "tsc",
        "dev": "tsc --watch",
        "clean": "rm -rf dist",
        "lint": "biome check .",
        "typecheck": "tsc --noEmit",
        "test": "vitest run"
      },
      "devDependencies": {
        "@syntropy/tsconfig": "workspace:*",
        "typescript": "catalog:"
      }
    }
    
  3. Create packages/my-package/tsconfig.json:

    {
      "extends": "@syntropy/tsconfig/node-library.json",
      "compilerOptions": {
        "outDir": "dist",
        "rootDir": "src"
      },
      "include": ["src"]
    }
    
  4. Run pnpm install.

  5. Add the dependency in consuming packages:

    "@syntropy/my-package": "workspace:*"
    

Verifying Setup

After creating a new app or package, use the /verify-setup skill in Claude Code to check that everything follows the monorepo conventions:

/verify-setup apps/my-app
/verify-setup packages/my-package

This runs automated checks against package.json, tsconfig.json, and the directory structure, reporting [PASS]/[FAIL] for each convention with fix suggestions on failures. Checks include:

  • Package naming (@syntropy/<dir-name>), private, and type fields
  • Required scripts (build, dev, clean, lint, typecheck, test)
  • Dependency conventions (workspace:* for internal deps, catalog: for catalog deps)
  • Package exports (main, types, exports) for packages under packages/
  • tsconfig.json structure (extends, include, outDir, rootDir)
  • src/ directory existence

Code Quality

Pre-commit Hook

Lefthook runs automatically on commit. It applies Ultracite (Biome) formatting and linting to staged files and re-stages the fixes (stage_fixed: true).

CI Checks

The GitHub Actions pipeline runs on every push:

  1. pnpm check:deps — dependency consistency
  2. pnpm lint --affected — lint changed packages only
  3. pnpm typecheck --affected — type-check changed packages
  4. pnpm test --affected — test changed packages

Testing

Tests use Vitest. Each package runs vitest run (or vitest run --passWithNoTests for apps).

# Run all tests
pnpm test

# Run tests for a specific package
pnpm test --filter=@syntropy/utils

# Watch mode (in a specific package directory)
cd packages/utils && npx vitest