Turborepo monorepo setup with Yarn workspaces, shared configs, and development workflows. Use this skill when working with monorepo setup, shared packages, workspace dependencies, or build orchestration.
This skill covers the monorepo architecture, workspace management, and development workflows for the Game Critique project using Turborepo and Yarn workspaces.
Game-Critique/
├── .github/ # GitHub configs and workflows
│ └── skills/ # Copilot skills
├── apps/ # Application workspaces
│ ├── api/ # NestJS GraphQL API
│ ├── native/ # Expo React Native app
│ └── web/ # React admin panel
├── packages/ # Shared packages
│ └── typescript-config/ # Shared TypeScript configs
├── package.json # Root package.json
├── turbo.json # Turborepo configuration
├── yarn.lock # Yarn lockfile
└── compose.yml # Docker Compose setup
// package.json (root)
{
"private": true,
"workspaces": [
"./apps/*",
"./packages/*"
],
"packageManager": "yarn@4.5.3",
"engines": {
"node": ">=18"
}
}
# Install dependencies for all workspaces
yarn install
# Add dependency to specific workspace
yarn workspace api add @nestjs/graphql
yarn workspace web add @tanstack/react-query
yarn workspace native add tamagui
# Add dev dependency
yarn workspace api add -D jest
# Remove dependency
yarn workspace api remove @nestjs/graphql
# Run script in workspace
yarn workspace api dev
yarn workspace web build
# Run script in all workspaces
yarn workspaces foreach run build
yarn workspaces foreach run test
# Interactive upgrade
yarn upgrade-interactive
// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["**/.env.*local"],
"tasks": {
"build": {
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
"dependsOn": ["^build"]
},
"dev": {
"cache": false,
"persistent": true
},
"test": {
"cache": false,
"persistent": false
},
"lint": {
"outputs": []
},
"clean": {
"cache": false
}
}
}
Build Dependencies:
^build means "build dependencies first"Caching:
cache: false for dev servers and testspersistent: true for long-running processes# Run tasks across all workspaces
turbo run build # Build all apps
turbo run dev # Start all dev servers
turbo run test # Run all tests
turbo run lint # Lint all code
# Run task for specific workspace
turbo run build --filter=api
turbo run dev --filter=web
turbo run test --filter=native
# Run task for multiple workspaces
turbo run dev --filter=web --filter=api
# Force run (ignore cache)
turbo run build --force
# Clear cache
turbo run clean
// package.json (root)
{
"scripts": {
"dev": "turbo run dev",
"dev:web": "turbo run dev --filter=web --filter=api",
"dev:api": "turbo run dev --filter=api",
"build": "turbo run build",
"test": "turbo run test",
"lint": "turbo run lint",
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\" --ignore-path .gitignore",
"clean": "turbo run clean && rm -rf node_modules"
}
}
packages/
typescript-config/
├── package.json
├── base.json # Base config
├── nestjs.json # NestJS-specific
├── nextjs.json # Next.js-specific
└── react-native-library.json
Package.json:
{
"name": "@repo/typescript-config",
"version": "0.0.0",
"private": true,
"files": [
"base.json",
"nestjs.json",
"nextjs.json",
"react-native-library.json"
]
}
Base Config:
// packages/typescript-config/base.json
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
}
}
NestJS Config:
// packages/typescript-config/nestjs.json
{
"extends": "./base.json",
"compilerOptions": {
"module": "commonjs",
"target": "ES2021",
"lib": ["ES2021"],
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"incremental": true,
"strictNullChecks": false,
"noImplicitAny": false,
"strictBindCallApply": false,
"strictPropertyInitialization": false
}
}
// apps/api/tsconfig.json
{
"extends": "@repo/typescript-config/nestjs.json",
"compilerOptions": {
"outDir": "./dist",
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
// apps/api/package.json
{
"name": "api",
"dependencies": {
"@repo/typescript-config": "*"
}
}
* for internal workspace dependenciesFull Stack:
# Start all services
yarn dev
# API + Web only
yarn dev:web
# API only
yarn dev:api
Individual Apps:
# API with database
cd apps/api
yarn start:db # Start PostgreSQL + Redis
yarn dev # Start API in watch mode
# Web admin panel
cd apps/web
yarn dev # Starts on port 5173
# Native mobile app
cd apps/native
yarn dev-local # With local API
yarn dev # With production API
# Build all apps
yarn build
# Build specific app
cd apps/api && yarn build
cd apps/web && yarn build
# Build with Turborepo
turbo run build --filter=api
turbo run build --filter=web
# Lint all workspaces
yarn lint
# Format all code
yarn format
# Workspace-specific
cd apps/api && yarn lint
cd apps/web && yarn format
apps/
api/
.env
.env.local
.env.example
web/
.env
.env.local
native/
.env.local
.env.production
API (NestJS):
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
],
})
export class AppModule {}
Web (Vite):
// Access with import.meta.env
const apiUrl = import.meta.env.VITE_API_URL;
Native (Expo):
// Access with process.env.EXPO_PUBLIC_*
const apiUrl = process.env.EXPO_PUBLIC_GRAPHQL_ENDPOINT;
// turbo.json
{
"globalDependencies": ["**/.env.*local"]
}
This ensures Turbo cache is invalidated when env files change.
# compose.yml (root)
name: game-critique
include:
- path: apps/api/compose.yml
# apps/api/compose.yml
services:
postgres:
image: postgres:15
ports:
- "5432:5432"
environment:
POSTGRES_USER: game_critique
POSTGRES_PASSWORD: password
POSTGRES_DB: game_critique
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
# Start services (from root or apps/api)
docker-compose up -d
# Stop services
docker-compose down
# View logs
docker-compose logs -f postgres
docker-compose logs -f redis
# Reset databases
docker-compose down -v # Removes volumes
// package.json (root)
{
"scripts": {
"prepare": "husky install"
},
"lint-staged": {
"*.{ts,tsx}": [
"prettier --write"
]
}
}
# .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
# graphql.config.yml (root)
schema: "apps/api/src/schema.gql"
apps/api/src/schema.gql// apps/web/codegen-dev.ts
const config: CodegenConfig = {
schema: "http://localhost:3001/graphql", // Or file path
documents: "src/**/*.graphql",
// ...
};
// apps/native/codegen.ts
const config: CodegenConfig = {
schema: process.env.EXPO_PUBLIC_GRAPHQL_ENDPOINT,
documents: ["modules/**/*.graphql"],
// ...
};
mkdir -p apps/new-app
cd apps/new-app
yarn init -p
{
"name": "new-app",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "...",
"build": "...",
"test": "..."
},
"dependencies": {
"@repo/typescript-config": "*"
}
}
# From root
yarn install
// turbo.json
{
"tasks": {
"new-task": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
}
}
}
mkdir -p packages/shared-utils
cd packages/shared-utils
// packages/shared-utils/package.json
{
"name": "@repo/shared-utils",
"version": "0.0.0",
"private": true,
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"scripts": {
"build": "tsc",
"dev": "tsc --watch"
},
"devDependencies": {
"@repo/typescript-config": "*",
"typescript": "^5.0.0"
}
}
// packages/shared-utils/tsconfig.json
{
"extends": "@repo/typescript-config/base.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"]
}
// packages/shared-utils/src/index.ts
export function formatDate(date: Date): string {
return date.toISOString();
}
export function slugify(text: string): string {
return text.toLowerCase().replace(/\s+/g, '-');
}
cd packages/shared-utils
yarn build
// apps/api/package.json
{
"dependencies": {
"@repo/shared-utils": "*"
}
}
// apps/api/src/some-file.ts
import { formatDate, slugify } from '@repo/shared-utils';
# Clear all node_modules
yarn clean
# Reinstall everything
yarn install
# Rebuild packages
turbo run build
# Clear Turbo cache
turbo run build --force
# Or delete cache directory
rm -rf node_modules/.cache/turbo
# Check workspace configuration
yarn workspaces list
# Verify package.json workspace paths
# Ensure package names match
# Find process using port
lsof -i :3000
lsof -i :5173
# Kill process
kill -9 <PID>
# Or change port in config
# Rebuild TypeScript projects
turbo run build --filter=@repo/typescript-config
turbo run build
# Restart TypeScript server in IDE
# VSCode: Cmd+Shift+P -> "TypeScript: Restart TS Server"
// Use * for internal dependencies
"dependencies": {
"@repo/typescript-config": "*" // ✅ Good
"@repo/typescript-config": "1.0.0" // ❌ Bad
}
dependsOn for build dependencies# Root level
yarn install # Install all dependencies
yarn dev # Start all apps
yarn dev:web # Start web + api
yarn dev:api # Start api only
yarn build # Build all apps
yarn lint # Lint all code
yarn format # Format all code
yarn clean # Clean all workspaces
# Workspace level
yarn workspace api dev
yarn workspace web build
yarn workspace native test
# Turbo commands
turbo run build
turbo run dev --filter=api
turbo run test --filter=web --filter=api
turbo run build --force
# Docker
docker-compose up -d
docker-compose down
docker-compose logs -f
# Yarn workspaces
yarn workspaces list
yarn workspaces foreach run build
yarn workspace api add lodash
# .github/workflows/ci.yml
- name: Setup Turbo cache
uses: actions/cache@v3
with:
path: .turbo
key: ${{ runner.os }}-turbo-${{ github.sha }}
restore-keys: |
${{ runner.os }}-turbo-
# Build only changed apps
turbo run build --filter=[HEAD^1]
# Test affected apps
turbo run test --filter=[main...HEAD]
strategy:
matrix:
app: [api, web, native]
steps:
- run: turbo run build --filter=${{ matrix.app }}
npx skills add Survikrowa/monorepo-structure下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer