
Turborepo Monorepo
- 22 installs
- 318 repo stars
- Updated June 22, 2026
- giuseppe-trisciuoglio/developer-kit-claude-code
This is a copy of turborepo-monorepo by giuseppe-trisciuoglio - installs and ranking accrue to the original listing.
Helps with ai & agent building tasks.
About
turborepo-monorepo is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- turborepo-monorepo
- AI & Agent Building
- AI-coding skill
Turborepo Monorepo by the numbers
- 22 all-time installs (skills.sh)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit-claude-code --skill turborepo-monorepoAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 22 |
|---|---|
| repo stars | ★ 318 |
| Last updated | June 22, 2026 |
| Repository | giuseppe-trisciuoglio/developer-kit-claude-code ↗ |
What it does
Helps with ai & agent building tasks.
Files
Turborepo Monorepo
Overview
Provides guidance for Turborepo monorepo management: workspace creation, turbo.json task configuration, Next.js/NestJS integration, testing pipelines (Vitest/Jest), CI/CD setup, and build performance optimization.
When to Use
- Create or initialize Turborepo workspaces
- Configure
turbo.jsontasks with dependencies and outputs - Set up Next.js/NestJS apps in monorepo structure
- Configure Vitest/Jest test pipelines
- Build CI/CD workflows (GitHub Actions, GitLab CI)
- Implement remote caching with Vercel Remote Cache
- Optimize build times and cache hit ratios
- Debug task dependency or cache issues
- Migrate from other monorepo tools to Turborepo
Instructions
Workspace Creation
1. Create a new workspace:
pnpm create turbo@latest my-workspace
cd my-workspace2. Initialize in existing project:
pnpm add -D -w turbo3. Create turbo.json in root (minimal config):
{
"$schema": "https://turborepo.dev/schema.json",
"pipeline": {
"build": { "dependsOn": ["^build"], "outputs": ["dist/**", ".next/**"] },
"lint": { "outputs": [] },
"test": { "dependsOn": ["build"], "outputs": ["coverage/**"] }
}
}4. Add scripts to root package.json:
{ "scripts": { "build": "turbo run build", "dev": "turbo run dev", "lint": "turbo run lint", "test": "turbo run test", "clean": "turbo run clean" } }5. Validate task graph before CI:
turbo run build --dry-run --filter=... # Verify task execution orderTask Configuration
1. Configure tasks in turbo.json:
{ "pipeline": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] }, "test": { "dependsOn": ["build"], "outputs": ["coverage/**"] }, "lint": { "outputs": [] } } }2. Run tasks:
turbo run build # All packages
turbo run lint test build # Multiple tasks
turbo run build --filter=web # Specific package3. Parallel type checking (use transit nodes to avoid cache issues):
{ "pipeline": { "transit": { "dependsOn": ["^transit"] }, "typecheck": { "dependsOn": ["transit"] } } }4. Validate before committing:
turbo run build --dry-run # Check task order and affected packagesFramework Integration
Next.js: outputs ".next/**" and env ["NEXT_PUBLIC_*"] - See references/nextjs-config.md
NestJS: outputs "dist/**", dev tasks with cache: false, persistent: true - See references/nestjs-config.md
Testing Setup
1. Vitest configuration:
{
"pipeline": {
"test": {
"outputs": [],
"inputs": ["$TURBO_DEFAULT$", "vitest.config.ts"]
},
"test:watch": {
"cache": false,
"persistent": true
}
}
}2. Run affected tests:
turbo run test --filter=[HEAD^]See references/testing-config.md for complete testing setup.
Package Configurations
1. Create package-specific turbo.json:
{
"extends": ["//"],
"tasks": {
"build": {
"outputs": ["$TURBO_EXTENDS$", ".next/**"]
}
}
}See references/package-configs.md for detailed package configuration patterns.
CI/CD Setup
1. GitHub Actions with validation checkpoints:
- name: Install dependencies
run: pnpm install
- name: Validate affected packages (dry-run)
run: pnpm turbo run build --filter=[HEAD^] --dry-run
# VALIDATE: Review output to confirm only expected packages will build
- name: Run tests
run: pnpm run test --filter=[HEAD^]
- name: Build affected packages
run: pnpm run build --filter=[HEAD^]
- name: Verify cache hits
run: pnpm turbo run build --filter=[HEAD^] --dry-run | grep "Cache"
# VALIDATE: Confirm cache hits for unchanged packages2. Remote cache setup:
# Login to Vercel
npx turbo login
# Link repository
npx turbo linkSee references/ci-cd.md for complete CI/CD setup examples.
Task Properties Reference
| Property | Description | Example |
|---|---|---|
dependsOn | Tasks that must complete first | ["^build"] - dependencies first |
outputs | Files/folders to cache | ["dist/**"] |
inputs | Files for cache hash | ["src/**/*.ts"] |
env | Environment variables affecting hash | ["DATABASE_URL"] |
cache | Enable/disable caching | true or false |
persistent | Long-running task | true for dev servers |
outputLogs | Log verbosity | "full", "new-only", "errors-only" |
Dependency Patterns
^task- Run task in dependencies first (topological order)task- Run task in same package firstpackage#task- Run specific package's task
Filter Syntax
| Filter | Description |
|---|---|
web | Only web package |
web... | web + all dependencies |
...web | web + all dependents |
...web... | web + deps + dependents |
[HEAD^] | Packages changed since last commit |
./apps/* | All packages in apps/ |
Best Practices
Performance Optimization
1. Use specific outputs - Only cache what's needed 2. Fine-tune inputs - Exclude files that don't affect output 3. Transit nodes - Enable parallel type checking 4. Remote cache - Share cache across team/CI 5. Package configurations - Customize per-package behavior
Caching Strategy
{
"pipeline": {
"build": {
"outputs": ["dist/**"],
"inputs": ["$TURBO_DEFAULT$", "!README.md", "!**/*.md"]
}
}
}Task Organization
- Independent tasks - No
dependsOn: lint, format, spellcheck - Build tasks -
dependsOn: ["^build"]: build, compile - Test tasks -
dependsOn: ["build"]: test, e2e - Dev tasks -
cache: false, persistent: true: dev, watch
Common Issues
Tasks not running in order
Problem: Tasks execute in wrong order
Solution: Check dependsOn configuration
{
"build": {
"dependsOn": ["^build"]
}
}Cache misses on unchanged files
Problem: Cache invalidating unexpectedly
Solution: Review globalDependencies and inputs
{
"globalDependencies": ["tsconfig.json"],
"pipeline": {
"build": {
"inputs": ["$TURBO_DEFAULT$", "!*.md"]
}
}
}Type errors after cache hit
Problem: TypeScript errors not caught due to cache
Solution: Use transit nodes for type checking
{
"transit": { "dependsOn": ["^transit"] },
"typecheck": { "dependsOn": ["transit"] }
}Examples
Example 1: Create New Workspace
Input: "Create a Turborepo with Next.js and NestJS"
pnpm create turbo@latest my-workspace
cd my-workspace
# Add Next.js app
pnpm add next react react-dom -F apps/web
# Add NestJS API
pnpm add @nestjs/core @nestjs/common -F apps/apiExample 2: Configure Testing Pipeline
Input: "Set up Vitest for all packages"
{
"pipeline": {
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"],
"inputs": ["$TURBO_DEFAULT$", "vitest.config.ts"]
},
"test:watch": {
"cache": false,
"persistent": true
}
}
}Example 3: Run Affected Tests in CI
Input: "Only test changed packages in CI"
pnpm run test --filter=[HEAD^]Example 4: Debug Cache Issues
Input: "Why is my cache missing?"
# Dry run to see what would be executed
turbo run build --dry-run --filter=web
# Show hash inputs
turbo run build --force --filter=webConstraints and Warnings
- Node.js 18+ is required for Turborepo
- Package manager field required in root
package.json - Outputs must be specified for caching to work
- Persistent tasks cannot have dependents
- Windows: WSL or Git Bash recommended
- Remote cache requires Vercel account or self-hosted solution
- Large monorepos may need increased
concurrencysettings
Reference Files
For detailed guidance on specific topics, consult:
| Topic | Reference File |
|---|---|
| turbo.json template | references/turbo.json |
| Next.js integration | references/nextjs-config.md |
| NestJS integration | references/nestjs-config.md |
| Vitest/Jest/Playwright | references/testing-config.md |
| GitHub/CircleCI/GitLab CI | references/ci-cd.md |
| Package configurations | references/package-configs.md |
CI/CD con Turborepo
GitHub Actions
Basic workflow
name: CI
on:
push:
branches: [main]
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-and-test:
name: Build and test
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Run lint
run: pnpm run lint --filter=[HEAD^]
- name: Run type check
run: pnpm run typecheck --filter=[HEAD^]
- name: Run tests
run: pnpm run test --filter=[HEAD^]
- name: Build
run: pnpm run build --filter=[HEAD^]Con Turborepo Remote Cache
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
build-and-test:
runs-on: ubuntu-latest
# Output from turbo's `pack` command
outputs:
artifact-hash: ${{ steps.pack.outputs.hash }}
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
steps:
- uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Build & test
run: pnpm run build test
- name: Pack cache
id: pack
run: |
tar -czf cache.tar.gz .turbo/cache
echo "hash=$(sha256sum cache.tar.gz | cut -c1-10)" >> $GITHUB_OUTPUT
- name: Upload cache
uses: actions/cache/save@v4
with:
path: .turbo/cache
key: turbo-${{ runner.os }}-${{ steps.pack.outputs.hash }}Workflow con affected packages
name: Affected CI
on:
pull_request:
jobs:
affected:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Lint affected
run: pnpm run lint --filter=[HEAD^]
- name: Test affected
run: pnpm run test --filter=[HEAD^]
- name: Build affected
run: pnpm run build --filter=[HEAD^]CircleCI
version: 2.1
orbs:
node: circleci/node@5.1
executors:
node-executor:
docker:
- image: cimg/node:20.11
resource_class: medium
jobs:
build-and-test:
executor: node-executor
steps:
- checkout
- node/install-packages:
pkg-manager: pnpm
cache-version: v1
- run:
name: Lint affected
command: pnpm run lint --filter=[HEAD^]
- run:
name: Test affected
command: pnpm run test --filter=[HEAD^]
- run:
name: Build affected
command: pnpm run build --filter=[HEAD^]
workflows:
build-test:
jobs:
- build-and-test:
context:
- turbo-secretsGitLab CI
stages:
- validate
- test
- build
variables:
PNPM_VERSION: "9"
NODE_VERSION: "20"
TURBO_TOKEN: ${TURBO_TOKEN}
TURBO_TEAM: ${TURBO_TEAM}
.cache_config:
cache:
key:
files:
- pnpm-lock.yaml
paths:
- .pnpm-store
- node_modules
lint:
stage: validate
image: node:${NODE_VERSION}
extends: .cache_config
script:
- corepack enable
- corepack prepare pnpm@${PNPM_VERSION} --activate
- pnpm install --frozen-lockfile
- pnpm run lint --filter=[HEAD^]
test:
stage: test
image: node:${NODE_VERSION}
extends: .cache_config
script:
- corepack enable
- corepack prepare pnpm@${PNPM_VERSION} --activate
- pnpm install --frozen-lockfile
- pnpm run test --filter=[HEAD^]
build:
stage: build
image: node:${NODE_VERSION}
extends: .cache_config
script:
- corepack enable
- corepack prepare pnpm@${PNPM_VERSION} --activate
- pnpm install --frozen-lockfile
- pnpm run build --filter=[HEAD^]Deployment Pipeline
Deploy changed apps
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup pnpm and Node
uses: pnpm/action-setup@v4
with:
version: 9
- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm run build --filter=[HEAD^]
- name: Deploy Next.js app
if: contains(steps.turbo.outputs.apps, 'web')
run: pnpm --filter web deploy
- name: Deploy NestJS API
if: contains(steps.turbo.outputs.apps, 'api')
run: pnpm --filter api deployBest Practices CI/CD
1. Usa sempre `--filter=[HEAD^]` nelle PR per testare solo i pacchetti modificati
2. Cache delle dipendenze per velocizzare il setup
3. Paralellizza i task dove possibile
4. Usa turbo-ignore per skipare le build inutili:
pnpm add -D -w turbo-ignore{
"scripts": {
"check": "turbo-ignore"
}
}5. Fallback cache locale se remote cache non è disponibile
6. Timeout appropriati per evitare job bloccati
7. Artifact caching tra jobs:
- name: Save build artifacts
uses: actions/upload-artifact@v4
with:
name: build
path: apps/*/dist
- name: Load build artifacts
uses: actions/download-artifact@v4
with:
name: buildTurbo in Docker
FROM node:20-alpine AS build
WORKDIR /app
# Setup pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
# Copy package files
COPY package.json pnpm-lock.yaml ./
COPY pnpm-workspace.yaml ./
# Install dependencies
RUN pnpm install --frozen-lockfile
# Copy source
COPY . .
# Build with turbo
RUN pnpm run build
# Production stage
FROM node:20-alpine AS prod
WORKDIR /app
COPY --from=build /app/apps/api/dist ./dist
COPY --from=build /app/apps/api/package.json ./
CMD ["node", "dist/main.js"]NestJS in Turborepo
Package Structure
apps/
api/
package.json
nest-cli.json
tsconfig.json
tsconfig.build.json
src/
main.ts
libs/
shared/
package.json
tsconfig.json
src/
index.tsapi/package.json
{
"name": "api",
"version": "0.0.0",
"private": true,
"scripts": {
"build": "nest build",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@nestjs/common": "^10.4.7",
"@nestjs/core": "^10.4.7",
"@nestjs/platform-express": "^10.4.7",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
"shared": "*"
},
"devDependencies": {
"@nestjs/cli": "^10.4.7",
"@nestjs/schematics": "^10.2.3",
"@nestjs/testing": "^10.4.7",
"@types/express": "^5.0.0",
"@types/jest": "^29.5.14",
"@types/node": "^22.10.5",
"@typescript-eslint/eslint-plugin": "^8.19.1",
"@typescript-eslint/parser": "^8.19.1",
"eslint": "^9",
"jest": "^29.7.0",
"ts-jest": "^29.2.5",
"ts-loader": "^9.5.2",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.7.2"
}
}turbo.json for NestJS
{
"$schema": "https://turborepo.dev/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"start:dev": {
"cache": false,
"persistent": true
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"],
"inputs": ["$TURBO_DEFAULT$", "jest.config.js"]
},
"lint": {
"outputs": []
},
"typecheck": {
"dependsOn": ["^build"],
"outputs": []
}
}
}nest-cli.json
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true,
"webpack": false
}
}tsconfig.build.json
{
"extends": "./tsconfig.json",
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
}Workspace tsconfig paths
In root tsconfig.json:
{
"compilerOptions": {
"paths": {
"api/*": ["./apps/api/src/*"],
"shared/*": ["./libs/shared/src/*"]
}
}
}Environment Variables
Use .env files with Turborepo global dependencies:
{
"globalDependencies": ["**/.env.*"],
"globalEnv": ["DATABASE_URL", "JWT_SECRET", "NODE_ENV"]
}Monorepo package exports
For libs/shared:
{
"name": "shared",
"version": "0.0.0",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
}
}Next.js in Turborepo
Package Structure
apps/
web/
package.json
next.config.js
tsconfig.json
next-env.d.ts
libs/
ui/
package.json
tsconfig.json
index.tsweb/package.json
{
"name": "web",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"next": "^15.1.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"ui": "*"
},
"devDependencies": {
"@next/eslint-plugin-next": "^15.1.0",
"typescript": "^5.7.2",
"eslint": "^9",
"eslint-config-next": "^15.1.0"
}
}turbo.json for Next.js
{
"$schema": "https://turborepo.dev/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**"],
"env": ["NEXT_PUBLIC_*"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"outputs": []
}
}
}With app router
{
"pipeline": {
"build": {
"outputs": [
".next/**",
"!.next/cache/**",
".next/server/**"
]
}
}
}Incremental Static Regeneration (ISR)
For ISR with Next.js, exclude fetch cache from outputs:
{
"pipeline": {
"build": {
"outputs": [
".next/**",
"!.next/cache/**",
"!.next/server/pages/**/_buildManifest.js"
]
}
}
}Image optimization
Next.js image optimization cache should be excluded:
{
"pipeline": {
"build": {
"outputs": [
".next/**",
"!.next/cache/**",
"!.next/static/media/**"
]
}
}
}Package Configurations in Turborepo
Le Package Configurations permettono di definire comportamenti specifici per singoli package senza influenzare l'intero repository.
Struttura
apps/
web/
package.json
turbo.json # Package configuration
libs/
ui/
package.json
turbo.json # Package configuration
turbo.json # Root configurationEstendere dalla configurazione root
Ogni turbo.json in un package deve estendere dalla root:
{
"$schema": "https://turborepo.dev/schema.json",
"extends": ["//"],
"tasks": {
"build": {
"outputs": ["$TURBO_EXTENDS$", ".next/**"]
}
}
}Esempi di Package Configurations
Next.js con output specifici
apps/web/turbo.json:
{
"extends": ["//"],
"tasks": {
"build": {
"outputs": ["$TURBO_EXTENDS$", ".next/**", "!.next/cache/**"]
},
"dev": {
"dependsOn": ["^dev"]
}
}
}NestJS API
apps/api/turbo.json:
{
"extends": ["//"],
"tasks": {
"build": {
"outputs": ["$TURBO_EXTENDS$", "dist/**"]
},
"start:dev": {
"cache": false,
"persistent": true
}
}
}Libreria UI
libs/ui/turbo.json:
{
"extends": ["//"],
"tasks": {
"build": {
"outputs": ["$TURBO_EXTENDS$", "dist/**"]
},
"lint": {
"outputs": [],
"inputs": ["$TURBO_DEFAULT$", "src/**/*.tsx", "src/**/*.ts"]
},
"storybook": {
"cache": false,
"persistent": true
}
}
}Escludere task dall'ereditarietà
Usa extends: false per escludere un task:
{
"extends": ["//"],
"tasks": {
"lint": {
"extends": false
}
}
}O definisci un nuovo task non ereditato:
{
"extends": ["//"],
"tasks": {
"lint": {
"extends": false,
"outputs": [],
"inputs": ["src/**/*.ts"]
}
}
}Condividere configurazioni
Crea un package di configurazione condivisa:
packages/
turbo-config/
package.json
turbo.json
apps/
web/
turbo.jsonpackages/turbo-config/turbo.json:
{
"tasks": {
"build": {
"outputs": ["dist/**"]
},
"lint": {
"outputs": []
}
}
}apps/web/turbo.json:
{
"extends": ["//", "turbo-config"],
"tasks": {
"build": {
"outputs": ["$TURBO_EXTENDS$", ".next/**"]
}
}
}Variabili di Environment per Package
Definisci variabili specifiche per package:
{
"extends": ["//"],
"tasks": {
"build": {
"env": ["$TURBO_EXTENDS$", "NEXT_PUBLIC_STRIPE_KEY"]
}
}
}Task specifici per package
Definisci task che esistono solo in certi package:
{
"extends": ["//"],
"tasks": {
"storybook": {
"cache": false,
"persistent": true,
"description": "Run Storybook for UI components"
},
"chromatic": {
"dependsOn": ["build"],
"outputs": [],
"description": "Publish to Chromatic"
}
}
}Dipendenze specifiche per package
Definisci dipendenze tra task di package specifici:
{
"extends": ["//"],
"tasks": {
"build": {
"dependsOn": ["utils#build", "shared#build"]
}
}
}Sovrascrivere outputs
Sostituisci completamente gli outputs ereditati:
{
"extends": ["//"],
"tasks": {
"build": {
"outputs": [".next/**"] // Sostituisce, non aggiunge
}
}
}Oppure aggiungi agli outputs esistenti:
{
"extends": ["//"],
"tasks": {
"build": {
"outputs": ["$TURBO_EXTENDS$", ".next/**"]
}
}
}Best Practices
1. Estendi sempre dalla root con ["//"] 2. Usa `$TURBO_EXTENDS$` per aggiungere ai valori ereditati 3. Mantieni le configurazioni semplici - metti solo le differenze 4. Documenta i task custom con description 5. Evita duplicazioni - usa package config condivisi per pattern comuni 6. Testa localmente prima di committare configurazioni complesse
Testing in Turborepo
Vitest Configuration
Installation
pnpm add -D -w vitest @vitest/ui
pnpm add -D vitestvitest.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
environment: 'node',
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
exclude: [
'node_modules/',
'dist/',
'**/*.config.ts',
'**/*.d.ts'
]
}
}
})package.json scripts
{
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"test:ui": "vitest --ui",
"test:coverage": "vitest run --coverage"
}
}turbo.json for Vitest
{
"pipeline": {
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"],
"inputs": ["$TURBO_DEFAULT$", "vitest.config.ts"],
"outputs": []
},
"test:watch": {
"cache": false,
"persistent": true
}
}
}Jest Configuration
Installation
pnpm add -D -w jest @types/jest
pnpm add -D jest ts-jest @types/jestjest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/src'],
testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
transform: {
'^.+\\.ts$': 'ts-jest'
},
collectCoverageFrom: [
'src/**/*.ts',
'!src/**/*.d.ts',
'!src/**/*.interface.ts',
'!src/main.ts'
],
coverageDirectory: 'coverage',
coverageReporters: ['text', 'lcov', 'html']
}turbo.json for Jest
{
"pipeline": {
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"],
"inputs": ["$TURBO_DEFAULT$", "jest.config.js"]
},
"test:watch": {
"cache": false,
"persistent": true
}
}
}Playwright Configuration
Installation
pnpm add -D -w @playwright/testplaywright.config.ts
import { defineConfig, devices } from '@playwright/test'
export default defineConfig({
testDir: './e2e',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry'
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] }
}
],
webServer: {
command: 'pnpm run dev',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI
}
})turbo.json for Playwright
{
"pipeline": {
"test:e2e": {
"dependsOn": ["build"],
"outputs": ["playwright-report/**"],
"inputs": ["$TURBO_DEFAULT$", "playwright.config.ts"]
}
}
}Testing Strategies
Unit Tests (fast, isolated)
{
"pipeline": {
"test:unit": {
"outputs": [],
"inputs": ["src/**/*.ts", "test/unit/**/*.ts"]
}
}
}Integration Tests (slower, dependencies)
{
"pipeline": {
"test:integration": {
"dependsOn": ["build"],
"outputs": ["coverage/**"]
}
}
}E2E Tests (slowest, full system)
{
"pipeline": {
"test:e2e": {
"dependsOn": ["^build"],
"outputs": ["playwright-report/**"]
}
}
}Running Tests by Type
# Run all tests
turbo run test
# Run only unit tests
turbo run test:unit
# Run tests for affected packages
turbo run test --filter=[HEAD^]
# Run tests with coverage
turbo run test:coverageCI/CD Testing
# .github/workflows/ci.yml
- name: Run tests
run: pnpm run test --filter=[HEAD^]
- name: Run E2E tests
run: pnpm run test:e2e --filter=[HEAD^]Test Monorepo Patterns
Testing library changes
When a library changes, only test packages that depend on it:
turbo run test --filter=[HEAD^]Testing only changed packages
turbo run test --filter=...[HEAD]Parallel test execution
Turborepo automatically runs tests in parallel based on dependencies:
{
"pipeline": {
"test": {
"dependsOn": ["build"]
}
}
}{
"$schema": "https://turborepo.dev/schema.json",
"globalDependencies": ["**/.env.*local", ".env"],
"globalEnv": ["NODE_ENV", "CI"],
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**", "dist/**", "build/**"],
"env": ["NEXT_PUBLIC_*", "VITE_*", "NUXT_PUBLIC_*"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"outputs": [],
"inputs": ["$TURBO_DEFAULT$", "!**/*.md", "!**/*.spec.ts", "!**/*.test.ts"]
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"],
"inputs": ["$TURBO_DEFAULT$", "jest.config.js", "vitest.config.ts"]
},
"typecheck": {
"dependsOn": ["^build"],
"outputs": [],
"inputs": ["$TURBO_DEFAULT$", "tsconfig.json"]
},
"clean": {
"cache": false
}
}
}