This repository has been archived on 2026-06-07. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
master-ai/docs_archive/TURBOREPO_MIGRATION_PLAN.md

8.5 KiB

Turborepo Monorepo Per-Project Migration Plan

Why We Are Making This Change

The core thesis of this platform is that one AI controls everything in one project. For that to work, the AI needs a complete mental model of the project — all apps, all shared code, all dependencies — in a single coherent context.

The current architecture creates a single Gitea repo per project with no enforced internal structure. The AI has no reliable way to know where apps live, what shares code with what, or how to trigger a targeted build for one part of the project.

By adopting Turborepo monorepo per project, every project repo gets a standardised structure containing all of its apps (product, website, admin, storybook) and shared packages (ui, tokens, types, config). The AI operates across the entire project simultaneously. Build orchestration, deployment, and shared code all become coherent automatically.

The structure every user project repo will have:

{project-slug}/               ← one Gitea repo per project
  apps/
    product/                  ← core user-facing app (Next.js)
    website/                  ← marketing / landing site (Next.js)
    admin/                    ← internal admin tool (Next.js)
    storybook/                ← component browser and design system
  packages/
    ui/                       ← shared React component library
    tokens/                   ← design tokens (colors, spacing, typography)
    types/                    ← shared TypeScript types
    config/                   ← shared eslint, tsconfig
  turbo.json
  package.json                ← pnpm workspace root
  .gitignore
  README.md

Turborepo is MIT-licensed, runs anywhere, and costs nothing. No Vercel dependency.


Infrastructure Context

Everything runs on a single GCP VM (34.19.250.135, Montreal) via Docker + Traefik:

Service URL Repo
Platform frontend vibnai.com git.vibnai.com/mark/vibn-frontend
Gitea git.vibnai.com
Coolify coolify.vibnai.com
PostgreSQL internal

All platform logic lives in vibn-frontend (Next.js). There is no separate control plane service. The backend is Next.js API routes in app/api/. Storage is PostgreSQL via raw SQL queries (no ORM layer in use for project data).

Integrations that already exist and should not be replaced:

  • lib/gitea.ts — full Gitea API client (create repo, webhooks, signature verification)
  • lib/coolify.ts — full Coolify API client (projects, databases, applications, deployments)
  • app/api/projects/create/route.ts — project creation flow (creates Gitea repo)
  • app/api/webhooks/gitea/route.ts — receives Gitea push/PR events
  • app/api/webhooks/coolify/route.ts — receives Coolify deployment events
  • app/api/ai/chat/route.ts — AI chat with Gemini
  • lib/auth/authOptions.ts — NextAuth v4 with Prisma adapter

Scope of Changes

1. Scaffold Templates

What: A set of template files written into the user's Gitea repo when a project is created, giving every project the standard Turborepo monorepo structure.

Where: vibn-frontend/lib/scaffold/turborepo/

Files to create:

  • turbo.json — pipeline: build, dev, lint, type-check, test
  • package.json — pnpm workspace root pointing to apps/* and packages/*
  • .gitignore
  • README.md — project-specific (name injected at scaffold time)
  • apps/product/ — Next.js 15, references shared ui, tokens, types
  • apps/website/ — Next.js 15
  • apps/admin/ — Next.js 15
  • apps/storybook/ — Storybook 8
  • packages/ui/ — Button, Card, Input, Badge components using CSS token vars
  • packages/tokens/ — design tokens as TS + CSS custom properties
  • packages/types/ — shared User, ApiResponse, PaginatedResponse types
  • packages/config/tsconfig.base.json and eslint.config.js

Status: Templates were written and are ready. Need to be moved to vibn-frontend/lib/scaffold/turborepo/.


2. Project Creation Route — Add Scaffold Push

What: The existing app/api/projects/create/route.ts already creates a Gitea repo. It needs one additional step: push the Turborepo scaffold as the initial commit.

File to update: vibn-frontend/app/api/projects/create/route.ts

Current flow:

  1. Create Gitea repo (auto_init: true — creates empty repo with README)
  2. Register webhook
  3. Save project record to PostgreSQL

New step to add after repo creation:

  • Read scaffold template files from lib/scaffold/turborepo/
  • Replace {{project-slug}} and {{project-name}} placeholders
  • Push each file to the Gitea repo via the contents API
  • This replaces the default empty auto_init commit

Note: Change auto_init: true to auto_init: false since we are pushing the scaffold ourselves.


3. Project Data Model — Add App Tracking

What: The fs_projects table stores project data as a JSONB data column. The data object needs two new fields to track the monorepo apps and their Coolify services.

Fields to add to the project data JSONB:

apps: Array<{
  name: string;           // "product" | "website" | "admin" | "storybook"
  path: string;           // "apps/product"
  coolifyServiceUuid?: string;
  domain?: string;
}>
turboVersion: string;     // e.g. "2.3.3"

No schema migration needed — it's JSONB, just include these fields when inserting/updating.


4. Coolify — Per-App Service Provisioning

What: When a project is created, each app in the monorepo gets its own Coolify service with the correct Turbo build filter. This extends the existing lib/coolify.ts.

File to update: vibn-frontend/lib/coolify.ts

Add function:

createMonorepoAppService(opts: {
  projectUuid: string;
  appName: string;          // e.g. "product"
  gitRepo: string;          // the project's Gitea clone URL
  domain: string;           // e.g. "product-taskmaster.vibnai.com"
}): Promise<CoolifyApplication>

Build command: pnpm install && turbo run build --filter={appName}

Wire into project creation: After Gitea repo is created and scaffold is pushed, create one Coolify service per app and store the coolifyServiceUuid in the project's apps array.


5. Deploy API Route

What: A new API route that triggers a Coolify deployment for a specific app within a project.

File to create: vibn-frontend/app/api/projects/[projectId]/deploy/route.ts

POST /api/projects/{projectId}/deploy
Body: { app_name: "product" | "website" | "admin" | "storybook" }

Flow:

  1. Load project from PostgreSQL
  2. Find the app's coolifyServiceUuid
  3. Call deployApplication(uuid) from lib/coolify.ts
  4. Return deployment UUID

6. AI Chat — Project Context Injection

What: The existing app/api/ai/chat/route.ts handles Gemini chat. It needs to inject monorepo structure context when a projectId is present in the request.

File to update: vibn-frontend/app/api/ai/chat/route.ts

Add to chat request handling:

  • Accept optional projectId
  • When present, load the project from PostgreSQL
  • Inject into the system prompt:
    • Project name, slug, repo URL
    • List of apps and their domains
    • Shared packages available
    • Turbo version and build command pattern
  • Add two new Gemini tools:
    • deploy_app — triggers POST /api/projects/{projectId}/deploy
    • scaffold_app — adds a new app folder to the monorepo via Gitea contents API

Implementation Order

Step Task File Depends On
1 Move scaffold templates into vibn-frontend/lib/scaffold/ lib/scaffold/turborepo/**
2 Update project creation to push scaffold app/api/projects/create/route.ts Step 1
3 Add app tracking fields to project data app/api/projects/create/route.ts Step 2
4 Add createMonorepoAppService to Coolify lib lib/coolify.ts
5 Wire Coolify per-app provisioning into project creation app/api/projects/create/route.ts Steps 3, 4
6 Add deploy route app/api/projects/[projectId]/deploy/route.ts Step 4
7 Inject monorepo context into AI chat app/api/ai/chat/route.ts Step 3

What Does Not Change

  • Gitea as source control — same, one repo per project (already the case)
  • Coolify as deployment host — same, extended with per-app services
  • NextAuth for auth — unchanged
  • PostgreSQL + JSONB for project storage — unchanged
  • lib/gitea.ts and lib/coolify.ts — extended, not replaced
  • No Vercel dependency anywhere