Skip to content

Monorepo Setup Plan

Overview

This document outlines the setup and configuration of a monorepo structure for the content generation system using GitHub, with deployments to Vercel (Next.js frontend) and Railway (Python services). The monorepo approach enables shared configurations, easier collaboration, and streamlined CI/CD.

Repository Structure

content-gen-monorepo/
├── apps/                      # Main applications
│   ├── frontend/              # Next.js app (Vercel)
│   │   ├── src/
│   │   │   ├── app/          # App Router pages
│   │   │   ├── components/   # React components
│   │   │   ├── lib/          # Utilities
│   │   │   └── hooks/        # Custom hooks
│   │   ├── public/           # Static assets
│   │   ├── package.json
│   │   ├── next.config.js
│   │   ├── tsconfig.json
│   │   └── .env.local        # Local env vars
│   ├── cpm/                  # Content Production Module (Railway)
│   │   ├── app.py
│   │   ├── llm_client.py
│   │   ├── requirements.txt
│   │   ├── railway.json
│   │   └── .env
│   └── im/                   # Instructions Module (Railway)
│       ├── app.py
│       ├── requirements.txt
│       ├── railway.json
│       └── .env
├── packages/                 # Shared packages (V2)
│   └── shared-types/         # TypeScript types
├── docs/                     # Documentation
│   ├── architecture.md
│   └── deployment.md
├── .github/                  # GitHub Actions
│   └── workflows/
│       └── ci.yml
├── .gitignore
├── package.json              # Root package.json
├── pnpm-workspace.yaml       # pnpm workspace config
├── turbo.json                # Turborepo config
└── README.md

Initial Setup Steps

1. Create GitHub Repository

# Create new directory
mkdir content-gen-monorepo
cd content-gen-monorepo

# Initialize git
git init

# Create initial structure
mkdir -p apps/{frontend,cpm,im} packages docs .github/workflows

# Initialize root package.json
npm init -y

2. Configure pnpm Workspaces

Create pnpm-workspace.yaml:

packages:
  - 'apps/*'
  - 'packages/*'

Update root package.json:

{
  "name": "content-gen-monorepo",
  "version": "1.0.0",
  "private": true,
  "workspaces": [
    "apps/*",
    "packages/*"
  ],
  "scripts": {
    "dev": "turbo run dev",
    "build": "turbo run build",
    "test": "turbo run test",
    "lint": "turbo run lint"
  },
  "devDependencies": {
    "turbo": "^1.13.0"
  },
  "engines": {
    "node": ">=18.0.0",
    "pnpm": ">=8.0.0"
  }
}

3. Configure Turborepo

Create turbo.json:

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

4. Setup Frontend (Next.js)

cd apps/frontend

# Initialize Next.js app
pnpm create next-app@latest . --typescript --tailwind --app --src-dir --import-alias "@/*"

# Add dependencies
pnpm add @supabase/supabase-js axios swr
pnpm add -D @types/node

Create apps/frontend/next.config.js:

/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'standalone',
  env: {
    NEXT_PUBLIC_SUPABASE_URL: process.env.NEXT_PUBLIC_SUPABASE_URL,
    NEXT_PUBLIC_SUPABASE_ANON_KEY: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
    CPM_SERVICE_URL: process.env.CPM_SERVICE_URL,
    IM_SERVICE_URL: process.env.IM_SERVICE_URL,
  }
}

module.exports = nextConfig

5. Setup Python Services

CPM Setup

cd apps/cpm

# Create Python virtual environment (local development)
python -m venv .venv
source .venv/bin/activate  # or .venv\Scripts\activate on Windows

# Create requirements.txt (see CPM plan for full list)
cat > requirements.txt << EOF
fastapi==0.111.0
uvicorn==0.30.1
pydantic==2.7.1
supabase==2.5.0
openai==1.35.0
anthropic==0.30.0
google-generativeai==0.6.0
httpx==0.27.0
python-dotenv==1.0.1
EOF

# Install dependencies
pip install -r requirements.txt

# Create railway.json
cat > railway.json << 'EOF'
{
  "$schema": "https://railway.app/railway.schema.json",
  "build": {
    "builder": "NIXPACKS"
  },
  "deploy": {
    "startCommand": "uvicorn app:app --host 0.0.0.0 --port $PORT",
    "restartPolicyType": "ON_FAILURE",
    "restartPolicyMaxRetries": 3
  }
}
EOF

IM Setup (similar structure)

cd apps/im
# Repeat similar setup with IM-specific requirements

6. Configure Git and GitHub

Create .gitignore:

# Dependencies
node_modules/
.pnpm-store/

# Python
__pycache__/
*.py[cod]
*$py.class
.venv/
venv/
.env

# Next.js
.next/
out/
dist/

# Testing
coverage/
.nyc_output/

# Turborepo
.turbo/

# OS
.DS_Store
Thumbs.db

# IDEs
.vscode/
.idea/
*.swp
*.swo

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Environment variables
.env
.env.local
.env.*.local

GitHub Actions CI/CD

Create .github/workflows/ci.yml:

name: CI

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

jobs:
  lint-and-test:
    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'

      - uses: actions/setup-python@v4
        with:
          python-version: '3.12'

      - name: Install dependencies
        run: pnpm install

      - name: Run lints
        run: pnpm lint

      - name: Run tests
        run: pnpm test

      - name: Build
        run: pnpm build

  python-tests:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        service: [cpm, im]

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v4
        with:
          python-version: '3.12'

      - name: Install dependencies
        working-directory: apps/${{ matrix.service }}
        run: |
          pip install -r requirements.txt
          pip install pytest pytest-asyncio

      - name: Run tests
        working-directory: apps/${{ matrix.service }}
        run: pytest

Vercel Configuration

1. Connect Repository

  1. Go to Vercel Dashboard
  2. Click "Add New Project"
  3. Import from GitHub repository
  4. Select the monorepo

2. Configure Project Settings

  • Framework Preset: Next.js
  • Root Directory: apps/frontend
  • Build Command: cd ../.. && pnpm build --filter=frontend
  • Output Directory: apps/frontend/.next
  • Install Command: pnpm install

3. Environment Variables

Add in Vercel dashboard:

NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
CPM_SERVICE_URL=https://cpm.railway.app
IM_SERVICE_URL=https://im.railway.app

4. Configure Deployment Hooks

Create apps/frontend/vercel.json:

{
  "buildCommand": "cd ../.. && pnpm build --filter=frontend",
  "installCommand": "pnpm install",
  "framework": "nextjs",
  "outputDirectory": ".next"
}

Railway Configuration

1. Create Railway Project

  1. Go to Railway Dashboard
  2. Create new project
  3. Add services from GitHub repo

2. Configure CPM Service

  • Source: GitHub repo
  • Root Directory: /apps/cpm
  • Watch Paths: /apps/cpm/**
  • Start Command: Auto-detected from railway.json

Environment variables:

SUPABASE_URL=your_supabase_url
SUPABASE_KEY=your_supabase_service_key
OPENAI_API_KEY=your_openai_key
ANTHROPIC_API_KEY=your_anthropic_key
GOOGLE_API_KEY=your_google_key
IM_SERVICE_URL=https://im.railway.app

3. Configure IM Service

  • Source: GitHub repo
  • Root Directory: /apps/im
  • Watch Paths: /apps/im/**
  • Similar environment variables

4. Configure Domains

Railway will provide URLs like: - CPM: cpm-production.up.railway.app - IM: im-production.up.railway.app

Local Development Workflow

1. Install Dependencies

# Install pnpm globally
npm install -g pnpm

# Install all dependencies
pnpm install

2. Setup Environment Variables

Create .env.local files:

apps/frontend/.env.local:

NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
CPM_SERVICE_URL=http://localhost:8000
IM_SERVICE_URL=http://localhost:8001

apps/cpm/.env:

SUPABASE_URL=your_supabase_url
SUPABASE_KEY=your_supabase_service_key
OPENAI_API_KEY=your_openai_key
IM_SERVICE_URL=http://localhost:8001
PORT=8000

apps/im/.env:

SUPABASE_URL=your_supabase_url
SUPABASE_KEY=your_supabase_service_key
OPENAI_API_KEY=your_openai_key
PORT=8001

3. Run Services

# Terminal 1: Frontend
cd apps/frontend
pnpm dev

# Terminal 2: CPM
cd apps/cpm
source .venv/bin/activate
uvicorn app:app --reload --port 8000

# Terminal 3: IM
cd apps/im
source .venv/bin/activate
uvicorn app:app --reload --port 8001

Or use Turborepo (requires additional setup):

pnpm dev

Deployment Process

Automatic Deployments

  1. Development: Push to feature branch → Preview deployments
  2. Production: Merge to main → Production deployments

Manual Deployments

# Deploy frontend to Vercel
cd apps/frontend
vercel --prod

# Deploy to Railway via CLI
railway link
railway up

Monitoring and Maintenance

1. Setup Monitoring

  • Vercel: Built-in analytics and monitoring
  • Railway: View logs and metrics in dashboard
  • Sentry: Add error tracking (optional)

2. Regular Updates

# Update dependencies
pnpm update

# Check for vulnerabilities
pnpm audit

# Update Python dependencies
cd apps/cpm && pip-compile --upgrade

3. Backup Strategy

  • GitHub: Automatic code backups
  • Supabase: Configure database backups
  • Environment variables: Store securely in password manager

Troubleshooting

Common Issues

  1. Vercel Build Failures
  2. Check Node version compatibility
  3. Verify environment variables
  4. Review build logs

  5. Railway Deployment Issues

  6. Check Python version in runtime.txt
  7. Verify requirements.txt syntax
  8. Review deployment logs

  9. Local Development

  10. Port conflicts: Change ports in .env files
  11. CORS issues: Configure Next.js API routes as proxy

Debug Commands

# Check workspace structure
pnpm ls --depth 0

# Verify turbo pipeline
turbo run build --dry-run

# Test individual services
cd apps/frontend && pnpm build
cd apps/cpm && python -m pytest

Security Best Practices

  1. Environment Variables
  2. Never commit .env files
  3. Use different keys for dev/prod
  4. Rotate keys regularly

  5. API Security

  6. Implement rate limiting
  7. Add authentication headers
  8. Validate all inputs

  9. Dependency Management

  10. Regular security updates
  11. Use lockfiles (pnpm-lock.yaml)
  12. Audit dependencies

V2 Enhancements

1. Shared Packages

# Create shared types package
mkdir -p packages/shared-types
cd packages/shared-types
pnpm init

2. Docker Support

Add docker-compose.yml for local development:

version: '3.8'
services:
  frontend:
    build: ./apps/frontend
    ports:
      - "3000:3000"
    environment:
      - CPM_SERVICE_URL=http://cpm:8000
      - IM_SERVICE_URL=http://im:8001

  cpm:
    build: ./apps/cpm
    ports:
      - "8000:8000"
    environment:
      - IM_SERVICE_URL=http://im:8001

  im:
    build: ./apps/im
    ports:
      - "8001:8001"

3. Advanced CI/CD

  • Add E2E tests with Playwright
  • Implement preview deployments for PRs
  • Add performance budgets

Cost Optimization

Estimated Costs (Monthly)

  • GitHub: Free for private repos
  • Vercel: Free tier (100GB bandwidth)
  • Railway: ~$5-20 (usage-based)
  • Total: ~$5-20/month for MVP

Cost Saving Tips

  1. Use Vercel's edge functions for light API calls
  2. Optimize Railway resource usage
  3. Implement caching strategies
  4. Monitor and optimize LLM API calls