Skip to main content

CODITECT Production Folder Standard - Monorepo Projects

Version: 1.0.0 Last Updated: 2025-12-04 Applies To: Nx, Turborepo, Lerna, pnpm workspaces, Yarn workspaces Status: Production Standard


Overview

This standard defines the production-ready folder structure for monorepo projects containing multiple applications and shared libraries. Common for full-stack projects, microservices, and multi-platform applications.

Key Principles:

  • Application isolation - Each app is independent
  • Shared code extraction - Common code in packages/libs
  • Tool-agnostic - Works with Nx, Turborepo, Lerna
  • Dependency management - Clear boundaries between apps and libs
  • Build optimization - Parallel builds, caching, affected detection

Required Root Directory Structure

✅ Must Have in Root

monorepo-root/
├── README.md # Monorepo documentation
├── CLAUDE.md # AI agent context
├── CONTRIBUTING.md # Contribution guidelines
├── CHANGELOG.md # Version history
├── LICENSE # License file
├── SECURITY.md # Security policy
├── package.json # Root workspace config
├── pnpm-workspace.yaml # pnpm workspaces
├── nx.json # Nx configuration
├── turbo.json # Turborepo configuration
├── lerna.json # Lerna configuration
├── tsconfig.base.json # Base TypeScript config
├── .gitignore # Git ignore rules
├── .eslintrc.json # Root linting config
├── .prettierrc # Code formatting
└── docker-compose.yml # Local development

❌ Must NOT Have in Root

❌ Application code (*.tsx, *.py, *.rs)
❌ Shared library code directly in root
❌ Build artifacts
❌ Test files
❌ node_modules/ (should be in root only for hoisting)

Monorepo Structure Options

Option 1: Nx Monorepo (Enterprise)

monorepo/
├── apps/ # Applications
│ ├── web/ # Frontend web app (Next.js)
│ │ ├── src/
│ │ ├── public/
│ │ ├── package.json
│ │ ├── tsconfig.json
│ │ ├── project.json # Nx project config
│ │ └── README.md
│ ├── mobile/ # Mobile app (React Native)
│ │ ├── src/
│ │ ├── android/
│ │ ├── ios/
│ │ ├── package.json
│ │ └── project.json
│ ├── api/ # Backend API (Node.js/FastAPI)
│ │ ├── src/
│ │ ├── package.json
│ │ ├── Dockerfile
│ │ └── project.json
│ ├── admin/ # Admin dashboard
│ │ ├── src/
│ │ ├── package.json
│ │ └── project.json
│ └── worker/ # Background worker
│ ├── src/
│ ├── package.json
│ └── project.json

├── libs/ # Shared libraries
│ ├── frontend/
│ │ ├── ui/ # Shared UI components
│ │ │ ├── src/
│ │ │ │ ├── Button/
│ │ │ │ ├── Card/
│ │ │ │ └── index.ts
│ │ │ ├── package.json
│ │ │ └── project.json
│ │ ├── state/ # State management
│ │ │ ├── src/
│ │ │ ├── package.json
│ │ │ └── project.json
│ │ └── hooks/ # Shared hooks
│ │ ├── src/
│ │ ├── package.json
│ │ └── project.json
│ ├── backend/
│ │ ├── auth/ # Authentication logic
│ │ │ ├── src/
│ │ │ ├── package.json
│ │ │ └── project.json
│ │ ├── database/ # Database utilities
│ │ │ ├── src/
│ │ │ ├── package.json
│ │ │ └── project.json
│ │ └── email/ # Email service
│ │ ├── src/
│ │ ├── package.json
│ │ └── project.json
│ └── shared/
│ ├── types/ # Shared TypeScript types
│ │ ├── src/
│ │ │ ├── user.ts
│ │ │ ├── post.ts
│ │ │ └── index.ts
│ │ ├── package.json
│ │ └── project.json
│ ├── utils/ # Shared utilities
│ │ ├── src/
│ │ ├── package.json
│ │ └── project.json
│ ├── config/ # Shared configuration
│ │ ├── src/
│ │ ├── package.json
│ │ └── project.json
│ └── constants/ # Shared constants
│ ├── src/
│ ├── package.json
│ └── project.json

├── tools/ # Development tools
│ ├── generators/ # Code generators
│ │ ├── app/
│ │ └── lib/
│ ├── scripts/ # Utility scripts
│ │ ├── build-all.sh
│ │ ├── test-all.sh
│ │ └── deploy.sh
│ └── webpack-plugins/ # Custom webpack plugins

├── docs/ # Documentation
│ ├── api/
│ ├── architecture/
│ │ └── adrs/
│ ├── deployment/
│ └── monorepo-guide.md

├── dist/ # Build output (gitignored)
│ ├── apps/
│ └── libs/

└── node_modules/ # Hoisted dependencies

Option 2: Turborepo (Simpler)

monorepo/
├── apps/ # Applications
│ ├── web/ # Next.js frontend
│ │ ├── app/
│ │ ├── public/
│ │ ├── package.json
│ │ └── turbo.json
│ ├── docs/ # Documentation site
│ │ ├── pages/
│ │ ├── public/
│ │ └── package.json
│ └── api/ # Express backend
│ ├── src/
│ ├── package.json
│ └── Dockerfile

├── packages/ # Shared packages
│ ├── ui/ # UI component library
│ │ ├── src/
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── config/ # Shared configs
│ │ ├── eslint/
│ │ ├── typescript/
│ │ └── package.json
│ ├── tsconfig/ # TypeScript configs
│ │ ├── base.json
│ │ ├── nextjs.json
│ │ └── package.json
│ └── types/ # Shared types
│ ├── src/
│ └── package.json

├── package.json # Root workspace
├── turbo.json # Turborepo config
└── pnpm-workspace.yaml # pnpm workspaces

Option 3: Simple Monorepo (Minimal)

monorepo/
├── src/
│ ├── client/ # Frontend (React)
│ │ ├── components/
│ │ ├── pages/
│ │ └── package.json
│ └── server/ # Backend (Node.js)
│ ├── routes/
│ ├── controllers/
│ └── package.json

├── shared/ # Shared code
│ ├── types/
│ └── utils/

├── docs/
├── scripts/
└── package.json # Root workspace

Workspace Configuration

pnpm Workspaces

# pnpm-workspace.yaml
packages:
- 'apps/*'
- 'libs/*'
- 'packages/*'
- 'tools/*'

Nx Configuration

// nx.json
{
"npmScope": "@myorg",
"affected": {
"defaultBase": "main"
},
"tasksRunnerOptions": {
"default": {
"runner": "nx/tasks-runners/default",
"options": {
"cacheableOperations": ["build", "test", "lint"]
}
}
},
"targetDefaults": {
"build": {
"dependsOn": ["^build"]
}
}
}

Turborepo Configuration

// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"]
},
"test": {
"dependsOn": ["build"],
"cache": false
},
"lint": {
"outputs": []
},
"dev": {
"cache": false,
"persistent": true
}
}
}

Documentation Organization

docs/
├── architecture/ # Architecture documentation
│ ├── adrs/ # Monorepo-specific ADRs
│ │ ├── ADR-001-monorepo-tool.md
│ │ ├── ADR-002-shared-types.md
│ │ └── ADR-003-dependency-management.md
│ ├── C4-monorepo-context.md
│ └── inter-app-communication.md
├── deployment/ # Deployment guides
│ ├── docker-monorepo.md
│ ├── kubernetes-multi-app.md
│ └── ci-cd-monorepo.md
├── project-management/
│ ├── PROJECT-PLAN.md
│ └── TASKLIST-WITH-CHECKBOXES.md
├── apps/ # App-specific docs
│ ├── web/
│ │ └── README.md
│ └── api/
│ └── README.md
└── packages/ # Package-specific docs
├── ui/
│ └── README.md
└── types/
└── README.md

Scripts Organization

scripts/                         # Monorepo scripts
├── build/
│ ├── build-all.sh # Build all apps
│ ├── build-affected.sh # Build affected apps only
│ └── build-app.sh # Build specific app
├── test/
│ ├── test-all.sh # Test all apps
│ ├── test-affected.sh # Test affected apps only
│ └── test-app.sh # Test specific app
├── deploy/
│ ├── deploy-all.sh # Deploy all apps
│ ├── deploy-app.sh # Deploy specific app
│ └── rollback.sh # Rollback deployment
├── dev/
│ ├── start-all.sh # Start all dev servers
│ └── start-app.sh # Start specific app
└── utils/
├── sync-versions.sh # Sync package versions
├── check-deps.sh # Check for circular deps
└── generate-types.sh # Generate shared types

Dependency Management

Internal Dependencies

// apps/web/package.json
{
"name": "@myorg/web",
"dependencies": {
"@myorg/ui": "workspace:*",
"@myorg/types": "workspace:*",
"@myorg/utils": "workspace:*"
}
}

// libs/ui/package.json
{
"name": "@myorg/ui",
"dependencies": {
"@myorg/types": "workspace:*"
}
}

Versioning Strategy

// package.json (root)
{
"version": "1.0.0",
"workspaces": [
"apps/*",
"libs/*",
"packages/*"
]
}

Build Output Organization

dist/                            # Build artifacts (gitignored)
├── apps/
│ ├── web/
│ │ ├── .next/
│ │ └── out/
│ ├── api/
│ │ └── bundle.js
│ └── mobile/
│ ├── android/
│ └── ios/
└── libs/
├── ui/
│ └── dist/
└── types/
└── dist/

CI/CD for Monorepo

GitHub Actions Example

# .github/workflows/ci.yml
name: CI

on: [push, pull_request]

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetch all history for affected detection

- uses: pnpm/action-setup@v2
with:
version: 8

- name: Install dependencies
run: pnpm install

- name: Build affected
run: pnpm nx affected --target=build --base=origin/main

- name: Test affected
run: pnpm nx affected --target=test --base=origin/main

- name: Lint affected
run: pnpm nx affected --target=lint --base=origin/main

Project Type Detection Rules

Detect as Monorepo if:

  • Has apps/ and libs/ or packages/ directories
  • Has workspace configuration (pnpm-workspace.yaml, lerna.json, nx.json, turbo.json)
  • Root package.json has workspaces field
  • Multiple package.json files in subdirectories

Tool Detection:

  • Nx: Has nx.json or @nrwl/ packages
  • Turborepo: Has turbo.json
  • Lerna: Has lerna.json
  • pnpm: Has pnpm-workspace.yaml
  • Yarn: Has "workspaces" in package.json

Production Readiness Checklist

Root Configuration (25 points)

  • 5 pts: Workspace configuration present (pnpm-workspace.yaml, nx.json, turbo.json)
  • 5 pts: Root documentation (README, CLAUDE, CONTRIBUTING)
  • 5 pts: Shared configuration (tsconfig.base.json, .eslintrc)
  • 5 pts: CI/CD configuration for monorepo
  • 5 pts: Comprehensive .gitignore

Application Organization (25 points)

  • 5 pts: Clear apps/ directory with independent applications
  • 5 pts: Each app follows respective standard (frontend/backend)
  • 5 pts: No circular dependencies between apps
  • 5 pts: App-specific configuration and documentation
  • 5 pts: Independent deployment capability

Shared Code Organization (25 points)

  • 5 pts: Clear libs/ or packages/ directory
  • 5 pts: Proper namespace (@myorg/package-name)
  • 5 pts: Shared types extracted to common package
  • 5 pts: No circular dependencies between libs
  • 5 pts: Each lib has clear purpose and README

Build & Deployment (25 points)

  • 5 pts: Build caching configured (Nx/Turborepo)
  • 5 pts: Affected-only builds working
  • 5 pts: Scripts for monorepo operations
  • 5 pts: Docker configuration for each app
  • 5 pts: CI/CD pipeline optimized for monorepo

Total Score: 100 points Production Ready: 90+ points Needs Improvement: 70-89 points Not Ready: <70 points


Common Anti-Patterns to Avoid

❌ Don't Do This

❌ Circular dependencies between apps/libs
❌ Shared code directly in apps without extraction
❌ No versioning strategy for shared packages
❌ Building entire monorepo on every change
❌ No dependency boundaries enforcement
❌ Mixing app code with shared library code
❌ No caching or build optimization

✅ Do This Instead

✅ Clear dependency graph with no cycles
✅ Extract shared code to libs/ directory
✅ Use workspace protocol for internal deps
✅ Affected-only builds (Nx affected, Turbo cache)
✅ Enforce module boundaries with linting
✅ Keep apps and libs separate
✅ Configure build caching and parallelization

Monorepo Tool Comparison

FeatureNxTurborepoLernapnpm Workspaces
Build Caching✅ Advanced✅ Advanced❌ No❌ No
Affected Detection✅ Yes✅ Yes✅ Yes❌ No
Task Orchestration✅ Complex✅ Simple❌ Basic❌ No
Code Generation✅ Yes❌ No❌ No❌ No
Learning CurveHighLowMediumLow
Best ForEnterpriseVercel stackLegacySimple monorepos

Migration Guide

Converting to monorepo:

  1. Choose tool - Nx for complex, Turborepo for simple
  2. Create structure - apps/ and libs/ directories
  3. Extract shared code - Identify common code
  4. Setup workspaces - Configure package manager
  5. Configure builds - Setup caching and affected detection
  6. Update CI/CD - Optimize for monorepo
  7. Document structure - Update README and docs

Use: /organize-production command with monorepo detection


References


Status: Production Standard ✅ Version: 1.0.0 Last Updated: 2025-12-04 Applies To: Nx, Turborepo, Lerna, pnpm workspaces, Yarn workspaces