"use client"; import { useEffect, useState } from "react"; import { useParams } from "next/navigation"; import Link from "next/link"; interface App { name: string; type: string; description: string; tech: string[]; screens: string[]; } interface Package { name: string; description: string; } interface Infra { name: string; reason: string; } interface Integration { name: string; required: boolean; notes: string; } interface Architecture { productName: string; productType: string; summary: string; apps: App[]; packages: Package[]; infrastructure: Infra[]; integrations: Integration[]; designSurfaces: string[]; riskNotes: string[]; } function SectionLabel({ children }: { children: React.ReactNode }) { return (
{children}
); } function AppCard({ app }: { app: App }) { const [open, setOpen] = useState(false); const icons: Record = { web: "🌐", api: "⚡", simulator: "🎮", admin: "🔧", mobile: "📱", worker: "⚙️", engine: "🎯", }; const icon = Object.entries(icons).find(([k]) => app.name.toLowerCase().includes(k))?.[1] ?? "📦"; return (
{open && (
{app.tech.length > 0 && (
Stack
{app.tech.map((t, i) => ( {t} ))}
)} {app.screens.length > 0 && (
Key screens
{app.screens.map((s, i) => (
{s}
))}
)}
)}
); } export default function BuildPage() { const params = useParams(); const projectId = params.projectId as string; const workspace = params.workspace as string; const [prd, setPrd] = useState(null); const [architecture, setArchitecture] = useState(null); const [architectureConfirmed, setArchitectureConfirmed] = useState(false); const [loading, setLoading] = useState(true); const [generating, setGenerating] = useState(false); const [confirming, setConfirming] = useState(false); const [error, setError] = useState(null); useEffect(() => { fetch(`/api/projects/${projectId}/architecture`) .then(r => r.json()) .then(d => { setPrd(d.prd); setArchitecture(d.architecture ?? null); setLoading(false); }) .catch(() => setLoading(false)); // Also check confirmed flag fetch(`/api/projects/${projectId}`) .then(r => r.json()) .then(d => setArchitectureConfirmed(d.project?.architectureConfirmed === true)) .catch(() => {}); }, [projectId]); const handleGenerate = async (force = false) => { setGenerating(true); setError(null); try { const res = await fetch(`/api/projects/${projectId}/architecture`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ forceRegenerate: force }), }); const d = await res.json(); if (!res.ok) throw new Error(d.error || "Generation failed"); setArchitecture(d.architecture); } catch (e) { setError(e instanceof Error ? e.message : "Something went wrong"); } finally { setGenerating(false); } }; const handleConfirm = async () => { setConfirming(true); try { await fetch(`/api/projects/${projectId}/architecture`, { method: "PATCH" }); setArchitectureConfirmed(true); } catch { /* swallow */ } finally { setConfirming(false); } }; if (loading) { return (
Loading…
); } // No PRD yet if (!prd) { return (
🔒

Complete your PRD first

Finish your discovery conversation with Atlas, then the architect will unlock automatically.

Continue with Atlas →
); } // PRD exists but no architecture yet — prompt to generate if (!architecture) { return (
🏗️

Ready to architect {architecture ? (architecture as Architecture).productName : "your product"}

The AI will read your PRD and recommend the technical structure — apps, services, database, and integrations. You'll review it before anything gets built.

{error && (
{error}
)} {generating && (

This takes about 15–30 seconds

)}
); } // Architecture loaded — show full review UI return (
{/* Header */}

Architecture

{architecture.productType}

{architectureConfirmed && ( ✓ Confirmed )}
{/* Summary */}
{architecture.summary}
{/* Apps */} Apps — monorepo/apps/ {architecture.apps.map((app, i) => )} {/* Packages */} Shared packages — monorepo/packages/
{architecture.packages.map((pkg, i) => (
packages/{pkg.name}
{pkg.description}
))}
{/* Infrastructure */} {architecture.infrastructure.length > 0 && ( <> Infrastructure
{architecture.infrastructure.map((infra, i) => (
{infra.name} {infra.reason}
))}
)} {/* Integrations */} {architecture.integrations.length > 0 && ( <> External integrations
{architecture.integrations.map((intg, i) => (
{intg.required ? "required" : "optional"}
{intg.name}
{intg.notes}
))}
)} {/* Risk notes */} {architecture.riskNotes.length > 0 && ( <> Architecture risks
{architecture.riskNotes.map((risk, i) => (
⚠️{risk}
))}
)} {/* Confirm section */}
{architectureConfirmed ? (
✓ Architecture confirmed

You can still regenerate or adjust the architecture before scaffolding begins. Nothing has been built yet.

Choose your design →
) : (
Does this look right?

Review the structure above. You can regenerate if something's off, or confirm to move to design. You can always come back and adjust before the build starts — nothing gets scaffolded yet.

)}
); }