diff --git a/app/api/projects/create/route.ts b/app/api/projects/create/route.ts index 0eed6236..97c2e907 100644 --- a/app/api/projects/create/route.ts +++ b/app/api/projects/create/route.ts @@ -3,8 +3,6 @@ import { authSession } from "@/lib/auth/session-server"; import { query } from '@/lib/db-postgres'; import { randomUUID } from 'crypto'; import { createRepo, createWebhook, getRepo, listWebhooks, GITEA_ADMIN_USER_EXPORT } from '@/lib/gitea'; -import { pushTurborepoScaffold } from '@/lib/scaffold'; -import { createMonorepoAppService } from '@/lib/coolify'; import { getOrCreateProvisionedWorkspace } from '@/lib/workspaces'; import { ensureProjectCoolifyProject } from '@/lib/projects'; import type { ProjectPhaseData, ProjectPhaseScores } from '@/lib/types/project-artifacts'; @@ -131,7 +129,10 @@ export async function POST(request: Request) { giteaSshUrl = repo.ssh_url; // If a GitHub repo was provided, mirror it as-is. - // Otherwise push the default Turborepo scaffold. + // Otherwise leave the repo empty — the user (or AI) decides what to + // put in it. The old turborepo auto-scaffold is no longer pushed + // because most projects don't need a 4-app monorepo and the AI + // can scaffold whatever the user actually wants on demand. if (githubRepoUrl) { const agentRunnerUrl = process.env.AGENT_RUNNER_URL ?? 'http://localhost:3333'; const mirrorRes = await fetch(`${agentRunnerUrl}/api/mirror`, { @@ -149,9 +150,6 @@ export async function POST(request: Request) { throw new Error(`GitHub mirror failed: ${detail}`); } console.log(`[API] GitHub repo mirrored to ${giteaRepo}`); - } else { - await pushTurborepoScaffold(repoOwner, repoName, slug, projectName); - console.log(`[API] Turborepo scaffold pushed to ${giteaRepo}`); } // Register webhook — skip if one already points to this project @@ -174,22 +172,18 @@ export async function POST(request: Request) { } // ────────────────────────────────────────────── - // 2. Provision per-app services under the workspace's Coolify Project + // 2. Provision a dedicated Coolify project for this Vibn project // ────────────────────────────────────────────── - const APP_BASE_DOMAIN = process.env.APP_BASE_DOMAIN ?? 'vibnai.com'; - const appNames = ['product', 'website', 'admin', 'storybook'] as const; - const provisionedApps: Array<{ - name: string; path: string; coolifyServiceUuid: string | null; domain: string | null; - }> = appNames.map(name => ({ name, path: `apps/${name}`, coolifyServiceUuid: null, domain: null })); - - // Each Vibn project gets its OWN Coolify Project under the workspace. - // Naming: `vibn-{workspace-slug}-{project-slug}`. Falls back to the - // workspace's legacy Coolify Project UUID if Coolify provisioning fails, - // so apps still deploy (with degraded isolation). + // Each Vibn project gets its OWN Coolify project named + // `vibn-{workspace-slug}-{project-slug}`. All apps/databases/services + // the user (or AI) deploys for this project will land inside it. // - // Note: ensureProjectCoolifyProject reads the row, but we INSERT the row - // further below. To break the chicken-and-egg we insert a minimal row - // first, then provision Coolify, then complete the row. + // We don't pre-create any services anymore — the project starts empty + // and the user/AI decides what to deploy via apps_create on demand. + // + // Note: ensureProjectCoolifyProject reads the fs_projects row, so we + // insert a minimal row first, then provision Coolify, then update the + // row with the full project data further below. await query( `INSERT INTO fs_projects (id, data, user_id, workspace, slug, vibn_workspace_id) VALUES ($1, '{}'::jsonb, $2, $3, $4, $5) @@ -202,27 +196,6 @@ export async function POST(request: Request) { { projectSlug: slug, projectName }, ); - if (giteaCloneUrl && coolifyProjectUuid) { - for (const app of provisionedApps) { - try { - const domain = `${app.name}-${slug}.${APP_BASE_DOMAIN}`; - const service = await createMonorepoAppService({ - projectUuid: coolifyProjectUuid, - appName: `${slug}-${app.name}`, // unique within the workspace's Coolify Project - gitRepo: giteaCloneUrl, - domain, - }); - app.coolifyServiceUuid = service.uuid; - app.domain = domain; - console.log(`[API] Coolify service created: ${app.name} → ${domain}`); - } catch (appErr) { - console.error(`[API] Coolify service failed for ${app.name}:`, appErr); - } - } - } else if (!coolifyProjectUuid) { - console.warn('[API] Workspace has no Coolify Project UUID — skipped app provisioning. Run /api/workspaces/{slug}/provision to retry.'); - } - // ────────────────────────────────────────────── // 3. Save project record // ────────────────────────────────────────────── @@ -263,11 +236,9 @@ export async function POST(request: Request) { giteaError, // Context snapshot (kept fresh by webhooks) contextSnapshot: null, - // Coolify project — one per VIBN project, scopes all app services + DBs + // Coolify project — one per VIBN project, scopes all app services + DBs. + // Apps are deployed on-demand via apps_create (no auto-scaffold). coolifyProjectUuid, - // Turborepo monorepo apps — each gets its own Coolify service - turboVersion: '2.3.3', - apps: provisionedApps, // Import metadata isImport: !!githubRepoUrl, importAnalysisStatus: githubRepoUrl ? 'pending' : null,