diff --git a/vibn-frontend/app/[workspace]/project/[projectId]/(home)/overview/page.tsx b/vibn-frontend/app/[workspace]/project/[projectId]/(home)/overview/page.tsx
index ff1abb32..126d5cbc 100644
--- a/vibn-frontend/app/[workspace]/project/[projectId]/(home)/overview/page.tsx
+++ b/vibn-frontend/app/[workspace]/project/[projectId]/(home)/overview/page.tsx
@@ -1,378 +1,683 @@
"use client";
-import { useAnatomy } from "@/components/project/use-anatomy";
+import { useState } from "react";
import { useParams } from "next/navigation";
-import { ExternalLink, Copy, Users, EyeOff, LayoutGrid } from "lucide-react";
+import {
+ Loader2,
+ AlertCircle,
+ ExternalLink,
+ Globe,
+ RefreshCw,
+ CircleDot,
+ ChevronDown,
+ ChevronRight,
+ Copy,
+ Check,
+ Terminal,
+ Server,
+} from "lucide-react";
+import { useAnatomy, type Anatomy } from "@/components/project/use-anatomy";
-export default function OverviewPage() {
+/**
+ * Hosting tab — user-facing: "Is my thing live? How do I reach it?"
+ *
+ * One endpoint = one card. Each card shows:
+ * - Live URL (open in new tab)
+ * - Status dot + plain-language status
+ * - Redeploy button
+ * - Domain(s) list
+ * - Last build (time + status)
+ * - Expandable recent logs
+ *
+ * No master-detail split — with 1-3 services the overhead isn't worth it.
+ * Previews (dev server URLs) shown below in a secondary section.
+ */
+
+// ──────────────────────────────────────────────────
+// Types
+// ──────────────────────────────────────────────────
+
+type LiveItem = Anatomy["hosting"]["live"][number];
+type Preview = Anatomy["hosting"]["previews"][number];
+
+// ──────────────────────────────────────────────────
+// Main component
+// ──────────────────────────────────────────────────
+
+export default function OverviewTab() {
const params = useParams();
const projectId = params.projectId as string;
- const workspace = params.workspace as string;
- const { anatomy } = useAnatomy(projectId, { pollMs: 8000 });
-
- const activeProjectName = anatomy?.product?.codebases?.[0]?.label ?? "App";
-
- // Try to find the primary live URL
- const primaryLive = anatomy?.hosting?.live?.find((l) => !!l.fqdn);
- const displayUrl = primaryLive ? `https://${primaryLive.fqdn}` : null;
+ const { anatomy, loading, error } = useAnatomy(projectId, { pollMs: 8000 });
+ const showLoading = loading && !anatomy;
return (
-
- {/* Header card */}
-
-
-
-
-
-
-
- {activeProjectName}
-
-
- A comprehensive operating system for your users, integrating
- discovery, registration, operations, and growth automation into
- one unified platform.
-
-
- Created a few days ago
-
-
+
+ {showLoading && (
+
+
+
+ Loading…
+
+ )}
+ {error && !showLoading && (
+
+
+ {error}
+
+ )}
-
- {displayUrl ? (
-
- Open App
-
- ) : (
-
+ {anatomy && (
+ <>
+ {/* ── Live endpoints ── */}
+
+
+ {anatomy.hosting.live.length === 0 ? (
+ }
+ title="Nothing deployed yet"
+ hint="Ask the AI to deploy your app and it will appear here."
+ promptSuggestion="Deploy my app to production"
+ />
+ ) : (
+