toolchains/typescript/build/turborepo/SKILL.md
High-performance monorepo build system with intelligent caching, task orchestration, and parallel execution for multi-package repositories and microservices.
npx skillsauth add bobmatnyc/claude-mpm-skills turborepoInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Turborepo is a high-performance monorepo build system with intelligent caching, task orchestration, and parallel execution. It provides fast incremental builds through content-aware hashing and remote caching, ideal for managing multiple packages, apps, and shared code.
# Create new Turborepo (recommended)
npx create-turbo@latest
# Or add to existing monorepo
npm install turbo --save-dev
# Initialize Turborepo
npx turbo init
my-turborepo/
├── apps/
│ ├── web/ # Next.js app
│ └── api/ # Express API
├── packages/
│ ├── ui/ # Shared React components
│ ├── config/ # Shared configs (eslint, tsconfig)
│ └── utils/ # Shared utilities
├── turbo.json # Pipeline configuration
└── package.json # Root package.json
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"]
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"]
},
"lint": {
"outputs": []
},
"dev": {
"cache": false,
"persistent": true
}
}
}
# Build all packages and apps
turbo run build
# Run tests across workspace
turbo run test
# Run tasks in parallel
turbo run lint test build
# Filter by package
turbo run build --filter=web
turbo run test --filter=@myorg/ui
# Run in specific workspace
turbo run dev --filter=web...
Turborepo manages multiple packages in a single repository:
Content-aware hashing for intelligent cache invalidation:
{
"pipeline": {
"build": {
"outputs": ["dist/**", ".next/**"],
"inputs": ["src/**", "package.json"]
}
}
}
.turbo/cache directoryDefine task dependencies and execution order:
{
"pipeline": {
"build": {
"dependsOn": ["^build"], // Dependencies first
"outputs": ["dist/**"]
},
"test": {
"dependsOn": ["build"], // After local build
"outputs": ["coverage/**"]
},
"deploy": {
"dependsOn": ["build", "test"], // Multiple dependencies
"outputs": []
}
}
}
Dependency Operators:
^build: Run dependencies' build tasks first (topological)build: Run local build task firstturborepo-example/
├── apps/
│ ├── web/ # Next.js app
│ │ ├── src/
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── admin/ # Admin dashboard
│ │ ├── src/
│ │ └── package.json
│ └── api/ # Express API
│ ├── src/
│ └── package.json
├── packages/
│ ├── ui/ # Component library
│ │ ├── src/
│ │ │ ├── Button.tsx
│ │ │ ├── Input.tsx
│ │ │ └── index.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── config/ # Shared configs
│ │ ├── eslint-config/
│ │ ├── tsconfig/
│ │ └── tailwind-config/
│ ├── utils/ # Shared utilities
│ │ ├── src/
│ │ │ ├── format.ts
│ │ │ ├── validators.ts
│ │ │ └── index.ts
│ │ └── package.json
│ └── types/ # Shared TypeScript types
│ ├── src/
│ └── package.json
├── .turbo/ # Cache directory
├── turbo.json # Pipeline config
├── package.json # Root package
├── pnpm-workspace.yaml # Workspace definition
└── tsconfig.json # Root TypeScript config
Root package.json:
{
"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",
"clean": "turbo run clean && rm -rf node_modules .turbo"
},
"devDependencies": {
"turbo": "latest"
},
"engines": {
"node": ">=18",
"pnpm": ">=8"
},
"packageManager": "[email protected]"
}
pnpm-workspace.yaml:
packages:
- "apps/*"
- "packages/*"
Fast, efficient, and workspace-native:
# Install dependencies
pnpm install
# Add dependency to specific package
pnpm add react --filter=web
pnpm add @myorg/ui --filter=admin
# Add workspace dependency
cd apps/web
pnpm add @myorg/ui@workspace:*
# Run scripts
pnpm turbo run build
pnpm-workspace.yaml:
packages:
- "apps/*"
- "packages/*"
{
"workspaces": ["apps/*", "packages/*"]
}
npm install
npm run build --workspace=web
npm run test --workspaces
{
"workspaces": {
"packages": ["apps/*", "packages/*"]
}
}
yarn install
yarn workspace web build
yarn workspaces run test
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": [".env", "tsconfig.json"],
"globalEnv": ["NODE_ENV", "API_URL"],
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**", "build/**"],
"env": ["NEXT_PUBLIC_API_URL"],
"outputMode": "new-only"
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"],
"inputs": ["src/**", "test/**", "__tests__/**"]
},
"test:unit": {
"dependsOn": [],
"outputs": [],
"cache": false
},
"lint": {
"dependsOn": [],
"outputs": []
},
"type-check": {
"dependsOn": [],
"outputs": []
},
"dev": {
"cache": false,
"persistent": true
},
"clean": {
"cache": false
}
}
}
dependsOn: Task dependencies
{
"build": {
"dependsOn": ["^build"] // Run dependencies' build first
},
"test": {
"dependsOn": ["build"] // Run local build first
},
"deploy": {
"dependsOn": ["build", "test"] // Multiple tasks
}
}
outputs: Files to cache
{
"build": {
"outputs": [
"dist/**", // Output directory
".next/**", // Next.js build
"!.next/cache/**" // Exclude cache
]
}
}
inputs: Files that invalidate cache
{
"build": {
"inputs": [
"src/**", // Source files
"package.json", // Dependencies
"tsconfig.json" // Config files
]
}
}
env: Environment variables affecting cache
{
"build": {
"env": [
"NEXT_PUBLIC_API_URL",
"DATABASE_URL"
]
}
}
outputMode: Control console output
{
"build": {
"outputMode": "new-only" // Only show new output
// "full" | "hash-only" | "new-only" | "errors-only" | "none"
}
}
cache: Enable/disable caching
{
"dev": {
"cache": false, // Don't cache dev server
"persistent": true // Keep process running
}
}
globalDependencies: Files affecting all tasks
{
"globalDependencies": [
".env",
"tsconfig.json",
"package.json"
]
}
globalEnv: Environment variables for all tasks
{
"globalEnv": [
"NODE_ENV",
"CI",
"VERCEL"
]
}
# Run single task
turbo run build
turbo run test
turbo run lint
# Run multiple tasks
turbo run build test lint
# Run in specific order (sequential)
turbo run build && turbo run test && turbo run deploy
Filter by package:
# Single package
turbo run build --filter=web
turbo run test --filter=@myorg/ui
# Multiple packages
turbo run build --filter=web --filter=admin
turbo run build --filter={web,admin}
Include dependencies:
# Package and its dependencies
turbo run build --filter=web...
# Package and its dependents
turbo run test --filter=...@myorg/ui
Filter by directory:
# All apps
turbo run build --filter=./apps/*
# Specific directory
turbo run test --filter=./packages/ui
Filter by git changes:
# Changed since main
turbo run build --filter=[main]
# Changed in last commit
turbo run test --filter=[HEAD^1]
# Changed packages only
turbo run lint --filter=[origin/main]
Parallel execution:
# Control concurrency
turbo run build --concurrency=4
turbo run test --concurrency=50%
# Unlimited parallel (default)
turbo run lint --concurrency=100%
Force execution (bypass cache):
turbo run build --force
turbo run test --force
Continue on error:
turbo run test --continue
Output modes:
turbo run build --output-logs=new-only
turbo run test --output-logs=errors-only
turbo run lint --output-logs=full
Dry run:
turbo run build --dry
turbo run build --dry=json
Environment modes:
turbo run build --env-mode=strict # Error on missing env vars
turbo run build --env-mode=loose # Allow missing env vars
Automatic file-based caching in .turbo/cache:
# First run: Full execution
turbo run build
# >>> FULL TURBO
# >>> build: cache miss, executing...
# Second run: Cache hit
turbo run build
# >>> FULL TURBO
# >>> build: cache hit, replaying output...
Cache structure:
.turbo/
├── cache/
│ ├── abc123.tar.zst # Compressed outputs
│ └── def456.tar.zst
└── runs/
└── xyz789.json # Run metadata
Share cache across team and CI:
# Link to Vercel
npx turbo login
npx turbo link
# Runs will now use remote cache
turbo run build
# >>> Remote caching enabled
turbo.json with remote cache:
{
"remoteCache": {
"enabled": true
}
}
Self-hosted cache server:
# Configure custom cache
turbo run build --api="https://cache.mycompany.com" --token="${TURBO_TOKEN}"
Environment variables:
export TURBO_API="https://cache.mycompany.com"
export TURBO_TOKEN="your-secret-token"
export TURBO_TEAM="team-id"
Disable caching:
{
"pipeline": {
"dev": {
"cache": false
}
}
}
Cache signatures (what affects cache):
Invalidate cache:
# Delete local cache
rm -rf .turbo/cache
# Force rebuild
turbo run build --force
Shared component library:
packages/ui/
├── src/
│ ├── Button.tsx
│ ├── Input.tsx
│ └── index.ts
├── package.json
└── tsconfig.json
packages/ui/package.json:
{
"name": "@myorg/ui",
"version": "0.0.0",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts",
"./button": "./src/Button.tsx"
},
"scripts": {
"lint": "eslint src/",
"type-check": "tsc --noEmit"
},
"devDependencies": {
"react": "^18.0.0",
"typescript": "^5.0.0"
}
}
packages/ui/src/index.ts:
export { Button } from './Button';
export { Input } from './Input';
export type { ButtonProps, InputProps } from './types';
Using in apps:
{
"dependencies": {
"@myorg/ui": "workspace:*"
}
}
import { Button, Input } from '@myorg/ui';
ESLint config package:
packages/config/eslint-config/
├── index.js
├── package.json
└── README.md
package.json:
{
"name": "@myorg/eslint-config",
"version": "0.0.0",
"main": "index.js",
"dependencies": {
"eslint": "^8.0.0",
"eslint-config-next": "^14.0.0"
}
}
index.js:
module.exports = {
extends: ['next', 'prettier'],
rules: {
'@next/next/no-html-link-for-pages': 'off',
},
};
Using in apps:
{
"devDependencies": {
"@myorg/eslint-config": "workspace:*"
}
}
.eslintrc.js:
module.exports = {
extends: ['@myorg/eslint-config'],
};
Shared tsconfig:
packages/config/tsconfig/
├── base.json
├── nextjs.json
├── react-library.json
└── package.json
base.json:
{
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"incremental": true
}
}
nextjs.json:
{
"extends": "./base.json",
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"jsx": "preserve",
"module": "esnext",
"noEmit": true
}
}
Using in apps:
{
"extends": "@myorg/tsconfig/nextjs.json",
"compilerOptions": {
"outDir": "dist"
},
"include": ["src"],
"exclude": ["node_modules"]
}
Root tsconfig.json:
{
"files": [],
"references": [
{ "path": "./apps/web" },
{ "path": "./apps/admin" },
{ "path": "./packages/ui" },
{ "path": "./packages/utils" }
]
}
Package tsconfig.json:
{
"extends": "@myorg/tsconfig/react-library.json",
"compilerOptions": {
"composite": true,
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"],
"references": [
{ "path": "../utils" }
]
}
Build with references:
tsc --build
turbo run type-check
apps/web/package.json:
{
"name": "web",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"next": "^14.0.0",
"react": "^18.0.0",
"@myorg/ui": "workspace:*",
"@myorg/utils": "workspace:*"
}
}
apps/web/next.config.js:
/** @type {import('next').NextConfig} */
module.exports = {
transpilePackages: ['@myorg/ui', '@myorg/utils'],
reactStrictMode: true,
};
turbo.json:
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
packages/ui/package.json:
{
"name": "@myorg/ui",
"version": "0.0.0",
"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"
}
},
"scripts": {
"build": "tsup src/index.ts --format cjs,esm --dts",
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
"lint": "eslint src/"
},
"devDependencies": {
"tsup": "^8.0.0",
"typescript": "^5.0.0",
"react": "^18.0.0"
},
"peerDependencies": {
"react": "^18.0.0"
}
}
packages/ui/tsup.config.ts:
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
dts: true,
sourcemap: true,
clean: true,
external: ['react'],
});
packages/api-client/package.json:
{
"name": "@myorg/api-client",
"scripts": {
"build": "tsup src/index.ts --format cjs,esm --dts",
"test": "vitest run",
"type-check": "tsc --noEmit"
},
"dependencies": {
"@myorg/types": "workspace:*"
},
"devDependencies": {
"tsup": "^8.0.0",
"vitest": "^1.0.0"
}
}
src/client.ts:
import type { User, Post } from '@myorg/types';
export class APIClient {
constructor(private baseUrl: string) {}
async getUser(id: string): Promise<User> {
const response = await fetch(`${this.baseUrl}/users/${id}`);
return response.json();
}
async getPosts(): Promise<Post[]> {
const response = await fetch(`${this.baseUrl}/posts`);
return response.json();
}
}
Build only what you need:
FROM node:18-alpine AS base
RUN npm install -g turbo pnpm
FROM base AS builder
WORKDIR /app
COPY . .
# Prune workspace to only include 'web' app
RUN turbo prune --scope=web --docker
FROM base AS installer
WORKDIR /app
# Copy pruned workspace
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
RUN pnpm install --frozen-lockfile
COPY --from=builder /app/out/full/ .
RUN pnpm turbo run build --filter=web...
FROM base AS runner
WORKDIR /app
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
EXPOSE 3000
CMD ["node", "apps/web/server.js"]
# Build stage with pruning
FROM node:18-alpine AS builder
RUN npm install -g turbo pnpm
WORKDIR /app
COPY . .
# Prune for specific app (passed as build arg)
ARG APP
RUN turbo prune --scope=${APP} --docker
# Install dependencies
FROM node:18-alpine AS installer
WORKDIR /app
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
RUN pnpm install --frozen-lockfile
# Build
COPY --from=builder /app/out/full/ .
ARG APP
RUN pnpm turbo run build --filter=${APP}...
# Runtime
FROM node:18-alpine AS runner
ARG APP
WORKDIR /app
COPY --from=installer /app .
CMD pnpm --filter=${APP} start
Build:
docker build --build-arg APP=web -t my-web-app .
docker build --build-arg APP=admin -t my-admin-app .
version: '3.8'
services:
web:
build:
context: .
dockerfile: Dockerfile
args:
APP: web
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- API_URL=http://api:3001
admin:
build:
context: .
dockerfile: Dockerfile
args:
APP: admin
ports:
- "3001:3000"
environment:
- NODE_ENV=production
api:
build:
context: .
dockerfile: apps/api/Dockerfile
ports:
- "3001:3001"
environment:
- DATABASE_URL=postgres://db:5432/mydb
db:
image: postgres:15
environment:
POSTGRES_DB: mydb
POSTGRES_PASSWORD: secret
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
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'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm turbo run build
- name: Test
run: pnpm turbo run test
- name: Lint
run: pnpm turbo run lint
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
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'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build and test
run: pnpm turbo run build test lint --cache-dir=.turbo
- name: Upload cache
uses: actions/cache@v3
with:
path: .turbo
key: ${{ runner.os }}-turbo-${{ github.sha }}
restore-keys: |
${{ runner.os }}-turbo-
name: CI
on:
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v2
with:
version: 8
- uses: actions/setup-node@v4
with:
node-version: 18
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build changed packages
run: pnpm turbo run build --filter=[origin/main]
- name: Test changed packages
run: pnpm turbo run test --filter=[origin/main]
Automatic deployment with remote cache:
{
"buildCommand": "turbo run build",
"framework": "nextjs",
"installCommand": "pnpm install",
"outputDirectory": "apps/web/.next"
}
vercel.json:
{
"buildCommand": "turbo run build --filter=web",
"installCommand": "pnpm install --frozen-lockfile",
"framework": null,
"outputDirectory": "apps/web/.next"
}
# Get changed apps since last deploy
CHANGED_APPS=$(turbo run build --filter=[origin/main] --dry=json | jq -r '.packages[]')
# Deploy each changed app
for app in $CHANGED_APPS; do
echo "Deploying $app..."
# Your deployment command
done
GitHub Actions example:
- name: Get changed apps
id: changed
run: |
CHANGED=$(pnpm turbo run build --filter=[origin/main] --dry=json | jq -r '.packages | join(",")')
echo "apps=$CHANGED" >> $GITHUB_OUTPUT
- name: Deploy web
if: contains(steps.changed.outputs.apps, 'web')
run: vercel deploy --prod apps/web
- name: Deploy admin
if: contains(steps.changed.outputs.apps, 'admin')
run: vercel deploy --prod apps/admin
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build and push Docker image
run: |
docker build --build-arg APP=web -t myregistry/web:latest .
docker push myregistry/web:latest
- name: Deploy to Kubernetes
run: |
kubectl set image deployment/web web=myregistry/web:latest
1. Initialize Turborepo:
# In existing repo
npm install turbo --save-dev
npx turbo init
2. Create workspace structure:
mkdir -p apps/web packages/ui
3. Move existing app:
# Move current code to apps/web
git mv src apps/web/src
git mv public apps/web/public
git mv package.json apps/web/package.json
4. Update root package.json:
{
"name": "monorepo",
"private": true,
"workspaces": ["apps/*", "packages/*"],
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
"test": "turbo run test"
},
"devDependencies": {
"turbo": "latest"
}
}
5. Configure turbo.json:
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
6. Extract shared code:
# Create shared package
mkdir -p packages/ui/src
# Move components
mv apps/web/src/components packages/ui/src/
# Update imports in apps/web
7. Install dependencies:
pnpm install
8. Test:
pnpm turbo run build
pnpm turbo run dev
packages/utilspackages/ui| Feature | Turborepo | Nx | |---------|-----------|-----| | Caching | Content-based | Content-based | | Remote cache | Vercel + custom | Nx Cloud + custom | | Complexity | Minimal config | Feature-rich | | Learning curve | Low | Medium-High | | Code generation | No | Yes (generators) | | Best for | Simple monorepos | Enterprise apps |
| Feature | Turborepo | Lerna | |---------|-----------|-------| | Caching | Advanced | Basic | | Speed | Very fast | Slower | | Maintenance | Active | Maintenance mode | | Focus | Build system | Package management | | Best for | Modern monorepos | Legacy projects |
| Feature | Turborepo | Rush | |---------|-----------|------| | Package manager | Any | pnpm-focused | | Complexity | Simple | Complex | | Configuration | Minimal | Extensive | | Best for | Most teams | Large enterprises |
When to choose Turborepo:
When to consider alternatives:
{
"pipeline": {
"build": {
"outputs": [
"dist/**",
".next/**",
"!**/*.map", // Exclude source maps
"!.next/cache/**" // Exclude Next.js cache
]
}
}
}
# Limit concurrency for memory-constrained environments
turbo run build --concurrency=2
# Use all cores
turbo run test --concurrency=100%
# Specific number
turbo run lint --concurrency=8
# Only changed packages
turbo run build --filter=[HEAD^1]
# Package and dependencies
turbo run build --filter=web...
# Exclude packages
turbo run test --filter=!admin
{
"globalEnv": ["NODE_ENV", "CI"],
"pipeline": {
"build": {
"env": [
"NEXT_PUBLIC_API_URL",
"DATABASE_URL"
]
}
}
}
Only list env vars that affect output - unnecessary env vars invalidate cache.
{
"pipeline": {
"build": {
"dependsOn": ["^build"], // Necessary
"inputs": [
"src/**/*.{ts,tsx}", // Source only
"!**/__tests__/**" // Exclude tests
]
}
}
}
Check cache hits:
turbo run build --dry=json | jq '.tasks[] | {task: .taskId, cache: .cache}'
Common causes:
envDebug caching:
# Force execution
turbo run build --force
# Check what invalidated cache
turbo run build --output-logs=hash-only
Dependency issues:
# Clear and reinstall
rm -rf node_modules .turbo
pnpm install --frozen-lockfile
TypeScript errors:
# Check project references
tsc --build --force
# Type check all packages
turbo run type-check
Profile builds:
turbo run build --profile
Check task graph:
turbo run build --graph
Generates graph.png showing task dependencies.
Optimize concurrency:
# Too many parallel tasks can exhaust memory
turbo run build --concurrency=4
Check authentication:
npx turbo login
npx turbo link
Verify environment variables:
echo $TURBO_TOKEN
echo $TURBO_TEAM
Test connection:
turbo run build --remote-only
"@myorg/ui": "workspace:*"^build for topological dependenciesoutputs for all build artifactsenv variablescache: false for dev servers and watch modespersistent: true for long-running processes.turbo/ in .gitignore--force to bypass cache when neededworkspace:*0.0.0.turbo/ directory--filter=[origin/main] for changed packagesTURBO_TOKEN and TURBO_TEAM for remote cache--frozen-lockfile for reproducible buildscomposite: true for referenced projectspaths for clean importstsup or tsup for library buildsturbo run test--filter to test changed packages--profile flagoutputs configuration{
"pipeline": {
"build": {
"outputs": [
"dist/**",
".next/**",
"{projectRoot}/build/**" // Project-specific
]
}
}
}
{
"pipeline": {
"build:production": {
"dependsOn": ["^build"],
"env": ["NODE_ENV", "API_URL"],
"outputs": ["dist/**"]
},
"build:staging": {
"dependsOn": ["^build"],
"env": ["NODE_ENV", "STAGING_API_URL"],
"outputs": ["dist/**"]
}
}
}
# Build web and its dependencies
turbo run build --filter=web...
# Build everything that depends on ui
turbo run build --filter=...ui
# Build changed packages and dependents
turbo run build --filter=[main]...
# Build specific scope
turbo run build --filter=@myorg/*
# Exclude packages
turbo run test --filter=!admin --filter=!legacy
{
"name": "@myorg/ui",
"exports": {
".": "./src/index.ts",
"./button": "./src/button.tsx",
"./input": "./src/input.tsx",
"./hooks": "./src/hooks/index.ts"
}
}
import { Button } from '@myorg/ui/button';
import { useDebounce } from '@myorg/ui/hooks';
packages/scripts/
├── build.js
├── test.js
└── package.json
build.js:
#!/usr/bin/env node
const { build } = require('tsup');
build({
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
dts: true,
sourcemap: true,
clean: true,
}).catch((error) => {
console.error(error);
process.exit(1);
});
Using in packages:
{
"scripts": {
"build": "node ../../packages/scripts/build.js"
}
}
This skill provides comprehensive Turborepo knowledge for building high-performance monorepos with intelligent caching and task orchestration.
development
Optimize web performance using Core Web Vitals, modern patterns (View Transitions, Speculation Rules), and framework-specific techniques
development
Best practices for documenting APIs and code interfaces, eliminating redundant documentation guidance per agent.
development
Comprehensive API design patterns covering REST, GraphQL, gRPC, versioning, authentication, and modern API best practices
development
Visual verification workflow for UI changes to accelerate code review and catch ...