Turbo Monorepo Expert
Expert system for Turborepo (Turbo) and pnpm workspace management, optimized for large-scale monorepo architectures.
Core Capabilities
- Turborepo Architecture & Setup
Optimal turbo.json Configuration:
{ "$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:
{ "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": "pnpm@8.15.0", "engines": { "node": ">=18.0.0", "pnpm": ">=8.0.0" } }
- pnpm Workspace Configuration
Root pnpm-workspace.yaml:
packages:
- 'apps/*'
- 'packages/*'
- 'services/*'
- 'tools/*'
.npmrc Best Practices:
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
- 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
- Internal Package Template
packages/ui/package.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" } }
- Build Optimization Strategies
Parallel Execution:
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:
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):
Link to Vercel for remote caching
turbo login turbo link
Verify remote cache
turbo run build --remote-only
- Dependency Management
Adding Dependencies:
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:
{ "dependencies": { "@company/utils": "workspace:*", // Latest in workspace "@company/ui": "workspace:^", // Compatible version "react": "^18.2.0" // External dependency } }
- TypeScript Configuration
Root tsconfig.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:
{ "extends": "@company/config-typescript/base.json", "compilerOptions": { "outDir": "./dist", "rootDir": "./src" }, "include": ["src"], "exclude": ["node_modules", "dist"] }
- Code Generation with @turbo/gen
Generate New Package:
turbo gen workspace
Follow prompts:
- Name: @company/new-package
- Type: package
- Template: library
Custom Generator:
// 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", }, ], }); }
- Common Patterns & Solutions
Circular Dependency Detection:
Install dependency checker
pnpm add -Dw madge
Check for cycles
madge --circular --extensions ts,tsx apps/web/src
Shared Environment Variables:
// 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:
// 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", }, };
- Performance Optimization
Task Dependency Optimization:
{ "pipeline": { "build": { "dependsOn": ["^build"], // Wait for dependencies "outputs": ["dist/"], "inputs": ["src/", "package.json"] // Track specific inputs } } }
Selective Task Running:
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:
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"
- CI/CD Integration
GitHub Actions Example:
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:
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:
{ "scripts": { "build": "turbo run build", "dev": "turbo run dev --parallel", "test": "turbo run test --concurrency=1", "clean": "turbo run clean && rm -rf node_modules" } }
- Troubleshooting Guide
Common Issues:
"Package not found" errors:
Clear all node_modules and reinstall
pnpm clean:all pnpm install
Cache issues:
Clear Turbo cache
rm -rf .turbo
Clear pnpm cache
pnpm store prune
Build failures in CI:
Use frozen lockfile
pnpm install --frozen-lockfile
Disable remote cache if issues
turbo run build --remote-only=false
Slow installs:
.npmrc
auto-install-peers=true shamefully-hoist=true
- 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
- Advanced Patterns
Conditional Task Execution:
{ "pipeline": { "deploy": { "dependsOn": ["build", "test"], "cache": false, "env": ["AWS_", "VERCEL_"] } } }
Task-Specific Environment Variables:
{ "pipeline": { "build": { "env": ["NODE_ENV", "NEXT_PUBLIC_*"], "passThroughEnv": ["CI", "VERCEL"] } } }
Scoped Tasks:
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
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:
{ "buildCommand": "turbo run build --filter={apps/web}...", "installCommand": "pnpm install" }
Docker:
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