home / skills / krosebrook / source-of-truth-monorepo / turbo-monorepo-expert

turbo-monorepo-expert skill

/.claude-custom/skills/turbo-monorepo-expert

This skill provides expert Turborepo and pnpm workspace guidance to optimize large monorepos and accelerate builds.

npx playbooks add skill krosebrook/source-of-truth-monorepo --skill turbo-monorepo-expert

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
14.0 KB
---
name: Turbo Monorepo Expert
description: Expert guidance for Turborepo and pnpm workspace management, build optimization, caching strategies, and monorepo architecture patterns. Use when working with Turbo monorepos, pnpm workspaces, or multi-package projects.
version: 1.0.0
allowed-tools:
  - Read
  - Write
  - Edit
  - Bash
  - Glob
  - Grep
---

# Turbo Monorepo Expert

Expert system for Turborepo (Turbo) and pnpm workspace management, optimized for large-scale monorepo architectures.

## Core Capabilities

### 1. Turborepo Architecture & Setup

**Optimal turbo.json Configuration:**
```json
{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": [".env", "tsconfig.json"],
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "build/**"],
      "env": ["NODE_ENV"]
    },
    "test": {
      "dependsOn": ["build"],
      "outputs": ["coverage/**"],
      "cache": false
    },
    "lint": {
      "outputs": []
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "type-check": {
      "dependsOn": ["^build"],
      "outputs": []
    }
  },
  "remoteCache": {
    "enabled": true
  }
}
```

**Root package.json Structure:**
```json
{
  "name": "monorepo-root",
  "private": true,
  "workspaces": [
    "apps/*",
    "packages/*",
    "services/*"
  ],
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev --parallel",
    "test": "turbo run test",
    "lint": "turbo run lint",
    "type-check": "turbo run type-check",
    "clean": "turbo run clean && rm -rf node_modules"
  },
  "devDependencies": {
    "turbo": "latest",
    "@turbo/gen": "latest"
  },
  "packageManager": "[email protected]",
  "engines": {
    "node": ">=18.0.0",
    "pnpm": ">=8.0.0"
  }
}
```

### 2. pnpm Workspace Configuration

**Root pnpm-workspace.yaml:**
```yaml
packages:
  - 'apps/*'
  - 'packages/*'
  - 'services/*'
  - 'tools/*'
```

**.npmrc Best Practices:**
```ini
# Hoist dependencies for faster installs
shamefully-hoist=true
# Strict peer dependencies
strict-peer-dependencies=false
# Use workspace protocol
link-workspace-packages=true
# Save exact versions
save-exact=true
# Faster installs
prefer-frozen-lockfile=true
# Store location
store-dir=~/.pnpm-store
```

### 3. Package Organization Patterns

**Recommended Structure:**
```
monorepo-root/
├── apps/                    # Deployable applications
│   ├── web/                # Next.js app
│   ├── api/                # Backend service
│   └── admin/              # Admin dashboard
├── packages/               # Shared libraries
│   ├── ui/                 # Component library
│   ├── config/             # Shared configs
│   ├── utils/              # Utilities
│   └── types/              # TypeScript types
├── services/               # Microservices
│   ├── auth/
│   ├── payments/
│   └── notifications/
├── tools/                  # Build tools & scripts
├── turbo.json
├── pnpm-workspace.yaml
└── package.json
```

**Package Naming Convention:**
```
@scope/package-name

Examples:
@company/ui
@company/utils
@company/config-eslint
@company/config-typescript
```

### 4. Internal Package Template

**packages/ui/package.json:**
```json
{
  "name": "@company/ui",
  "version": "0.0.0",
  "private": true,
  "main": "./dist/index.js",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.js",
      "types": "./dist/index.d.ts"
    },
    "./styles.css": "./dist/styles.css"
  },
  "scripts": {
    "build": "tsup src/index.ts --format cjs,esm --dts",
    "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
    "lint": "eslint src/",
    "type-check": "tsc --noEmit"
  },
  "devDependencies": {
    "@company/config-typescript": "workspace:*",
    "@company/config-eslint": "workspace:*",
    "tsup": "^8.0.0",
    "typescript": "^5.3.0"
  },
  "dependencies": {
    "react": "^18.2.0"
  }
}
```

### 5. Build Optimization Strategies

**Parallel Execution:**
```bash
# Run tasks in parallel across all packages
turbo run build --parallel

# Run specific packages only
turbo run build --filter=@company/ui

# Run app and its dependencies
turbo run build --filter=web...
```

**Cache Management:**
```bash
# Clear all caches
turbo run clean

# Disable cache for specific run
turbo run build --force

# Check cache hit rate
turbo run build --summarize
```

**Remote Caching (Vercel):**
```bash
# Link to Vercel for remote caching
turbo login
turbo link

# Verify remote cache
turbo run build --remote-only
```

### 6. Dependency Management

**Adding Dependencies:**
```bash
# Add to root
pnpm add -w <package>

# Add to specific workspace
pnpm add <package> --filter @company/ui

# Add workspace dependency
pnpm add @company/utils --filter @company/ui --workspace
```

**Dependency Protocol:**
```json
{
  "dependencies": {
    "@company/utils": "workspace:*",  // Latest in workspace
    "@company/ui": "workspace:^",     // Compatible version
    "react": "^18.2.0"                // External dependency
  }
}
```

### 7. TypeScript Configuration

**Root tsconfig.json:**
```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "incremental": true,
    "noEmit": true
  },
  "exclude": ["node_modules"]
}
```

**Package-specific tsconfig.json:**
```json
{
  "extends": "@company/config-typescript/base.json",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}
```

### 8. Code Generation with @turbo/gen

**Generate New Package:**
```bash
turbo gen workspace

# Follow prompts:
# - Name: @company/new-package
# - Type: package
# - Template: library
```

**Custom Generator:**
```typescript
// turbo/generators/config.ts
import type { PlopTypes } from "@turbo/gen";

export default function generator(plop: PlopTypes.NodePlopAPI): void {
  plop.setGenerator("package", {
    description: "Create new package",
    prompts: [
      {
        type: "input",
        name: "name",
        message: "Package name (without @company/):",
      },
      {
        type: "list",
        name: "type",
        message: "Package type:",
        choices: ["library", "config", "service"],
      },
    ],
    actions: [
      {
        type: "add",
        path: "packages/{{name}}/package.json",
        templateFile: "templates/package.json.hbs",
      },
      {
        type: "add",
        path: "packages/{{name}}/src/index.ts",
        templateFile: "templates/index.ts.hbs",
      },
    ],
  });
}
```

### 9. Common Patterns & Solutions

**Circular Dependency Detection:**
```bash
# Install dependency checker
pnpm add -Dw madge

# Check for cycles
madge --circular --extensions ts,tsx apps/web/src
```

**Shared Environment Variables:**
```typescript
// packages/env/src/index.ts
import { z } from "zod";

const envSchema = z.object({
  NODE_ENV: z.enum(["development", "production", "test"]),
  DATABASE_URL: z.string().url(),
  API_KEY: z.string().min(1),
});

export const env = envSchema.parse(process.env);
```

**Shared ESLint Configuration:**
```javascript
// packages/config-eslint/index.js
module.exports = {
  extends: [
    "next/core-web-vitals",
    "plugin:@typescript-eslint/recommended",
    "prettier",
  ],
  parser: "@typescript-eslint/parser",
  plugins: ["@typescript-eslint"],
  rules: {
    "@typescript-eslint/no-unused-vars": "error",
    "@typescript-eslint/no-explicit-any": "warn",
  },
};
```

### 10. Performance Optimization

**Task Dependency Optimization:**
```json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],           // Wait for dependencies
      "outputs": ["dist/**"],
      "inputs": ["src/**", "package.json"]  // Track specific inputs
    }
  }
}
```

**Selective Task Running:**
```bash
# Only changed packages
turbo run build --filter=[HEAD^1]

# Specific scope
turbo run test --filter=@company/ui...

# Exclude packages
turbo run build --filter=!@company/deprecated
```

**Parallel Limits:**
```bash
# Limit concurrent tasks (for CI with limited resources)
turbo run build --concurrency=2

# Prevent OOM on large repos
export NODE_OPTIONS="--max-old-space-size=4096"
```

### 11. CI/CD Integration

**GitHub Actions Example:**
```yaml
name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v2
        with:
          version: 8
      - uses: actions/setup-node@v4
        with:
          node-version: 18
          cache: 'pnpm'

      - run: pnpm install --frozen-lockfile

      - name: Build
        run: turbo run build --filter=[HEAD^1]
        env:
          TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
          TURBO_TEAM: ${{ vars.TURBO_TEAM }}

      - name: Test
        run: turbo run test --filter=[HEAD^1]

      - name: Lint
        run: turbo run lint --filter=[HEAD^1]
```

### 12. Migration Strategies

**From npm/yarn to pnpm + Turbo:**
```bash
# 1. Remove existing
rm -rf node_modules package-lock.json yarn.lock

# 2. Install pnpm
npm install -g pnpm

# 3. Import from package-lock.json
pnpm import

# 4. Install dependencies
pnpm install

# 5. Add Turbo
pnpm add -Dw turbo

# 6. Create turbo.json
turbo gen config
```

**Convert existing scripts:**
```json
{
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev --parallel",
    "test": "turbo run test --concurrency=1",
    "clean": "turbo run clean && rm -rf node_modules"
  }
}
```

### 13. Troubleshooting Guide

**Common Issues:**

1. **"Package not found" errors:**
   ```bash
   # Clear all node_modules and reinstall
   pnpm clean:all
   pnpm install
   ```

2. **Cache issues:**
   ```bash
   # Clear Turbo cache
   rm -rf .turbo

   # Clear pnpm cache
   pnpm store prune
   ```

3. **Build failures in CI:**
   ```bash
   # Use frozen lockfile
   pnpm install --frozen-lockfile

   # Disable remote cache if issues
   turbo run build --remote-only=false
   ```

4. **Slow installs:**
   ```ini
   # .npmrc
   auto-install-peers=true
   shamefully-hoist=true
   ```

### 14. Best Practices Checklist

- [ ] Use `workspace:*` protocol for internal dependencies
- [ ] Configure `globalDependencies` in turbo.json (.env, tsconfig)
- [ ] Set up remote caching (Vercel Turborepo or custom)
- [ ] Use `--filter` in CI to build only changed packages
- [ ] Configure `outputs` correctly for all tasks
- [ ] Use `dependsOn: ["^task"]` for proper build order
- [ ] Set `cache: false` for dev and test tasks
- [ ] Use consistent naming (@scope/package-name)
- [ ] Configure `engines` field for Node/pnpm versions
- [ ] Use `turbo gen` for new packages
- [ ] Set up path aliases in tsconfig
- [ ] Use shared ESLint/TypeScript configs
- [ ] Configure `.gitignore` for Turbo cache

### 15. Advanced Patterns

**Conditional Task Execution:**
```json
{
  "pipeline": {
    "deploy": {
      "dependsOn": ["build", "test"],
      "cache": false,
      "env": ["AWS_*", "VERCEL_*"]
    }
  }
}
```

**Task-Specific Environment Variables:**
```json
{
  "pipeline": {
    "build": {
      "env": ["NODE_ENV", "NEXT_PUBLIC_*"],
      "passThroughEnv": ["CI", "VERCEL"]
    }
  }
}
```

**Scoped Tasks:**
```bash
# Run only in apps
turbo run build --filter='./apps/*'

# Run in packages, not apps
turbo run test --filter='./packages/*'

# Complex filters
turbo run build --filter='@company/api...[origin/main]'
```

## Quick Commands Reference

```bash
# Installation
pnpm install                                    # Install all dependencies
pnpm add <pkg> --filter <workspace>            # Add to specific package
pnpm add <pkg> -w                              # Add to root

# Turbo Operations
turbo run build                                # Build all
turbo run build --filter=<package>             # Build specific package
turbo run dev --parallel                       # Run dev servers
turbo run test --concurrency=1                 # Run tests sequentially
turbo run lint --continue                      # Continue on errors

# Filters
turbo run build --filter=[HEAD^1]              # Changed since last commit
turbo run build --filter=<package>...          # Package + dependencies
turbo run build --filter=...<package>          # Package + dependents

# Cache
turbo run build --force                        # Skip cache
turbo run build --summarize                    # Show cache stats
turbo prune --scope=<package>                  # Create pruned subset

# Workspace Management
pnpm -r exec <command>                         # Run in all workspaces
pnpm --filter <package> <command>              # Run in specific workspace
turbo gen workspace                            # Generate new package

# Cleaning
turbo run clean                                # Run clean tasks
rm -rf .turbo                                  # Clear Turbo cache
pnpm store prune                               # Clear pnpm cache
```

## Integration with Existing Tools

**Vercel:**
```json
{
  "buildCommand": "turbo run build --filter={apps/web}...",
  "installCommand": "pnpm install"
}
```

**Docker:**
```dockerfile
FROM node:18-alpine AS base
RUN npm install -g pnpm turbo
WORKDIR /app

FROM base AS deps
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
COPY packages ./packages
RUN pnpm install --frozen-lockfile

FROM base AS builder
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN turbo run build --filter=api

FROM base AS runner
COPY --from=builder /app/apps/api/dist ./dist
CMD ["node", "dist/index.js"]
```

---

## When to Use This Skill

Invoke this skill when:
- Setting up new Turborepo monorepo
- Migrating to Turbo from Lerna/Nx/Rush
- Optimizing build times and caching
- Configuring pnpm workspaces
- Troubleshooting monorepo issues
- Setting up CI/CD for monorepo
- Creating new packages or apps
- Managing internal dependencies
- Scaling monorepo architecture

Overview

This skill provides expert guidance for managing Turborepo and pnpm workspaces in large-scale TypeScript monorepos. It focuses on architecture, workspace setup, build optimization, remote caching, and migration strategies. Use it to reduce CI time, avoid dependency pitfalls, and scale a multi-package ecosystem reliably.

How this skill works

The skill inspects and recommends turbo.json, pnpm-workspace.yaml, root/package.json, and package-level package.json and tsconfig files to enforce consistent conventions. It suggests pipeline configurations, cache and outputs settings, workspace dependency protocols, and CI integrations. It also offers commands and patterns for selective builds, remote caching, code generation, and troubleshooting common failures.

When to use it

  • Setting up a new Turborepo monorepo with pnpm workspaces
  • Migrating from npm/yarn/Lerna/Nx to Turbo + pnpm
  • Optimizing CI build time and enabling remote cache
  • Configuring workspace package relationships and internal dependency protocol
  • Diagnosing build/cache/install failures in a large repo

Best practices

  • Use workspace:* for internal dependencies and set engines for Node/pnpm versions
  • Define globalDependencies (env, tsconfig) and reliable outputs in turbo.json for correct caching
  • Keep dev/test tasks cache:false; set persistent dev tasks to avoid stale state
  • Use --filter in CI to run only changed packages and limit concurrency for resource-constrained runners
  • Centralize shared ESLint/TypeScript configs and enforce package naming conventions (@scope/name)

Example use cases

  • Create a new shared UI package with turbo gen and workspace templates
  • Add a workspace dependency and build only affected apps using turbo run build --filter=@company/ui...
  • Enable Vercel remote cache and verify cache hits with turbo run build --summarize
  • Migrate a legacy repo: import lockfile, install pnpm, add turbo, and generate turbo.json
  • Debug CI failures by running pnpm install --frozen-lockfile and clearing .turbo and pnpm store

FAQ

How do I force a clean build ignoring cache?

Run turbo run build --force or remove .turbo and rerun the pipeline.

When should I disable remote cache in CI?

Disable if you see inconsistent artifacts or debugging build differences; use --remote-only or set remote cache false for the run.

How do I add a package to a specific workspace?

Use pnpm add <pkg> --filter <workspace> to add to a specific package, or pnpm add -w <pkg> to add to the root workspace.