home / skills / brixtonpham / claude-config / turborepo

turborepo skill

/skills/turborepo

This is most likely a fork of the turborepo skill from einverne
npx playbooks add skill brixtonpham/claude-config --skill turborepo

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

Files (1)
SKILL.md
21.1 KB
---
name: turborepo
description: Guide for implementing Turborepo - a high-performance build system for JavaScript and TypeScript monorepos. Use when setting up monorepos, optimizing build performance, implementing task pipelines, configuring caching strategies, or orchestrating tasks across multiple packages.
license: MIT
version: 1.0.0
---

# Turborepo Skill

Turborepo is a high-performance build system optimized for JavaScript and TypeScript monorepos, written in Rust. It provides intelligent caching, task orchestration, and remote execution capabilities to dramatically speed up development workflows.

## Reference

https://turborepo.com/llms.txt

## When to Use This Skill

Use this skill when:
- Setting up a new monorepo with multiple packages
- Optimizing build performance in existing monorepos
- Implementing task pipelines across packages
- Configuring intelligent caching strategies
- Setting up remote caching for teams
- Orchestrating tasks with dependency awareness
- Integrating monorepo with CI/CD pipelines
- Migrating from Lerna, Nx, or other monorepo tools
- Building microfrontends or shared libraries
- Managing workspace dependencies

## Core Concepts

### 1. Monorepo Architecture
Turborepo organizes code into packages within a single repository:
- **Root Package**: Contains workspace configuration
- **Internal Packages**: Shared libraries, utilities, configs
- **Applications**: Frontend apps, backend services, etc.
- **Workspaces**: npm/yarn/pnpm workspace configuration

### 2. Task Pipeline
Tasks are organized in a dependency graph:
- **Task Dependencies**: Define execution order (build before test)
- **Package Dependencies**: Respect internal package relationships
- **Parallel Execution**: Run independent tasks simultaneously
- **Topological Ordering**: Execute tasks in correct dependency order

### 3. Intelligent Caching
Turborepo caches task outputs based on inputs:
- **Local Cache**: Stores outputs on local machine
- **Remote Cache**: Shares cache across team/CI (Vercel or custom)
- **Content-Based Hashing**: Only re-run when inputs change
- **Cache Restoration**: Instant task completion from cache

### 4. Task Outputs
Define what gets cached:
- Build artifacts (dist/, build/)
- Test results
- Generated files
- Type definitions

## Installation

### Prerequisites
```bash
# Requires Node.js 18+ and a package manager
node --version  # v18.0.0+
```

### Global Installation
```bash
# npm
npm install turbo --global

# yarn
yarn global add turbo

# pnpm
pnpm add turbo --global

# bun
bun add turbo --global
```

### Per-Project Installation
```bash
# npm
npm install turbo --save-dev

# yarn
yarn add turbo --dev

# pnpm
pnpm add turbo --save-dev

# bun
bun add turbo --dev
```

## Project Setup

### Create New Monorepo

Using official examples:
```bash
npx create-turbo@latest
```

Interactive prompts will ask:
- Project name
- Package manager (npm/yarn/pnpm/bun)
- Example template selection

### Manual Setup

**1. Initialize workspace:**

```json
// package.json (root)
{
  "name": "my-turborepo",
  "private": true,
  "workspaces": ["apps/*", "packages/*"],
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "test": "turbo run test",
    "lint": "turbo run lint"
  },
  "devDependencies": {
    "turbo": "latest"
  }
}
```

**2. Create directory structure:**
```
my-turborepo/
├── apps/
│   ├── web/              # Next.js app
│   └── docs/             # Documentation site
├── packages/
│   ├── ui/               # Shared UI components
│   ├── config/           # Shared configs (ESLint, TS)
│   └── tsconfig/         # Shared TypeScript configs
├── turbo.json            # Turborepo configuration
└── package.json          # Root package.json
```

**3. Create turbo.json:**
```json
{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": ["**/.env.*local"],
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**", "dist/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "lint": {},
    "test": {
      "dependsOn": ["build"]
    }
  }
}
```

## Configuration (turbo.json)

### Basic Structure
```json
{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": [".env", "tsconfig.json"],
  "globalEnv": ["NODE_ENV"],
  "pipeline": {
    // Task definitions
  }
}
```

### Pipeline Configuration

**Task with dependencies:**
```json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**"],
      "env": ["NODE_ENV", "API_URL"]
    }
  }
}
```

**Key properties:**
- `dependsOn`: Tasks to run first
  - `["^build"]`: Run dependencies' build first
  - `["build"]`: Run own build first
  - `["^build", "lint"]`: Run deps' build and own lint
- `outputs`: Files/directories to cache
- `inputs`: Override input detection (default: all tracked files)
- `cache`: Enable/disable caching (default: true)
- `env`: Environment variables that affect output
- `persistent`: Keep task running (for dev servers)
- `outputMode`: Control output display

### Task Dependency Patterns

**Topological (^):**
```json
{
  "build": {
    "dependsOn": ["^build"]  // Run dependencies' build first
  }
}
```

**Regular:**
```json
{
  "deploy": {
    "dependsOn": ["build", "test"]  // Run own build and test first
  }
}
```

**Combined:**
```json
{
  "test": {
    "dependsOn": ["^build", "lint"]  // Deps' build, then own lint
  }
}
```

### Output Modes

```json
{
  "pipeline": {
    "build": {
      "outputMode": "full"        // Show all output
    },
    "dev": {
      "outputMode": "hash-only"   // Show cache hash only
    },
    "test": {
      "outputMode": "new-only"    // Show new output only
    },
    "lint": {
      "outputMode": "errors-only" // Show errors only
    }
  }
}
```

### Environment Variables

**Global environment variables:**
```json
{
  "globalEnv": ["NODE_ENV", "CI"],
  "globalDependencies": [".env", ".env.local"]
}
```

**Per-task environment variables:**
```json
{
  "pipeline": {
    "build": {
      "env": ["NEXT_PUBLIC_API_URL", "DATABASE_URL"],
      "passThroughEnv": ["CUSTOM_VAR"]  // Pass without hashing
    }
  }
}
```

## Commands

### turbo run

Run tasks across packages:

```bash
# Run build in all packages
turbo run build

# Run multiple tasks
turbo run build test lint

# Run in specific packages
turbo run build --filter=web
turbo run build --filter=@myorg/ui

# Run in packages matching pattern
turbo run build --filter='./apps/*'

# Force execution (skip cache)
turbo run build --force

# Run from specific directory
turbo run build --filter='[./apps/web]'

# Run with dependencies
turbo run build --filter='...^web'

# Parallel execution control
turbo run build --concurrency=3
turbo run build --concurrency=50%

# Continue on error
turbo run test --continue

# Dry run
turbo run build --dry-run

# Output control
turbo run build --output-logs=new-only
turbo run build --output-logs=hash-only
turbo run build --output-logs=errors-only
turbo run build --output-logs=full
```

### turbo prune

Create a subset of the monorepo:

```bash
# Prune for specific app
turbo prune --scope=web

# Prune with Docker
turbo prune --scope=api --docker

# Output to custom directory
turbo prune --scope=web --out-dir=./deploy
```

**Use cases:**
- Docker builds (only include necessary packages)
- Deploy specific apps
- Reduce CI/CD context size

### turbo gen

Generate code in your monorepo:

```bash
# Generate new package
turbo gen workspace

# Generate from custom generator
turbo gen my-generator

# List available generators
turbo gen --list
```

### turbo link

Link local repo to remote cache:

```bash
# Link to Vercel
turbo link

# Unlink
turbo unlink
```

### turbo login

Authenticate with Vercel:

```bash
turbo login
```

### turbo ls

List packages in monorepo:

```bash
# List all packages
turbo ls

# JSON output
turbo ls --json
```

## Filtering

### Filter by Package Name

```bash
# Single package
turbo run build --filter=web

# Multiple packages
turbo run build --filter=web --filter=api

# Scoped package
turbo run build --filter=@myorg/ui
```

### Filter by Pattern

```bash
# All apps
turbo run build --filter='./apps/*'

# Pattern matching
turbo run build --filter='*-ui'
```

### Filter by Directory

```bash
# From specific directory
turbo run build --filter='[./apps/web]'
```

### Filter by Git

```bash
# Changed since main
turbo run build --filter='[main]'

# Changed since HEAD~1
turbo run build --filter='[HEAD~1]'

# Changed in working directory
turbo run test --filter='...[HEAD]'
```

### Filter by Dependencies

```bash
# Package and its dependencies
turbo run build --filter='...web'

# Package's dependencies only
turbo run build --filter='...^web'

# Package and its dependents
turbo run test --filter='ui...'

# Package's dependents only
turbo run test --filter='^ui...'
```

## Caching Strategies

### Local Caching

Enabled by default, stores in `./node_modules/.cache/turbo`

**Cache behavior:**
```json
{
  "pipeline": {
    "build": {
      "outputs": ["dist/**"],  // Cache dist directory
      "cache": true            // Enable caching (default)
    },
    "dev": {
      "cache": false           // Disable for dev servers
    }
  }
}
```

**Clear cache:**
```bash
# Clear Turbo cache
rm -rf ./node_modules/.cache/turbo

# Or use turbo command
turbo run build --force  # Skip cache for this run
```

### Remote Caching

Share cache across team and CI:

**1. Link to Vercel (recommended):**
```bash
turbo login
turbo link
```

**2. Custom remote cache:**
```json
// .turbo/config.json
{
  "teamid": "team_123",
  "apiurl": "https://cache.example.com",
  "token": "your-token"
}
```

**Benefits:**
- Share builds across team
- Speed up CI/CD
- Consistent builds
- Reduce compute costs

### Cache Signatures

Cache is invalidated when:
- Source files change
- Dependencies change
- Environment variables change (if specified)
- Global dependencies change
- Task configuration changes

**Control inputs:**
```json
{
  "pipeline": {
    "build": {
      "inputs": ["src/**/*.ts", "!src/**/*.test.ts"],
      "env": ["NODE_ENV"]
    }
  }
}
```

## Workspace Patterns

### Package Types

**1. Internal packages (packages/*):**
```json
// packages/ui/package.json
{
  "name": "@myorg/ui",
  "version": "0.0.0",
  "main": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "scripts": {
    "build": "tsc",
    "dev": "tsc --watch",
    "lint": "eslint ."
  }
}
```

**2. Applications (apps/*):**
```json
// apps/web/package.json
{
  "name": "web",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "@myorg/ui": "*",
    "next": "latest"
  },
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  }
}
```

### Dependency Management

**Workspace protocol (pnpm/yarn):**
```json
{
  "dependencies": {
    "@myorg/ui": "workspace:*"
  }
}
```

**Version protocol (npm):**
```json
{
  "dependencies": {
    "@myorg/ui": "*"
  }
}
```

### Shared Configuration

**ESLint config package:**
```js
// packages/eslint-config/index.js
module.exports = {
  extends: ["next", "prettier"],
  rules: {
    // shared rules
  }
}
```

**TypeScript config package:**
```json
// packages/tsconfig/base.json
{
  "compilerOptions": {
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}
```

**Usage:**
```json
// apps/web/tsconfig.json
{
  "extends": "@myorg/tsconfig/base.json",
  "compilerOptions": {
    "jsx": "preserve"
  }
}
```

## CI/CD Integration

### GitHub Actions

```yaml
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 18

      - name: Install dependencies
        run: npm install

      - name: Build
        run: npx turbo run build
        env:
          TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
          TURBO_TEAM: ${{ secrets.TURBO_TEAM }}

      - name: Test
        run: npx turbo run test
```

### GitLab CI

```yaml
image: node:18

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - node_modules/
    - .turbo/

build:
  stage: build
  script:
    - npm install
    - npx turbo run build
  variables:
    TURBO_TOKEN: $TURBO_TOKEN
    TURBO_TEAM: $TURBO_TEAM
```

### Docker

```dockerfile
FROM node:18-alpine AS base

# Prune workspace
FROM base AS builder
RUN npm install -g turbo
COPY . .
RUN turbo prune --scope=web --docker

# Install dependencies
FROM base AS installer
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/package-lock.json ./package-lock.json
RUN npm install

# Build
COPY --from=builder /app/out/full/ .
RUN npx turbo run build --filter=web

# Runner
FROM base AS runner
COPY --from=installer /app/apps/web/.next/standalone ./
COPY --from=installer /app/apps/web/.next/static ./apps/web/.next/static
COPY --from=installer /app/apps/web/public ./apps/web/public

CMD node apps/web/server.js
```

### Optimization Tips

1. **Use remote caching in CI:**
```yaml
env:
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
  TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
```

2. **Cache node_modules:**
```yaml
- uses: actions/cache@v3
  with:
    path: node_modules
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
```

3. **Run only affected tasks:**
```bash
turbo run build test --filter='...[origin/main]'
```

## Framework Integration

### Next.js

```json
// apps/web/package.json
{
  "name": "web",
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "latest",
    "react": "latest"
  }
}
```

**turbo.json:**
```json
{
  "pipeline": {
    "build": {
      "outputs": [".next/**", "!.next/cache/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}
```

### Vite

```json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}
```

### NuxtJS

```json
{
  "pipeline": {
    "build": {
      "outputs": [".output/**", ".nuxt/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}
```

## Development Tools Integration

### TypeScript

```json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", "*.tsbuildinfo"]
    },
    "typecheck": {
      "dependsOn": ["^build"]
    }
  }
}
```

### ESLint

```json
{
  "pipeline": {
    "lint": {
      "dependsOn": ["^build"],
      "outputs": []
    }
  }
}
```

### Jest / Vitest

```json
{
  "pipeline": {
    "test": {
      "dependsOn": ["build"],
      "outputs": ["coverage/**"],
      "cache": true
    }
  }
}
```

### Prisma

```json
{
  "pipeline": {
    "db:generate": {
      "cache": false
    },
    "db:push": {
      "cache": false
    }
  }
}
```

## Best Practices

### 1. Structure Your Monorepo

```
my-monorepo/
├── apps/                    # Applications
│   ├── web/                # Frontend app
│   ├── api/                # Backend API
│   └── docs/               # Documentation
├── packages/               # Shared packages
│   ├── ui/                 # UI components
│   ├── config/             # Shared configs
│   ├── utils/              # Utilities
│   └── tsconfig/           # TS configs
├── tooling/                # Development tools
│   ├── eslint-config/
│   └── prettier-config/
└── turbo.json
```

### 2. Define Clear Task Dependencies

```json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"]
    },
    "test": {
      "dependsOn": ["build"]
    },
    "lint": {
      "dependsOn": ["^build"]
    },
    "deploy": {
      "dependsOn": ["build", "test", "lint"]
    }
  }
}
```

### 3. Optimize Cache Configuration

- **Cache build outputs, not source files**
- **Include all generated files in outputs**
- **Exclude cache directories** (e.g., `.next/cache`)
- **Disable cache for dev servers**

```json
{
  "pipeline": {
    "build": {
      "outputs": [
        "dist/**",
        ".next/**",
        "!.next/cache/**",
        "storybook-static/**"
      ]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}
```

### 4. Use Environment Variables Wisely

```json
{
  "globalEnv": ["NODE_ENV", "CI"],
  "pipeline": {
    "build": {
      "env": ["NEXT_PUBLIC_API_URL"],
      "passThroughEnv": ["DEBUG"]  // Don't affect cache
    }
  }
}
```

### 5. Leverage Remote Caching

- Enable for all team members
- Configure in CI/CD
- Reduces build times significantly
- Especially beneficial for large teams

### 6. Use Filters Effectively

```bash
# Build only changed packages
turbo run build --filter='...[origin/main]'

# Build specific app with dependencies
turbo run build --filter='...web'

# Test only affected packages
turbo run test --filter='...[HEAD^1]'
```

### 7. Organize Scripts Consistently

Root package.json:
```json
{
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint",
    "test": "turbo run test",
    "clean": "turbo run clean && rm -rf node_modules"
  }
}
```

### 8. Handle Persistent Tasks

```json
{
  "pipeline": {
    "dev": {
      "cache": false,
      "persistent": true  // Keeps running
    }
  }
}
```

## Common Patterns

### Full-Stack Application

```
apps/
├── web/          # Next.js frontend
│   └── package.json
├── api/          # Express backend
│   └── package.json
└── mobile/       # React Native
    └── package.json

packages/
├── ui/           # Shared UI components
├── database/     # Database client/migrations
├── types/        # Shared TypeScript types
└── config/       # Shared configs
```

### Shared Component Library

```
packages/
├── ui/                    # Component library
│   ├── src/
│   ├── package.json
│   └── tsconfig.json
└── ui-docs/              # Storybook
    ├── .storybook/
    ├── stories/
    └── package.json
```

### Microfrontends

```
apps/
├── shell/        # Container app
├── dashboard/    # Dashboard MFE
└── settings/     # Settings MFE

packages/
├── shared-ui/    # Shared components
└── router/       # Routing logic
```

## Troubleshooting

### Cache Issues

**Problem**: Task not using cache when it should
```bash
# Check what's causing cache miss
turbo run build --dry-run=json

# Force rebuild
turbo run build --force

# Clear cache
rm -rf ./node_modules/.cache/turbo
```

**Problem**: Cache too large
```bash
# Limit cache size in turbo.json
{
  "cacheDir": ".turbo",
  "cacheSize": "50gb"
}
```

### Dependency Issues

**Problem**: Internal package not found
```bash
# Ensure workspace is set up correctly
npm install

# Check package names match
npm ls @myorg/ui

# Rebuild dependencies
turbo run build --filter='...web'
```

### Task Execution Issues

**Problem**: Tasks running in wrong order
- Check `dependsOn` configuration
- Use `^task` for dependency tasks
- Verify task names match package.json scripts

**Problem**: Dev server not starting
```json
{
  "pipeline": {
    "dev": {
      "cache": false,
      "persistent": true  // Add this
    }
  }
}
```

### Performance Issues

**Problem**: Builds taking too long
```bash
# Run with concurrency limit
turbo run build --concurrency=2

# Use filters to build less
turbo run build --filter='...[origin/main]'

# Check for unnecessary dependencies
turbo run build --dry-run
```

**Problem**: Remote cache not working
```bash
# Verify authentication
turbo link

# Check environment variables
echo $TURBO_TOKEN
echo $TURBO_TEAM

# Test connection
turbo run build --output-logs=hash-only
```

## Migration Guide

### From Lerna

1. Replace Lerna with Turborepo:
```bash
npm uninstall lerna
npm install turbo --save-dev
```

2. Convert lerna.json to turbo.json:
```json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"]
    }
  }
}
```

3. Update scripts:
```json
{
  "scripts": {
    "build": "turbo run build",
    "test": "turbo run test"
  }
}
```

### From Nx

1. Install Turborepo:
```bash
npm install turbo --save-dev
```

2. Convert nx.json to turbo.json:
- Map targetDefaults to pipeline
- Convert dependsOn syntax
- Configure caching

3. Update workspace configuration
4. Migrate CI/CD scripts

## Resources

- Documentation: https://turbo.build/repo/docs
- Examples: https://github.com/vercel/turbo/tree/main/examples
- Discord: https://turbo.build/discord
- GitHub: https://github.com/vercel/turbo

## Implementation Checklist

When setting up Turborepo:

- [ ] Install Turborepo globally or per-project
- [ ] Set up workspace structure (apps/, packages/)
- [ ] Create turbo.json with pipeline configuration
- [ ] Define task dependencies (build, test, lint)
- [ ] Configure cache outputs for each task
- [ ] Set up global dependencies and environment variables
- [ ] Link to remote cache (Vercel or custom)
- [ ] Configure CI/CD integration
- [ ] Add filtering strategies for large repos
- [ ] Document monorepo structure for team
- [ ] Set up code generation (turbo gen)
- [ ] Configure Docker builds with turbo prune
- [ ] Test caching behavior locally
- [ ] Verify remote cache in CI
- [ ] Optimize concurrency settings