- Add Turborepo scaffold templates (apps: product, website, admin, storybook; packages: ui, tokens, types, config) - Add ProjectRecord and AppRecord types to control plane - Add Gitea integration service (repo creation, scaffold push, webhooks) - Add Coolify integration service (project + per-app service provisioning with turbo --filter) - Add project routes: GET/POST /projects, GET /projects/:id/apps, POST /projects/:id/deploy - Update chat route to inject project/monorepo context into AI requests - Add deploy_app and scaffold_app tools to Gemini tool set - Update deploy executor with monorepo-aware /execute/deploy endpoint - Add TURBOREPO_MIGRATION_PLAN.md documenting rationale and scope Co-authored-by: Cursor <cursoragent@cursor.com>
230 lines
9.5 KiB
Markdown
230 lines
9.5 KiB
Markdown
# 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 separate Gitea repos per app (frontend repo, API repo, etc.), which fragments that context. The AI has to context-switch across repos, cross-repo dependencies are manual and brittle, and shared code has no clean home.
|
|
|
|
By adopting **Turborepo monorepo per project**, every project becomes a single repo containing all of its apps (`product`, `website`, `admin`) and shared packages (`ui`, `types`, `config`). The AI operates across the entire project simultaneously. Build orchestration, deployment, and shared code all become coherent automatically.
|
|
|
|
**The structure every project will have:**
|
|
|
|
```
|
|
{project-slug}/
|
|
apps/
|
|
product/ ← the core user-facing app
|
|
website/ ← marketing / landing site
|
|
admin/ ← internal admin tool
|
|
packages/
|
|
ui/ ← shared component library
|
|
types/ ← shared TypeScript types
|
|
config/ ← shared eslint, tsconfig
|
|
turbo.json
|
|
package.json ← workspace root (pnpm workspaces)
|
|
.gitignore
|
|
README.md
|
|
```
|
|
|
|
This is not a Vercel dependency. Turborepo is MIT-licensed, runs anywhere, and costs nothing. Remote caching is optional and can be self-hosted on Coolify.
|
|
|
|
---
|
|
|
|
## Scope of Changes
|
|
|
|
### 1. Project Scaffold Templates
|
|
|
|
**What:** Create a set of template files that get written into a new Gitea repo when a project is created.
|
|
|
|
**Files to create:** `platform/scripts/templates/turborepo/`
|
|
|
|
- `turbo.json` — pipeline config defining `build`, `dev`, `lint`, `test` tasks and their dependencies
|
|
- `package.json` — workspace root with pnpm workspaces pointing to `apps/*` and `packages/*`
|
|
- `.gitignore` — covering node_modules, dist, .turbo cache
|
|
- `apps/product/package.json` — Next.js app skeleton
|
|
- `apps/website/package.json` — Astro or Next.js skeleton
|
|
- `apps/admin/package.json` — Next.js app skeleton
|
|
- `packages/ui/package.json` — shared component library stub
|
|
- `packages/types/package.json` — shared types stub
|
|
- `packages/config/` — shared `tsconfig.json` and `eslint` base configs
|
|
|
|
**Notes:**
|
|
- Templates should be stack-agnostic at the shell level — the `turbo.json` pipeline is what matters, inner frameworks can vary
|
|
- Stack choices (Next.js vs Astro, etc.) can be parameterised later when we add a project creation wizard
|
|
|
|
---
|
|
|
|
### 2. Control Plane — Project Data Model Update
|
|
|
|
**What:** The current data model stores multiple Gitea repos per project. This changes to one repo per project.
|
|
|
|
**File:** `platform/backend/control-plane/src/types.ts`
|
|
|
|
**Changes:**
|
|
- Remove `repos: Array<{ gitea_repo, path }>` from `ProjectRecord` (or update it)
|
|
- Add `repo: string` — single Gitea repo URL for the project
|
|
- Add `apps: Array<{ name: string; path: string; coolify_service_uuid?: string }>` — tracks each app inside the monorepo and its Coolify service
|
|
- Add `turbo: { version: string }` — tracks which Turborepo version the project was scaffolded with
|
|
|
|
---
|
|
|
|
### 3. Control Plane — New Project Routes
|
|
|
|
**What:** Add project management endpoints to the control plane API.
|
|
|
|
**File to create:** `platform/backend/control-plane/src/routes/projects.ts`
|
|
|
|
**Endpoints:**
|
|
|
|
| Method | Path | Purpose |
|
|
|--------|------|---------|
|
|
| `POST` | `/projects` | Create project — scaffold Turborepo repo in Gitea, register in DB |
|
|
| `GET` | `/projects/:project_id` | Get project record |
|
|
| `GET` | `/projects/:project_id/apps` | List apps within the monorepo |
|
|
| `POST` | `/projects/:project_id/apps` | Add a new app to the monorepo |
|
|
| `POST` | `/projects/:project_id/deploy` | Trigger Turbo build + Coolify deploy for one or all apps |
|
|
|
|
**Project creation flow (`POST /projects`):**
|
|
1. Validate request (name, tenant_id, optional app selections)
|
|
2. Create Gitea repo via Gitea API
|
|
3. Scaffold Turborepo structure from templates, push initial commit
|
|
4. Register webhook: Gitea repo → control plane `/webhooks/gitea`
|
|
5. Create Coolify project
|
|
6. Create one Coolify service per app (with correct build filter)
|
|
7. Save project record to storage
|
|
8. Return project record with repo URL and app list
|
|
|
|
---
|
|
|
|
### 4. Control Plane — Storage Layer Updates
|
|
|
|
**What:** Add project storage operations alongside existing runs/tools storage.
|
|
|
|
**File to update:** `platform/backend/control-plane/src/storage/memory.ts`
|
|
**File to update:** `platform/backend/control-plane/src/storage/firestore.ts`
|
|
**File to update:** `platform/backend/control-plane/src/storage/index.ts`
|
|
|
|
**New operations to add:**
|
|
- `saveProject(project: ProjectRecord): Promise<void>`
|
|
- `getProject(projectId: string): Promise<ProjectRecord | null>`
|
|
- `listProjects(tenantId: string): Promise<ProjectRecord[]>`
|
|
- `updateProjectApp(projectId: string, app: AppRecord): Promise<void>`
|
|
|
|
---
|
|
|
|
### 5. Gitea Integration Service
|
|
|
|
**What:** New service to abstract all Gitea API calls. Currently there is no Gitea integration in the control plane.
|
|
|
|
**File to create:** `platform/backend/control-plane/src/gitea.ts`
|
|
|
|
**Responsibilities:**
|
|
- Create repo for a project
|
|
- Push initial scaffolded files (initial commit)
|
|
- Register webhooks
|
|
- Read file tree (so AI can understand the project structure)
|
|
- Read/write individual files (so AI can make edits)
|
|
|
|
**Config needed in `config.ts`:**
|
|
- `giteaUrl` — from `GITEA_URL` env var (e.g. `https://git.vibnai.com`)
|
|
- `giteaToken` — from `GITEA_TOKEN` env var (admin token for repo creation)
|
|
|
|
---
|
|
|
|
### 6. Coolify Integration Service
|
|
|
|
**What:** New service to abstract all Coolify API calls. Currently the deploy executor calls Coolify but there is no central integration.
|
|
|
|
**File to create:** `platform/backend/control-plane/src/coolify.ts`
|
|
|
|
**Responsibilities:**
|
|
- Create a Coolify project
|
|
- Create a Coolify application service linked to a Gitea repo
|
|
- Set the build command to `turbo run build --filter={app-name}`
|
|
- Set the publish directory per app
|
|
- Trigger a deployment
|
|
- Get deployment status
|
|
|
|
**Config needed in `config.ts`:**
|
|
- `coolifyUrl` — from `COOLIFY_URL` env var
|
|
- `coolifyToken` — from `COOLIFY_TOKEN` env var
|
|
|
|
---
|
|
|
|
### 7. Deploy Executor — Monorepo Awareness
|
|
|
|
**What:** The existing deploy executor (`platform/backend/executors/deploy`) currently deploys a single service. It needs to understand the monorepo structure and use `turbo run build --filter` to target the right app.
|
|
|
|
**File to update:** `platform/backend/executors/deploy/src/index.ts`
|
|
|
|
**Changes:**
|
|
- Accept `app_name` in the input payload (e.g. `"product"`, `"website"`, `"admin"`)
|
|
- Build command becomes `turbo run build --filter={app_name}` instead of `npm run build`
|
|
- Pass the root of the monorepo as the build context, not an app subdirectory
|
|
|
|
---
|
|
|
|
### 8. AI Context — Project-Aware Prompting
|
|
|
|
**What:** The Gemini chat integration currently has no awareness of which project the user is in. It needs project context so the AI can reason across the whole monorepo.
|
|
|
|
**File to update:** `platform/backend/control-plane/src/gemini.ts`
|
|
**File to update:** `platform/backend/control-plane/src/routes/chat.ts`
|
|
|
|
**Changes:**
|
|
- Add `project_id` to `ChatRequest`
|
|
- On chat requests with a `project_id`, fetch the project record and inject:
|
|
- Repo structure (app names, package names)
|
|
- Recent deployment status per app
|
|
- `turbo.json` pipeline config
|
|
- Add a new Gemini tool: `scaffold_app` — lets the AI add a new app to the user's monorepo
|
|
- Add a new Gemini tool: `deploy_app` — lets the AI trigger a Coolify deploy for a specific app by name
|
|
|
|
---
|
|
|
|
### 9. Theia Workspace — Single Repo Mode
|
|
|
|
**What:** The current Theia docker-compose opens a multi-root workspace across multiple repos. With one repo per project, this simplifies to a single workspace root.
|
|
|
|
**File to update:** `theia-docker-compose.yml` (and the Coolify service config for Theia)
|
|
|
|
**Changes:**
|
|
- Workspace path points to the cloned monorepo root
|
|
- Git remote is the project's single Gitea repo
|
|
- Theia extensions should be aware of the `turbo.json` to surface run targets in the UI (future)
|
|
|
|
---
|
|
|
|
### 10. Local Dev — Replace start-all.sh with Turbo
|
|
|
|
**What:** The current `platform/scripts/start-all.sh` manually starts each service with `&`. Once the platform itself is in a Turborepo, this can be replaced with `turbo run dev`.
|
|
|
|
**Note:** This is a nice-to-have follow-on. The priority is getting user project scaffolding right first. The platform's own internal structure can be migrated to Turborepo in a separate pass.
|
|
|
|
---
|
|
|
|
## Implementation Order
|
|
|
|
| Step | Task | Depends On |
|
|
|------|------|-----------|
|
|
| 1 | Create scaffold templates | Nothing |
|
|
| 2 | Add `ProjectRecord` type + storage ops | Step 1 |
|
|
| 3 | Build Gitea integration service | Step 2 |
|
|
| 4 | Build Coolify integration service | Step 2 |
|
|
| 5 | Add project routes to control plane | Steps 2, 3, 4 |
|
|
| 6 | Update deploy executor for monorepo | Step 5 |
|
|
| 7 | Update AI chat with project context | Step 5 |
|
|
| 8 | Update Theia workspace config | Step 5 |
|
|
| 9 | Migrate platform itself to Turborepo | All of the above |
|
|
|
|
---
|
|
|
|
## What Does Not Change
|
|
|
|
- Gitea as the source control host — same, just one repo per project instead of many
|
|
- Coolify as the deployment host — same, just configured with Turbo build filters
|
|
- Theia as the IDE — same, just opens one repo instead of multi-root
|
|
- The control plane API architecture (Fastify, in-memory/Firestore storage) — same, just extended
|
|
- Auth model — unchanged
|
|
- No Vercel dependency anywhere in this plan
|