Monorepo Setup with Turborepo
Monorepo Setup with Turborepo
A monorepo lets you manage multiple packages, apps, and shared libraries in a single repository. Turborepo makes this practical by caching builds, running tasks in parallel, and managing dependencies between packages.
Why Monorepo?
Initial Setup
npx create-turbo@latest my-monorepo
cd my-monorepo
This scaffolds a structure like:
my-monorepo/
apps/
web/ # Next.js app
docs/ # Documentation site
packages/
ui/ # Shared component library
config/ # Shared ESLint/TS configs
utils/ # Shared utilities
turbo.json
package.json
Workspace Configuration
Configure npm/pnpm/yarn workspaces in your root package.json:
{
"name": "my-monorepo",
"private": true,
"workspaces": ["apps/*", "packages/*"],
"devDependencies": {
"turbo": "^2.0.0"
}
}
Turborepo Configuration
Define your task pipeline in turbo.json:
{
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/", "dist/"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"dependsOn": ["^build"]
},
"test": {
"dependsOn": ["build"]
}
}
}
The ^build syntax means "build my dependencies first." Turborepo resolves the dependency graph and runs tasks in the correct order.
Creating a Shared Package
// packages/ui/package.json
{
"name": "@repo/ui",
"version": "0.0.0",
"main": "./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"
}
}
Use it from an app:
// apps/web/package.json
{
"dependencies": {
"@repo/ui": "workspace:*"
}
}
import { Button } from "@repo/ui";
Caching
Turborepo caches task outputs locally. If nothing changed, the task completes in milliseconds:
$ turbo build
First run: 45s
$ turbo build
Second run: 0.1s (cached)
Enable remote caching to share across CI and team members:
npx turbo login
npx turbo link
Deployment
Deploy individual apps from the monorepo. Most platforms support monorepo deployments:
Vercel — set root directory to apps/web
Docker — use a targeted build
docker build -f apps/web/Dockerfile .
Filtered Builds
Only build what changed:
turbo build --filter=web
turbo build --filter=...web # web and its dependencies
turbo test --filter={./packages/*} # all packages
Best Practices
Conclusion
Turborepo makes monorepos practical by handling the hard parts — task orchestration, caching, and dependency resolution. Start with a web app and a shared UI package, then extract more packages as your codebase grows.