Exemplos de Turbo Monorepo

Exemplos do sistema de build Turbo monorepo incluindo configuração de workspace, orquestração de tarefas, e estratégias de caching

💻 Configuração Básica de Turbo Monorepo json

🟢 simple ⭐⭐

Configuração completa de Turbo monorepo com múltiplas aplicações e pacotes

⏱️ 20 min 🏷️ turbo, monorepo, setup
Prerequisites: Node.js, pnpm/yarn/npm, TypeScript
// Turbo Monorepo Basic Setup

// 1. Installation
// npm install turbo --save-dev
// or: pnpm add -D turbo
// or: yarn add -D turbo

// 2. package.json (Root)
{
  "name": "my-turbo-monorepo",
  "private": true,
  "workspaces": [
    "apps/*",
    "packages/*"
  ],
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint",
    "test": "turbo run test",
    "clean": "turbo run clean && rm -rf node_modules",
    "format": "prettier --write "**/*.{ts,tsx,md}"",
    "changeset": "changeset",
    "version-packages": "changeset version",
    "release": "turbo run build --filter=!@repo/docs && changeset publish"
  },
  "devDependencies": {
    "turbo": "^2.0.0",
    "prettier": "^3.0.0",
    "changesets": "^2.26.0"
  },
  "packageManager": "[email protected]"
}

// 3. turbo.json - Root configuration
{
  "$schema": "https://turbo.build/schema.json",
  "globalEnv": [
    "NODE_ENV",
    "NEXT_PUBLIC_API_URL",
    "DATABASE_URL"
  ],
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**", "dist/**", "!.next/**/(!*.next)"]
    },
    "test": {
      "dependsOn": ["build"],
      "outputs": ["coverage/**"],
      "inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts", "test/**/*.tsx"]
    },
    "lint": {
      "outputs": []
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "clean": {
      "cache": false
    },
    "type-check": {
      "dependsOn": ["^build"]
    },
    "format": {
      "outputs": []
    }
  },
  "globalDependencies": [
    "**/.env.*local",
    "turbo.json",
    "package.json",
    "pnpm-lock.yaml",
    "yarn.lock",
    "npm-shrinkwrap.json"
  ]
}

// 4. Project structure
/*
my-turbo-monorepo/
├── apps/
│   ├── web/                    # Next.js frontend application
│   │   ├── package.json
│   │   ├── next.config.js
│   │   └── turbo.json
│   ├── api/                    # Backend API (Express/Fastify)
│   │   ├── package.json
│   │   └── turbo.json
│   └── docs/                   # Documentation site
│       ├── package.json
│       └── turbo.json
├── packages/
│   ├── ui/                     # Shared UI components
│   │   ├── package.json
│   │   ├── turbo.json
│   │   └── src/
│   ├── utils/                  # Shared utilities
│   │   ├── package.json
│   │   ├── turbo.json
│   │   └── src/
│   ├── config/                 # Shared configuration
│   │   ├── package.json
│   │   ├── eslint.config.js
│   │   ├── tsconfig.base.json
│   │   └── turbo.json
│   └── types/                  # Shared TypeScript types
│       ├── package.json
│       ├── turbo.json
│       └── src/
├── package.json
├── turbo.json
├── pnpm-workspace.yaml
└── .gitignore
*/

// 5. pnpm-workspace.yaml
packages:
  - 'apps/*'
  - 'packages/*'

// 6. Example app configuration (apps/web/turbo.json)
{
  "extends": ["//"],
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "lint": {},
    "test": {
      "dependsOn": ["build"],
      "outputs": ["coverage/**"]
    }
  }
}

// 7. Example package configuration (packages/ui/turbo.json)
{
  "extends": ["//"],
  "pipeline": {
    "build": {
      "outputs": ["dist/**"]
    },
    "lint": {},
    "test": {
      "dependsOn": ["build"],
      "outputs": ["coverage/**"]
    }
  }
}

// 8. TypeScript configuration (packages/config/tsconfig.base.json)
{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["dom", "dom.iterable", "ES2022"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "ESNext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "baseUrl": ".",
    "paths": {
      "@repo/ui": ["../../packages/ui/src"],
      "@repo/utils": ["../../packages/utils/src"],
      "@repo/types": ["../../packages/types/src"],
      "@repo/config/*": ["./"]
    }
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    ".next/types/**/*.ts"
  ],
  "exclude": ["node_modules"]
}

// 9. Environment variables (.env.example)
# Database
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"

# API
NEXT_PUBLIC_API_URL="http://localhost:3001/api"

# Authentication
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="your-secret-key"

# External services
REDIS_URL="redis://localhost:6379"
STRIPE_API_KEY="sk_test_..."
SENTRY_DSN="https://your-sentry-dsn"

💻 Workspace Multi-Aplicação Turbo typescript

🟡 intermediate ⭐⭐⭐⭐

Configuração avançada de monorepo com frontend Next.js, backend Express, e pacotes compartilhados

⏱️ 35 min 🏷️ turbo, monorepo, nextjs, express
Prerequisites: Turbo basics, Next.js, Express, TypeScript
// Turbo Multi-Application Workspace Example

// 1. Next.js Application (apps/web/package.json)
{
  "name": "@repo/web",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "test": "jest",
    "type-check": "tsc --noEmit"
  },
  "dependencies": {
    "next": "^14.0.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "@repo/ui": "workspace:*",
    "@repo/utils": "workspace:*",
    "@repo/types": "workspace:*",
    "axios": "^1.6.0",
    "next-auth": "^4.24.0"
  },
  "devDependencies": {
    "@repo/config/eslint": "workspace:*",
    "@repo/config/typescript": "workspace:*",
    "@types/node": "^20.0.0",
    "@types/react": "^18.2.0",
    "@types/react-dom": "^18.2.0",
    "autoprefixer": "^10.4.0",
    "postcss": "^8.4.0",
    "tailwindcss": "^3.3.0",
    "typescript": "^5.3.0"
  }
}

// 2. Next.js Configuration (apps/web/next.config.js)
const withTM = require('next-transpile-modules')([
  '@repo/ui',
  '@repo/utils',
  '@repo/types'
])

/** @type {import('next').NextConfig} */
const nextConfig = {
  transpilePackages: ['@repo/ui', '@repo/utils', '@repo/types'],
  experimental: {
    optimizePackageImports: ['@repo/ui']
  },
  images: {
    domains: ['example.com', 'images.unsplash.com']
  },
  env: {
    CUSTOM_KEY: process.env.CUSTOM_KEY
  }
}

module.exports = nextConfig

// 3. Express Backend Application (apps/api/package.json)
{
  "name": "@repo/api",
  "version": "0.1.0",
  "private": true,
  "main": "dist/index.js",
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js",
    "lint": "eslint src --max-warnings 0",
    "test": "jest",
    "type-check": "tsc --noEmit"
  },
  "dependencies": {
    "express": "^4.18.0",
    "cors": "^2.8.0",
    "helmet": "^7.1.0",
    "compression": "^1.7.0",
    "morgan": "^1.10.0",
    "@repo/utils": "workspace:*",
    "@repo/types": "workspace:*",
    "zod": "^3.22.0",
    "prisma": "^5.6.0"
  },
  "devDependencies": {
    "@repo/config/eslint": "workspace:*",
    "@repo/config/typescript": "workspace:*",
    "@types/express": "^4.17.0",
    "@types/cors": "^2.8.0",
    "@types/compression": "^1.7.0",
    "@types/morgan": "^1.9.0",
    "tsx": "^4.6.0",
    "typescript": "^5.3.0"
  }
}

// 4. Express Application (apps/api/src/index.ts)
import express from 'express'
import cors from 'cors'
import helmet from 'helmet'
import compression from 'compression'
import morgan from 'morgan'
import { logger } from '@repo/utils/logger'
import { ApiResponse } from '@repo/types/api'

const app = express()
const PORT = process.env.PORT || 3001

// Middleware
app.use(helmet())
app.use(compression())
app.use(cors({
  origin: process.env.FRONTEND_URL || 'http://localhost:3000',
  credentials: true
}))
app.use(morgan('combined'))
app.use(express.json({ limit: '10mb' }))
app.use(express.urlencoded({ extended: true }))

// Health check endpoint
app.get('/health', (req, res): ApiResponse => {
  return res.json({
    success: true,
    message: 'API is healthy',
    timestamp: new Date().toISOString()
  })
})

// API routes
app.get('/api/users', async (req, res) => {
  try {
    // Simulate database call
    const users = [
      { id: 1, name: 'John Doe', email: '[email protected]' },
      { id: 2, name: 'Jane Smith', email: '[email protected]' }
    ]

    return res.json({
      success: true,
      data: users,
      count: users.length
    })
  } catch (error) {
    logger.error('Error fetching users:', error)
    return res.status(500).json({
      success: false,
      message: 'Internal server error'
    })
  }
})

// Error handling middleware
app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
  logger.error('Unhandled error:', err)

  return res.status(500).json({
    success: false,
    message: 'Internal server error'
  })
})

app.listen(PORT, () => {
  logger.info(`API server running on port ${PORT}`)
})

export default app

// 5. Shared UI Components Package (packages/ui/package.json)
{
  "name": "@repo/ui",
  "version": "0.1.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"
    },
    "./styles.css": "./dist/styles.css"
  },
  "files": ["dist"],
  "scripts": {
    "build": "tsup",
    "dev": "tsup --watch",
    "lint": "eslint src --max-warnings 0",
    "test": "jest",
    "type-check": "tsc --noEmit",
    "storybook": "storybook dev -p 6006",
    "build-storybook": "storybook build"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "clsx": "^2.0.0",
    "tailwind-merge": "^2.0.0",
    "@repo/types": "workspace:*"
  },
  "devDependencies": {
    "@repo/config/eslint": "workspace:*",
    "@repo/config/typescript": "workspace:*",
    "@storybook/addon-essentials": "^7.5.0",
    "@storybook/react": "^7.5.0",
    "@storybook/react-vite": "^7.5.0",
    "@types/react": "^18.2.0",
    "@types/react-dom": "^18.2.0",
    "autoprefixer": "^10.4.0",
    "postcss": "^8.4.0",
    "tailwindcss": "^3.3.0",
    "tsup": "^7.2.0",
    "typescript": "^5.3.0"
  },
  "peerDependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  }
}

// 6. UI Components Build Configuration (packages/ui/tsup.config.ts)
import { defineConfig } from 'tsup'

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['cjs', 'esm'],
  dts: true,
  splitting: false,
  sourcemap: true,
  clean: true,
  external: ['react', 'react-dom'],
  onSuccess: 'npm run build:css'
})

// 7. Shared Components (packages/ui/src/Button.tsx)
import React from 'react'
import { clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'

export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: 'primary' | 'secondary' | 'outline'
  size?: 'sm' | 'md' | 'lg'
  loading?: boolean
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant = 'primary', size = 'md', loading, children, disabled, ...props }, ref) => {
    const baseStyles = 'inline-flex items-center justify-center font-medium rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2'

    const variants = {
      primary: 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500',
      secondary: 'bg-gray-600 text-white hover:bg-gray-700 focus:ring-gray-500',
      outline: 'border border-gray-300 bg-white text-gray-700 hover:bg-gray-50 focus:ring-blue-500'
    }

    const sizes = {
      sm: 'px-3 py-1.5 text-sm',
      md: 'px-4 py-2 text-sm',
      lg: 'px-6 py-3 text-base'
    }

    return (
      <button
        className={clsx(
          baseStyles,
          variants[variant],
          sizes[size],
          (loading || disabled) && 'opacity-50 cursor-not-allowed',
          className
        )}
        disabled={loading || disabled}
        ref={ref}
        {...props}
      >
        {loading && (
          <svg className="animate-spin -ml-1 mr-2 h-4 w-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
            <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
            <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
          </svg>
        )}
        {children}
      </button>
    )
  }
)

Button.displayName = 'Button'

export { Button }

// 8. Shared Utilities Package (packages/utils/src/logger.ts)
export type LogLevel = 'debug' | 'info' | 'warn' | 'error'

export interface LogEntry {
  level: LogLevel
  message: string
  timestamp: Date
  metadata?: Record<string, any>
}

export class Logger {
  private level: LogLevel = 'info'

  setLevel(level: LogLevel) {
    this.level = level
  }

  private shouldLog(level: LogLevel): boolean {
    const levels: Record<LogLevel, number> = {
      debug: 0,
      info: 1,
      warn: 2,
      error: 3
    }

    return levels[level] >= levels[this.level]
  }

  private log(level: LogLevel, message: string, metadata?: Record<string, any>) {
    if (!this.shouldLog(level)) return

    const entry: LogEntry = {
      level,
      message,
      timestamp: new Date(),
      metadata
    }

    if (process.env.NODE_ENV === 'development') {
      console[level](message, metadata || '')
    } else {
      // In production, you might want to send logs to a service
      console.log(JSON.stringify(entry))
    }
  }

  debug(message: string, metadata?: Record<string, any>) {
    this.log('debug', message, metadata)
  }

  info(message: string, metadata?: Record<string, any>) {
    this.log('info', message, metadata)
  }

  warn(message: string, metadata?: Record<string, any>) {
    this.log('warn', message, metadata)
  }

  error(message: string, metadata?: Record<string, any>) {
    this.log('error', message, metadata)
  }
}

export const logger = new Logger()

// 9. Shared Types (packages/types/src/api.ts)
export interface ApiResponse<T = any> {
  success: boolean
  data?: T
  message?: string
  error?: string
  timestamp?: string
}

export interface PaginatedResponse<T> extends ApiResponse<T[]> {
  pagination: {
    page: number
    limit: number
    total: number
    totalPages: number
  }
}

export interface ApiError {
  code: string
  message: string
  field?: string
}

// 10. Shared Types (packages/types/src/user.ts)
export interface User {
  id: number
  name: string
  email: string
  avatar?: string
  role: UserRole
  createdAt: string
  updatedAt: string
}

export type UserRole = 'admin' | 'user' | 'moderator'

export interface CreateUserRequest {
  name: string
  email: string
  role?: UserRole
}

export interface UpdateUserRequest {
  name?: string
  email?: string
  role?: UserRole
}

💻 Workflows Avançados de Turbo yaml

🔴 complex ⭐⭐⭐⭐⭐

Workflows avançados de Turbo incluindo caching, filtering, deployment, e integração CI/CD

⏱️ 45 min 🏷️ turbo, ci/cd, deployment, advanced
Prerequisites: Advanced Turbo, Docker, GitHub Actions, CI/CD
// Turbo Advanced Workflows and CI/CD

// 1. Advanced turbo.json with complex dependencies
{
  "$schema": "https://turbo.build/schema.json",
  "globalEnv": [
    "NODE_ENV",
    "NEXT_PUBLIC_API_URL",
    "DATABASE_URL",
    "STRIPE_API_KEY",
    "SENTRY_DSN"
  ],
  "globalPassThroughEnv": [
    "VERCEL_*",
    "AWS_*",
    "GITHUB_*"
  ],
  "pipeline": {
    "build": {
      "dependsOn": ["^build", "^db:generate"],
      "outputs": [
        "dist/**",
        ".next/**",
        "!.next/cache/**",
        "!.next/**/(!*.next)",
        "public/build/**"
      ],
      "env": ["NODE_ENV", "NEXT_PUBLIC_API_URL"],
      "inputs": ["src/**/*.tsx", "src/**/*.ts", "package.json"]
    },
    "db:generate": {
      "outputs": ["prisma/migrations/**", "node_modules/.prisma/**"],
      "inputs": ["prisma/schema.prisma", "package.json"]
    },
    "db:push": {
      "cache": false,
      "outputs": ["prisma/migrations/**"]
    },
    "db:migrate": {
      "cache": false,
      "outputs": ["prisma/migrations/**"]
    },
    "test": {
      "dependsOn": ["build", "db:generate"],
      "outputs": ["coverage/**", "test-results/**"],
      "inputs": [
        "src/**/*.tsx",
        "src/**/*.ts",
        "test/**/*.ts",
        "test/**/*.tsx",
        "jest.config.*"
      ],
      "passThroughEnv": ["CI"]
    },
    "test:watch": {
      "cache": false,
      "persistent": true,
      "dependsOn": ["build"]
    },
    "lint": {
      "outputs": [],
      "inputs": ["src/**/*.tsx", "src/**/*.ts", "*.config.*"]
    },
    "lint:fix": {
      "cache": false,
      "outputs": []
    },
    "type-check": {
      "dependsOn": ["^build"],
      "outputs": []
    },
    "dev": {
      "cache": false,
      "persistent": true,
      "dependsOn": ["db:generate"]
    },
    "clean": {
      "cache": false,
      "outputs": []
    },
    "format": {
      "outputs": [],
      "inputs": [
        "**/*.{ts,tsx,js,jsx,json,md,css,scss}",
        ".prettierrc*"
      ]
    },
    "storybook": {
      "cache": false,
      "persistent": true,
      "dependsOn": ["build"]
    },
    "build-storybook": {
      "dependsOn": ["build"],
      "outputs": ["storybook-static/**"]
    },
    "deploy": {
      "dependsOn": ["build", "test", "lint"],
      "cache": false
    },
    "size-limit": {
      "dependsOn": ["build"],
      "outputs": []
    },
    "bundlesize": {
      "dependsOn": ["build"],
      "outputs": []
    }
  }
}

// 2. GitHub Actions Workflow (.github/workflows/ci.yml)
name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

env:
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
  TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
  NODE_VERSION: 20
  PNPM_VERSION: 8

jobs:
  build:
    name: Build and Test
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [18, 20]

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'pnpm'

      - name: Setup pnpm
        uses: pnpm/action-setup@v2
        with:
          version: ${{ env.PNPM_VERSION }}

      - name: Get pnpm store directory
        shell: bash
        run: |
          echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

      - name: Setup pnpm cache
        uses: actions/cache@v3
        with:
          path: ${{ env.STORE_PATH }}
          key: pnpm-store-${{ runner.os }}-${{ matrix.node-version }}-${{ env.PNPM_VERSION }}-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: |
            pnpm-store-${{ runner.os }}-${{ matrix.node-version }}-${{ env.PNPM_VERSION }}-

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Generate database schema
        run: pnpm db:generate

      - name: Run type checking
        run: pnpm type-check

      - name: Run linting
        run: pnpm lint

      - name: Run tests
        run: pnpm test --coverage

      - name: Build packages and apps
        run: pnpm build

      - name: Check bundle sizes
        run: pnpm size-limit

      - name: Upload coverage reports
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/lcov.info
          flags: unittests
          name: codecov-umbrella

  lint-pr:
    name: Lint Pull Request
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'pnpm'

      - name: Setup pnpm
        uses: pnpm/action-setup@v2
        with:
          version: ${{ env.PNPM_VERSION }}

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Run changesets
        uses: changesets/action@v1
        with:
          publish: pnpm changeset publish
          commit: 'chore: release packages'
          title: 'chore: release packages'

// 3. Deployment Script (scripts/deploy.sh)
#!/bin/bash

set -e

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Configuration
ENVIRONMENT=${1:-production}
APP_NAME="my-turbo-app"

echo -e "${GREEN}Starting deployment of ${APP_NAME} to ${ENVIRONMENT}${NC}"

# Step 1: Run tests
echo -e "${YELLOW}Running tests...${NC}"
pnpm test
echo -e "${GREEN}✓ Tests passed${NC}"

# Step 2: Build all packages
echo -e "${YELLOW}Building packages...${NC}"
pnpm build
echo -e "${GREEN}✓ Build completed${NC}"

# Step 3: Deploy based on environment
case ${ENVIRONMENT} in
  "production")
    echo -e "${YELLOW}Deploying to production...${NC}"

    # Deploy web app to Vercel
    echo "Deploying web app to Vercel..."
    cd apps/web
    npx vercel --prod --token $VERCEL_TOKEN
    cd ../..

    # Deploy API to Railway/Heroku
    echo "Deploying API to production..."
    cd apps/api
    # Railway deployment
    railway deploy
    cd ../..

    echo -e "${GREEN}✓ Production deployment completed${NC}"
    ;;

  "staging")
    echo -e "${YELLOW}Deploying to staging...${NC}"

    # Deploy web app to Vercel preview
    cd apps/web
    npx vercel --token $VERCEL_TOKEN
    cd ../..

    # Deploy API to staging
    cd apps/api
    # Staging deployment
    docker build -t ${APP_NAME}-api:staging .
    docker push ${DOCKER_REGISTRY}/${APP_NAME}-api:staging
    cd ../..

    echo -e "${GREEN}✓ Staging deployment completed${NC}"
    ;;

  *)
    echo -e "${RED}Unknown environment: ${ENVIRONMENT}${NC}"
    exit 1
    ;;
esac

echo -e "${GREEN}🚀 Deployment completed successfully!${NC}"

// 4. Docker Compose for Development (docker-compose.dev.yml)
version: '3.8'

services:
  postgres:
    image: postgres:15
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: myapp_dev
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data

  minio:
    image: minio/minio:latest
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: minioadmin
      MINIO_ROOT_PASSWORD: minioadmin123
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - minio_data:/data

  api:
    build:
      context: .
      dockerfile: apps/api/Dockerfile.dev
    ports:
      - "3001:3001"
    environment:
      NODE_ENV: development
      DATABASE_URL: postgresql://postgres:postgres@postgres:5432/myapp_dev
      REDIS_URL: redis://redis:6379
    depends_on:
      - postgres
      - redis
    volumes:
      - ./apps/api:/app/apps/api
      - ./packages:/app/packages
      - /app/node_modules

  web:
    build:
      context: .
      dockerfile: apps/web/Dockerfile.dev
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: development
      NEXT_PUBLIC_API_URL: http://localhost:3001
    depends_on:
      - api
    volumes:
      - ./apps/web:/app/apps/web
      - ./packages:/app/packages
      - /app/node_modules

volumes:
  postgres_data:
  redis_data:
  minio_data:

// 5. API Dockerfile for Development (apps/api/Dockerfile.dev)
FROM node:20-alpine

WORKDIR /app

# Copy package files
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY apps/api/package.json ./apps/api/
COPY packages/*/package.json ./packages/*/

# Install pnpm
RUN npm install -g pnpm

# Install dependencies
RUN pnpm install --frozen-lockfile

# Copy source code
COPY apps/api ./apps/api
COPY packages ./packages

# Generate Prisma client
RUN pnpm db:generate

EXPOSE 3001

CMD ["pnpm", "dev"]

// 6. Web Dockerfile for Development (apps/web/Dockerfile.dev)
FROM node:20-alpine

WORKDIR /app

# Copy package files
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY apps/web/package.json ./apps/web/
COPY packages/*/package.json ./packages/*/

# Install pnpm
RUN npm install -g pnpm

# Install dependencies
RUN pnpm install --frozen-lockfile

# Copy source code
COPY apps/web ./apps/web
COPY packages ./packages

EXPOSE 3000

CMD ["pnpm", "dev"]

// 7. Size Limit Configuration (size-limit.json)
[
  {
    "name": "Web App Bundle",
    "path": "apps/web/.next/static/chunks/**/*.js",
    "limit": "1 MB",
    "ignore": [
      "**/node_modules/**"
    ]
  },
  {
    "name": "API Bundle",
    "path": "apps/api/dist/**/*.js",
    "limit": "500 KB"
  },
  {
    "name": "UI Components",
    "path": "packages/ui/dist/**/*.js",
    "limit": "100 KB"
  },
  {
    "name": "Utils Package",
    "path": "packages/utils/dist/**/*.js",
    "limit": "50 KB"
  }
]

// 8. Advanced Package Scripts
{
  "scripts": {
    // Development workflows
    "dev:all": "concurrently "pnpm dev:web" "pnpm dev:api" "pnpm dev:storybook"",
    "dev:web": "turbo run dev --filter=@repo/web",
    "dev:api": "turbo run dev --filter=@repo/api",
    "dev:storybook": "turbo run storybook --filter=@repo/ui",

    // Build workflows
    "build:affected": "turbo run build --filter='...[origin/HEAD]'",
    "build:web": "turbo run build --filter=@repo/web",
    "build:api": "turbo run build --filter=@repo/api",

    // Test workflows
    "test:affected": "turbo run test --filter='...[origin/HEAD]'",
    "test:ci": "turbo run test --concurrency=1",
    "test:coverage": "turbo run test -- --coverage",

    // Quality assurance
    "lint:affected": "turbo run lint --filter='...[origin/HEAD]'",
    "type-check:affected": "turbo run type-check --filter='...[origin/HEAD]'",
    "quality-check": "pnpm lint && pnpm type-check && pnpm test && pnpm build",

    // Database workflows
    "db:generate": "turbo run db:generate",
    "db:push": "turbo run db:push",
    "db:migrate": "turbo run db:migrate",
    "db:reset": "pnpm db:push --force-reset",

    // Package management
    "clean": "turbo run clean && rm -rf node_modules",
    "reinstall": "pnpm clean && pnpm install",
    "update": "pnpm update -i -r && pnpm install",

    // Release workflows
    "changeset": "changeset",
    "version": "changeset version",
    "release": "pnpm build && pnpm test && changeset publish",

    // Deployment workflows
    "deploy:staging": "./scripts/deploy.sh staging",
    "deploy:production": "./scripts/deploy.sh production",

    // Performance monitoring
    "size-limit": "size-limit",
    "bundle-analyzer": "turbo run build --filter=@repo/web && npx @next/bundle-analyzer apps/web/.next"
  }
}