Back to skills
SKILL.md
Turborepo Monorepo
BSecurityExpert in Turborepo, monorepo architecture, workspace management, and build optimization. Use when designing system architecture or making technical decisions about turborepo monorepo.
- 9 stars
- 0 votes
- 0 copies
- 1 view
- Added September 8, 2026
Works with
Security analysis
85/100- Performs destructive filesystem operations
- Installs packages at runtime which could introduce malicious dependencies
- Installs packages at runtime which could introduce malicious dependencies
npx -y skills add anubhavg-icpl/vibe --skill turborepo-monorepo --agent claude-codeAre you the author of Turborepo Monorepo?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-turborepo-monorepo)---
name: turborepo-monorepo
description: Expert in Turborepo, monorepo architecture, workspace management, and build optimization. Use when designing system architecture or making technical decisions about turborepo monorepo.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: architecture
---
# Turborepo & Monorepo Expert Mode
You are an expert in Turborepo and monorepo architecture. You design and implement scalable monorepo structures with efficient caching, task orchestration, and workspace management.
## Core Competencies
### Turborepo Capabilities
- Incremental builds
- Remote caching
- Task pipelines
- Workspace management
- Parallel execution
## Monorepo Architecture
```text
┌─────────────────────────────────────────────────────────────────┐
│ Monorepo Structure │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Root │ │
│ │ package.json, turbo.json, tsconfig.json │ │
│ └────────────────────────┬────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────┼────────────────────────────────┐ │
│ │ apps/ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ web │ │ api │ │ admin │ │ │
│ │ │ (Next) │ │ (Hono) │ │ (Next) │ │ │
│ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │
│ └───────┼─────────────┼─────────────┼─────────────────────┘ │
│ │ │ │ │
│ ┌───────┼─────────────┼─────────────┼─────────────────────┐ │
│ │ └─────────────┼─────────────┘ │ │
│ │ packages/ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ ui │ │ shared │ │ config │ │ │
│ │ │(shadcn) │ │ (utils) │ │(eslint) │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
## Project Setup
```bash
# Create new Turborepo
npx create-turbo@latest my-monorepo
# Or add to existing project
npm install turbo --save-dev
```
### Root Structure
```text
my-monorepo/
├── apps/
│ ├── web/ # Next.js web app
│ ├── api/ # Backend API
│ ├── admin/ # Admin dashboard
│ └── docs/ # Documentation site
├── packages/
│ ├── ui/ # Shared UI components
│ ├── shared/ # Shared utilities
│ ├── database/ # Database client & schemas
│ ├── config-eslint/ # ESLint configuration
│ ├── config-typescript/ # TypeScript configuration
│ └── config-tailwind/ # Tailwind configuration
├── turbo.json
├── package.json
├── pnpm-workspace.yaml
└── tsconfig.json
```
## Configuration Files
### turbo.json
```json
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["**/.env.*local"],
"globalEnv": ["NODE_ENV", "CI"],
"ui": "tui",
"tasks": {
"build": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"outputs": [".next/**", "!.next/cache/**", "dist/**"],
"env": ["NEXT_PUBLIC_*"]
},
"lint": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", ".eslintrc*"]
},
"test": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", "**/*.test.ts", "**/*.test.tsx"],
"outputs": ["coverage/**"],
"env": ["CI"]
},
"test:watch": {
"cache": false,
"persistent": true
},
"dev": {
"cache": false,
"persistent": true,
"dependsOn": ["^build"]
},
"typecheck": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", "tsconfig.json"]
},
"clean": {
"cache": false
},
"db:generate": {
"cache": false
},
"db:push": {
"cache": false
}
}
}
```
### Root package.json
```json
{
"name": "my-monorepo",
"private": true,
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
"lint": "turbo run lint",
"test": "turbo run test",
"typecheck": "turbo run typecheck",
"clean": "turbo run clean && rm -rf node_modules",
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
"db:generate": "turbo run db:generate",
"db:push": "turbo run db:push"
},
"devDependencies": {
"prettier": "^3.2.0",
"turbo": "^2.0.0",
"typescript": "^5.3.0"
},
"packageManager": "pnpm@8.15.0",
"engines": {
"node": ">=20"
}
}
```
### pnpm-workspace.yaml
```yaml
packages:
- "apps/*"
- "packages/*"
```
## Shared Packages
### packages/ui/package.json
```json
{
"name": "@repo/ui",
"version": "0.0.0",
"private": true,
"sideEffects": false,
"exports": {
"./button": "./src/button.tsx",
"./card": "./src/card.tsx",
"./input": "./src/input.tsx",
"./styles.css": "./dist/styles.css",
".": "./src/index.ts"
},
"scripts": {
"build": "tailwindcss -i ./src/styles.css -o ./dist/styles.css",
"dev": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --watch",
"lint": "eslint src/",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@radix-ui/react-slot": "^1.0.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"tailwind-merge": "^2.2.0"
},
"devDependencies": {
"@repo/config-eslint": "workspace:*",
"@repo/config-tailwind": "workspace:*",
"@repo/config-typescript": "workspace:*",
"@types/react": "^18.2.0",
"react": "^18.2.0",
"tailwindcss": "^3.4.0",
"typescript": "^5.3.0"
},
"peerDependencies": {
"react": "^18.2.0"
}
}
```
### packages/ui/src/button.tsx
```tsx
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "./utils";
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input bg-background hover:bg-accent",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
},
);
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
asChild?: boolean;
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button";
return <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />;
},
);
Button.displayName = "Button";
export { Button, buttonVariants };
```
### packages/shared/package.json
```json
{
"name": "@repo/shared",
"version": "0.0.0",
"private": true,
"exports": {
".": "./src/index.ts",
"./utils": "./src/utils.ts",
"./types": "./src/types.ts",
"./validators": "./src/validators.ts"
},
"scripts": {
"typecheck": "tsc --noEmit",
"lint": "eslint src/",
"test": "vitest run"
},
"dependencies": {
"zod": "^3.22.0"
},
"devDependencies": {
"@repo/config-typescript": "workspace:*",
"typescript": "^5.3.0",
"vitest": "^1.2.0"
}
}
```
### packages/shared/src/validators.ts
```typescript
import { z } from "zod";
// Shared validation schemas
export const userSchema = z.object({
id: z.string().uuid(),
email: z.string().email(),
name: z.string().min(2).max(100),
role: z.enum(["admin", "user", "guest"]),
createdAt: z.date(),
updatedAt: z.date(),
});
export const createUserSchema = userSchema.omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const updateUserSchema = createUserSchema.partial();
export const paginationSchema = z.object({
page: z.number().int().positive().default(1),
limit: z.number().int().min(1).max(100).default(20),
sortBy: z.string().optional(),
order: z.enum(["asc", "desc"]).default("desc"),
});
// Type exports
export type User = z.infer<typeof userSchema>;
export type CreateUser = z.infer<typeof createUserSchema>;
export type UpdateUser = z.infer<typeof updateUserSchema>;
export type Pagination = z.infer<typeof paginationSchema>;
```
### packages/database/package.json
```json
{
"name": "@repo/database",
"version": "0.0.0",
"private": true,
"exports": {
".": "./src/index.ts",
"./client": "./src/client.ts",
"./schema": "./src/schema.ts"
},
"scripts": {
"db:generate": "drizzle-kit generate",
"db:push": "drizzle-kit push",
"db:studio": "drizzle-kit studio",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"drizzle-orm": "^0.29.0",
"postgres": "^3.4.0"
},
"devDependencies": {
"@repo/config-typescript": "workspace:*",
"drizzle-kit": "^0.20.0",
"typescript": "^5.3.0"
}
}
```
## TypeScript Configuration
### packages/config-typescript/base.json
```json
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Default",
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"esModuleInterop": true,
"incremental": true,
"isolatedModules": true,
"lib": ["ES2022"],
"module": "NodeNext",
"moduleDetection": "force",
"moduleResolution": "NodeNext",
"noUncheckedIndexedAccess": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
"target": "ES2022"
},
"exclude": ["node_modules"]
}
```
### packages/config-typescript/nextjs.json
```json
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Next.js",
"extends": "./base.json",
"compilerOptions": {
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "Bundler",
"jsx": "preserve",
"plugins": [{ "name": "next" }],
"noEmit": true
}
}
```
## ESLint Configuration
### packages/config-eslint/package.json
```json
{
"name": "@repo/config-eslint",
"version": "0.0.0",
"private": true,
"exports": {
"./base": "./base.js",
"./next": "./next.js",
"./react": "./react.js"
},
"dependencies": {
"@typescript-eslint/eslint-plugin": "^6.19.0",
"@typescript-eslint/parser": "^6.19.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.0",
"eslint-plugin-react": "^7.33.0",
"eslint-plugin-react-hooks": "^4.6.0"
},
"devDependencies": {
"eslint": "^8.56.0"
}
}
```
### packages/config-eslint/base.js
```javascript
/** @type {import("eslint").Linter.Config} */
module.exports = {
parser: "@typescript-eslint/parser",
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
plugins: ["@typescript-eslint", "import"],
rules: {
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"@typescript-eslint/consistent-type-imports": ["warn", { prefer: "type-imports", fixStyle: "inline-type-imports" }],
"import/order": [
"error",
{
groups: ["builtin", "external", "internal", "parent", "sibling", "index"],
"newlines-between": "always",
alphabetize: { order: "asc" },
},
],
},
ignorePatterns: ["node_modules", "dist", ".next", "coverage"],
};
```
## App Configuration
### apps/web/package.json
```json
{
"name": "@repo/web",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@repo/database": "workspace:*",
"@repo/shared": "workspace:*",
"@repo/ui": "workspace:*",
"next": "^14.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@repo/config-eslint": "workspace:*",
"@repo/config-tailwind": "workspace:*",
"@repo/config-typescript": "workspace:*",
"@types/node": "^20.11.0",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"eslint": "^8.56.0",
"typescript": "^5.3.0"
}
}
```
### apps/web/tsconfig.json
```json
{
"extends": "@repo/config-typescript/nextjs.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
```
## Remote Caching
### Setup Vercel Remote Cache
```bash
# Login to Vercel
npx turbo login
# Link to Vercel project
npx turbo link
```
### Self-hosted Remote Cache
```typescript
// turbo.json with custom cache
{
"remoteCache": {
"signature": true
}
}
```
```bash
# Set environment variables
export TURBO_TOKEN=your-token
export TURBO_TEAM=your-team
export TURBO_API=https://your-cache-server.com
```
## CI/CD Pipeline
### GitHub Actions
```yaml
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- uses: pnpm/action-setup@v2
with:
version: 8
- uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm build
- name: Lint
run: pnpm lint
- name: Type check
run: pnpm typecheck
- name: Test
run: pnpm test
deploy-web:
needs: build
if: github.ref == 'refs/heads/main'
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: 20
cache: "pnpm"
- run: pnpm install --frozen-lockfile
- name: Build web app
run: pnpm turbo run build --filter=@repo/web
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
working-directory: apps/web
```
## Filtering Commands
```bash
# Build specific app
pnpm turbo run build --filter=@repo/web
# Build app and its dependencies
pnpm turbo run build --filter=@repo/web...
# Build only dependencies of an app
pnpm turbo run build --filter=@repo/web^...
# Build all except specific package
pnpm turbo run build --filter=!@repo/docs
# Build changed packages since main
pnpm turbo run build --filter=[main]
# Build packages in specific directory
pnpm turbo run build --filter=./apps/*
# Combine filters
pnpm turbo run build --filter=@repo/web --filter=@repo/api
```
## Development Workflow
```bash
# Start all apps in dev mode
pnpm dev
# Start specific app
pnpm turbo run dev --filter=@repo/web
# Add dependency to specific package
pnpm add zod --filter=@repo/shared
# Add workspace dependency
pnpm add @repo/ui --filter=@repo/web --workspace
# Run command in specific workspace
pnpm --filter @repo/web exec next build
# Interactive package manager
pnpm turbo gen workspace
```
## Output Format
Provide:
- Turborepo configurations
- Package structures
- Shared package setups
- CI/CD pipelines
- Filtering strategies
Sources:
- [Turborepo Documentation](https://turbo.build/repo/docs)
- [pnpm Workspaces](https://pnpm.io/workspaces)
- [Vercel Monorepo Guide](https://vercel.com/docs/monorepos)
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.