Files
vibn-frontend/components/project-main/MvpSetupDescribeView.tsx
Mark Henderson 651ddf1e11 Rip out Theia, ship P5.1 attach E2E + Justine UI work-in-progress
Theia rip-out:
- Delete app/api/theia-auth/route.ts (Traefik ForwardAuth shim)
- Delete app/api/projects/[projectId]/workspace/route.ts and
  app/api/projects/prewarm/route.ts (Cloud Run Theia provisioning)
- Delete lib/cloud-run-workspace.ts and lib/coolify-workspace.ts
- Strip provisionTheiaWorkspace + theiaWorkspaceUrl/theiaAppUuid/
  theiaError from app/api/projects/create/route.ts response
- Remove Theia callbackUrl branch in app/auth/page.tsx
- Drop "Open in Theia" button + xterm/Theia PTY copy in build/page.tsx
- Drop theiaWorkspaceUrl from deployment/page.tsx Project type
- Strip Theia IDE line + theia-code-os from advisor + agent-chat
  context strings
- Scrub Theia mention from lib/auth/workspace-auth.ts comment

P5.1 (custom apex domains + DNS):
- lib/coolify.ts + lib/opensrs.ts: nameserver normalization, OpenSRS
  XML auth, Cloud DNS plumbing
- scripts/smoke-attach-e2e.ts: full prod GCP + sandbox OpenSRS +
  prod Coolify smoke covering register/zone/A/NS/PATCH/cleanup

In-progress (Justine onboarding/build, MVP setup, agent telemetry):
- New (justine)/stories, project (home) layouts, mvp-setup, run, tasks
  routes + supporting components
- Project shell + sidebar + nav refactor for the Stackless palette
- Agent session API hardening (sessions, events, stream, approve,
  retry, stop) + atlas-chat, advisor, design-surfaces refresh
- New scripts/sync-db-url-from-coolify.mjs +
  scripts/prisma-db-push.mjs + docker-compose.local-db.yml for
  local Prisma workflows
- lib/dev-bypass.ts, lib/chat-context-refs.ts, lib/prd-sections.ts
- Misc: stories CSS, debug/prisma route, modal-theme, BuildLivePlanPanel

Made-with: Cursor
2026-04-22 18:05:01 -07:00

130 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { Suspense, useCallback, useEffect, useState } from "react";
import { JM, JV } from "@/components/project-creation/modal-theme";
import { AtlasChat } from "@/components/AtlasChat";
import {
BuildLivePlanPanel,
addSectionContextRef,
} from "@/components/project-main/BuildLivePlanPanel";
import {
type ChatContextRef,
contextRefKey,
} from "@/lib/chat-context-refs";
export function MvpSetupDescribeView({ projectId, workspace }: { projectId: string; workspace: string }) {
const [chatContextRefs, setChatContextRefs] = useState<ChatContextRef[]>([]);
const [tab, setTab] = useState<"chat" | "plan">("chat");
const [narrow, setNarrow] = useState(false);
useEffect(() => {
const mq = window.matchMedia("(max-width: 900px)");
const apply = () => setNarrow(mq.matches);
apply();
mq.addEventListener("change", apply);
return () => mq.removeEventListener("change", apply);
}, []);
const removeChatContextRef = useCallback((key: string) => {
setChatContextRefs(prev => prev.filter(r => contextRefKey(r) !== key));
}, []);
const addPlanSectionToChat = useCallback((label: string, phaseId: string | null) => {
setChatContextRefs(prev => addSectionContextRef(prev, label, phaseId));
}, []);
return (
<div style={{ flex: 1, display: "flex", flexDirection: "column", minHeight: 0, background: JV.chatColumnBg }}>
<div
style={{
padding: "18px 28px 14px",
background: "#fff",
borderBottom: `1px solid ${JM.border}`,
flexShrink: 0,
}}
>
<div style={{ fontSize: 17, fontWeight: 700, color: JM.ink, marginBottom: 3, fontFamily: JM.fontDisplay }}>
Describe
</div>
<div style={{ fontSize: 12.5, color: JM.muted }}>
Tell Vibn about your idea your plan fills in on the right as you go.
</div>
</div>
{narrow && (
<div
style={{
display: "flex",
borderBottom: `1px solid ${JM.border}`,
background: "#EEF0FF",
flexShrink: 0,
}}
>
{(["chat", "plan"] as const).map(id => (
<button
key={id}
type="button"
onClick={() => setTab(id)}
style={{
flex: 1,
padding: "11px 8px",
border: "none",
background: "transparent",
fontSize: 13,
fontWeight: tab === id ? 600 : 500,
color: tab === id ? JM.indigo : JM.muted,
borderBottom: tab === id ? `2px solid ${JM.indigo}` : "2px solid transparent",
cursor: "pointer",
fontFamily: JM.fontSans,
}}
>
{id === "chat" ? "Chat" : "Your plan"}
</button>
))}
</div>
)}
<div style={{ flex: 1, display: "flex", minHeight: 0, overflow: "hidden" }}>
<div
style={{
flex: 1,
minWidth: 0,
display: narrow && tab !== "chat" ? "none" : "flex",
flexDirection: "column",
}}
>
<AtlasChat
projectId={projectId}
conversationScope="overview"
contextEmptyLabel="Plan"
emptyStateHint="Answer Vibns questions — each phase you complete updates your plan."
chatContextRefs={chatContextRefs}
onRemoveChatContextRef={removeChatContextRef}
/>
</div>
<div
style={{
width: narrow ? undefined : 308,
flex: narrow && tab === "plan" ? 1 : undefined,
flexShrink: 0,
minWidth: 0,
display: narrow && tab !== "plan" ? "none" : "flex",
flexDirection: "column",
overflow: "hidden",
}}
>
<Suspense fallback={<div style={{ flex: 1, background: JV.prdPanelBg }} />}>
<BuildLivePlanPanel
projectId={projectId}
workspace={workspace}
chatContextRefs={chatContextRefs}
onAddSectionRef={addPlanSectionToChat}
compactHeader={narrow}
/>
</Suspense>
</div>
</div>
</div>
);
}