diff --git a/packages/website/public/homepage-hero.png b/packages/website/public/homepage-hero.png new file mode 100644 index 000000000..6ab4ada9f Binary files /dev/null and b/packages/website/public/homepage-hero.png differ diff --git a/packages/website/src/components/hero-mockup.tsx b/packages/website/src/components/hero-mockup.tsx index 9545b3d57..f1a0733d3 100644 --- a/packages/website/src/components/hero-mockup.tsx +++ b/packages/website/src/components/hero-mockup.tsx @@ -1,1005 +1,15 @@ -import * as React from "react"; -import { motion } from "framer-motion"; -import { - FolderGit2, - Paperclip, - ArrowUp, - X, - MessagesSquare, - Plus, - Settings, - Monitor, - GitCommitHorizontal, - ChevronDown, - ChevronRight, - ListChevronsUpDown, - Bot, - Check, - Loader, - SquareTerminal, - PanelLeft, - Ellipsis, - Mic, - GitPullRequest, - SquarePen, - Columns2, - Rows2, -} from "lucide-react"; -import { ClaudeIcon, CodexIcon, SourceControlIcon } from "~/components/mockup"; - -const USER_BUBBLE_STYLE = { borderRadius: "16px 2px 16px 16px" }; -const NEW_BADGE_STYLE = { backgroundColor: "rgba(46, 160, 67, 0.2)" }; - -// ── Stagger timing ────────────────────────────────────── - -const D = { - shell: 0, - sidebar: 0.1, - titleBar: 0.15, - tabs: 0.25, - chat: 0.35, - diffPanel: 0.55, -}; - -function fade(delay: number) { - return { - initial: { opacity: 0, y: 8 } as const, - animate: { opacity: 1, y: 0 } as const, - transition: { duration: 0.5, delay, ease: "easeOut" as const }, - }; -} - -// ── Data ──────────────────────────────────────────────── - -type ChatItem = - | { type: "user"; text: string } - | { type: "text"; text: string; bold?: boolean } - | { type: "tool"; label: string; summary?: string; status: "running" | "done" }; - -const CHAT: ChatItem[] = [ - { type: "user", text: "Build me an internal dashboard for tracking customer returns" }, - { type: "text", text: "I'll break this down into planning and implementation.", bold: true }, - { type: "tool", label: "Run plan-technical", summary: "codex · plan-technical", status: "done" }, - { type: "tool", label: "Run plan-design", summary: "claude · plan-design", status: "done" }, - { - type: "tool", - label: "Wait for agents", - summary: "plan-technical plan-design", - status: "done", - }, - { type: "text", text: "Got the plans. Spinning up Codex for implementation.", bold: true }, - { type: "tool", label: "Run implement", summary: "codex · 12 files changed", status: "done" }, - { type: "text", text: "Implementation done. Requesting review from Claude." }, - { type: "tool", label: "Run review", summary: "claude · no issues found", status: "running" }, - { type: "text", text: "All tasks complete. Dashboard is ready.", bold: true }, -]; - -// ── Sidebar data ──────────────────────────────────────── - -interface SidebarWorkspace { - name: string; - kind: "checkout" | "worktree"; - status: "running" | "done" | "idle" | "syncing"; - selected?: boolean; - diffStat?: { additions: number; deletions: number }; - pr?: { number: number; state: "open" | "merged" | "closed" }; -} - -interface SidebarProject { - initial: string; - name: string; - workspaces: SidebarWorkspace[]; -} - -const SIDEBAR_PROJECTS: SidebarProject[] = [ - { - initial: "A", - name: "acme/returns-app", - workspaces: [ - { - name: "main", - kind: "checkout", - status: "syncing", - selected: true, - diffStat: { additions: 247, deletions: 15 }, - }, - { - name: "feat/dashboard", - kind: "worktree", - status: "done", - pr: { number: 142, state: "open" }, - }, - ], - }, - { - initial: "P", - name: "acme/payments", - workspaces: [ - { name: "main", kind: "checkout", status: "idle" }, - { - name: "fix/stripe-webhook", - kind: "worktree", - status: "done", - diffStat: { additions: 38, deletions: 4 }, - pr: { number: 89, state: "merged" }, - }, - ], - }, - { - initial: "I", - name: "acme/infra", - workspaces: [ - { name: "main", kind: "checkout", status: "idle" }, - { - name: "feat/k8s-autoscale", - kind: "worktree", - status: "syncing", - diffStat: { additions: 91, deletions: 3 }, - }, - ], - }, - { - initial: "D", - name: "acme/design-system", - workspaces: [{ name: "main", kind: "checkout", status: "idle" }], - }, -]; - -// ── Tab data ───────────────────────────────────────────── - -interface TabDef { - name: string; - provider: "claude" | "codex" | "terminal"; - done: boolean; - active?: boolean; -} - -const TABS: TabDef[] = [ - { name: "Orchestrator", provider: "claude", done: false, active: true }, - { name: "Implement", provider: "codex", done: true }, -]; - -// ── Diff data ────────────────────────────────────────── - -type DiffLineType = "add" | "remove" | "context" | "header"; -interface DiffLine { - type: DiffLineType; - ln: string | null; - content?: string; - tokens?: Array<{ text: string; cls: string }>; -} - -const DIFF_LINES: DiffLine[] = [ - { - type: "add", - ln: "1", - tokens: [ - { text: "import", cls: "text-syn-keyword" }, - { text: " { ", cls: "text-syn-punctuation" }, - { text: "useState", cls: "text-syn-variable" }, - { text: " } ", cls: "text-syn-punctuation" }, - { text: "from", cls: "text-syn-keyword" }, - { text: ' "react"', cls: "text-syn-string" }, - ], - }, - { - type: "add", - ln: "2", - tokens: [ - { text: "import", cls: "text-syn-keyword" }, - { text: " { ", cls: "text-syn-punctuation" }, - { text: "ReturnTable", cls: "text-syn-variable" }, - { text: " } ", cls: "text-syn-punctuation" }, - { text: "from", cls: "text-syn-keyword" }, - { text: ' "./components"', cls: "text-syn-string" }, - ], - }, - { type: "add", ln: "3", tokens: [] }, - { - type: "add", - ln: "4", - tokens: [ - { text: "export", cls: "text-syn-keyword" }, - { text: " function", cls: "text-syn-keyword" }, - { text: " Dashboard", cls: "text-syn-function" }, - { text: "() {", cls: "text-syn-punctuation" }, - ], - }, - { - type: "add", - ln: "5", - tokens: [ - { text: " const", cls: "text-syn-keyword" }, - { text: " [returns, setReturns]", cls: "text-syn-variable" }, - { text: " = ", cls: "text-syn-operator" }, - { text: "useState", cls: "text-syn-function" }, - { text: "([])", cls: "text-syn-punctuation" }, - ], - }, - { - type: "add", - ln: "6", - tokens: [ - { text: " const", cls: "text-syn-keyword" }, - { text: " [filter, setFilter]", cls: "text-syn-variable" }, - { text: " = ", cls: "text-syn-operator" }, - { text: "useState", cls: "text-syn-function" }, - { text: '("all")', cls: "text-syn-string" }, - ], - }, - { type: "add", ln: "7", tokens: [] }, - { - type: "add", - ln: "8", - tokens: [ - { text: " ", cls: "text-syn-punctuation" }, - { text: "return", cls: "text-syn-keyword" }, - { text: " (", cls: "text-syn-punctuation" }, - ], - }, - { - type: "add", - ln: "9", - tokens: [ - { text: " <", cls: "text-syn-punctuation" }, - { text: "main", cls: "text-syn-tag" }, - { text: " className", cls: "text-syn-property" }, - { text: '="', cls: "text-syn-punctuation" }, - { text: "min-h-screen p-8", cls: "text-syn-string" }, - { text: '">', cls: "text-syn-punctuation" }, - ], - }, - { - type: "add", - ln: "10", - tokens: [ - { text: " <", cls: "text-syn-punctuation" }, - { text: "h1", cls: "text-syn-tag" }, - { text: ">Customer Returns", cls: "text-syn-variable" }, - { text: "h1", cls: "text-syn-tag" }, - { text: ">", cls: "text-syn-punctuation" }, - ], - }, - { - type: "add", - ln: "11", - tokens: [ - { text: " <", cls: "text-syn-punctuation" }, - { text: "FilterBar", cls: "text-syn-tag" }, - { text: " value", cls: "text-syn-property" }, - { text: "={", cls: "text-syn-punctuation" }, - { text: "filter", cls: "text-syn-variable" }, - { text: "}", cls: "text-syn-punctuation" }, - { text: " onChange", cls: "text-syn-property" }, - { text: "={", cls: "text-syn-punctuation" }, - { text: "setFilter", cls: "text-syn-variable" }, - { text: "} />", cls: "text-syn-punctuation" }, - ], - }, - { - type: "add", - ln: "12", - tokens: [ - { text: " <", cls: "text-syn-punctuation" }, - { text: "ReturnTable", cls: "text-syn-tag" }, - { text: " data", cls: "text-syn-property" }, - { text: "={", cls: "text-syn-punctuation" }, - { text: "returns", cls: "text-syn-variable" }, - { text: "} />", cls: "text-syn-punctuation" }, - ], - }, - { - type: "add", - ln: "13", - tokens: [ - { text: " <", cls: "text-syn-punctuation" }, - { text: "StatusChart", cls: "text-syn-tag" }, - { text: " data", cls: "text-syn-property" }, - { text: "={", cls: "text-syn-punctuation" }, - { text: "returns", cls: "text-syn-variable" }, - { text: "} />", cls: "text-syn-punctuation" }, - ], - }, - { - type: "add", - ln: "14", - tokens: [ - { text: " ", cls: "text-syn-punctuation" }, - { text: "main", cls: "text-syn-tag" }, - { text: ">", cls: "text-syn-punctuation" }, - ], - }, - { type: "add", ln: "15", tokens: [{ text: " )", cls: "text-syn-punctuation" }] }, - { type: "add", ln: "16", tokens: [{ text: "}", cls: "text-syn-punctuation" }] }, -]; - -// ── Implementation agent chat data ────────────────────── - -// ── Terminal log lines ───────────────────────────────── - -const TERMINAL_LINES = [ - { id: "cmd", text: "$ npm run dev", cls: "text-mock-fg" }, - { id: "blank1", text: "", cls: "" }, - { id: "pkg", text: "> acme-returns@0.1.0 dev", cls: "text-mock-fg-muted" }, - { id: "pkg-cmd", text: "> next dev --turbopack", cls: "text-mock-fg-muted" }, - { id: "blank2", text: "", cls: "" }, - { id: "next-ver", text: " ▲ Next.js 15.3.1 (Turbopack)", cls: "text-mock-fg" }, - { id: "next-local", text: " - Local: http://localhost:3000", cls: "text-mock-fg-muted" }, - { id: "blank3", text: "", cls: "" }, - { id: "starting", text: " ✓ Starting...", cls: "text-mock-green" }, - { id: "ready", text: " ✓ Ready in 1.2s", cls: "text-mock-green" }, - { id: "compiling-dashboard", text: " ○ Compiling /dashboard ...", cls: "text-mock-fg-muted" }, - { id: "compiled-dashboard", text: " ✓ Compiled /dashboard in 340ms", cls: "text-mock-green" }, - { id: "compiling-api", text: " ○ Compiling /api/returns ...", cls: "text-mock-fg-muted" }, - { id: "compiled-api", text: " ✓ Compiled /api/returns in 120ms", cls: "text-mock-green" }, -]; - -// ── Sub-components ────────────────────────────────────── - -function TrafficLights() { - return ( -
- {line.ln ?? ""}
-
-
- {line.tokens?.map((tok) => (
-
- {tok.text}
-
- ))}
-
- - {item.text} -
- ); - })} -{line.text}
-
+