"use client" import { Suspense } from "react" import { useSearchParams } from "next/navigation" import { GoogleDrive, Notion } from "@ui/assets/icons" import { cn } from "@lib/utils" import { dmSans125ClassName, dmSansClassName } from "@/lib/fonts" import { ArrowRight, Mail, MessageSquare, Plus, Sparkles } from "lucide-react" import { AnimatedGradientBackground } from "@/components/animated-gradient-background" import { Header } from "@/components/header" import { HomeChatComposer } from "@/components/chat/home-chat-composer" import { RecommendedRail, SourcesHealthRail, } from "@/components/brain-home/widgets" const modalCardStyle = { boxShadow: "0 2.842px 14.211px 0 rgba(0, 0, 0, 0.25), 0.711px 0.711px 0.711px 0 rgba(255, 255, 255, 0.10) inset", } const inputBevelStyle = { boxShadow: "0px 1px 2px 0px rgba(0,43,87,0.1), inset 0px 0px 0px 1px rgba(43,49,67,0.08), inset 0px 1px 1px 0px rgba(0,0,0,0.08), inset 0px 2px 4px 0px rgba(0,0,0,0.02)", } type Space = { id: string name: string icon: React.ReactNode itemCount: number lastSync: string } const _SPACES: Space[] = [ { id: "drive", name: "My Drive", icon: , itemCount: 287, lastSync: "2h ago", }, { id: "notion", name: "Company Notion", icon: , itemCount: 142, lastSync: "12m ago", }, { id: "gmail", name: "Gmail", icon: , itemCount: 1843, lastSync: "Just now", }, ] type Stat = { label: string value: string delta?: string deltaTint?: "up" | "down" | "neutral" } const STATS: Stat[] = [ { label: "Items ingested", value: "2,272", delta: "+148 this week", deltaTint: "up", }, { label: "Agent sessions", value: "184", delta: "+42 vs last wk", deltaTint: "up", }, { label: "Active contributors", value: "4", delta: "of 6 invited", deltaTint: "neutral", }, { label: "Top space", value: "Gmail", delta: "1,843 items", deltaTint: "neutral", }, ] type AgentSeries = { key: string label: string color: string } const AGENT_SERIES: AgentSeries[] = [ { key: "cursor", label: "Cursor", color: "#4BA0FA" }, { key: "claudeCode", label: "Claude Code", color: "#FF8A47" }, { key: "claudeDesktop", label: "Claude Desktop", color: "#B19CFF" }, { key: "chatgpt", label: "ChatGPT", color: "#10A37F" }, { key: "other", label: "Other", color: "#525D6E" }, ] const SESSIONS_BY_DAY: { label: string values: Record }[] = [ { label: "Mon", values: { cursor: 8, claudeCode: 4, claudeDesktop: 3, chatgpt: 2, other: 1, }, }, { label: "Tue", values: { cursor: 10, claudeCode: 6, claudeDesktop: 4, chatgpt: 3, other: 1, }, }, { label: "Wed", values: { cursor: 12, claudeCode: 9, claudeDesktop: 5, chatgpt: 4, other: 1, }, }, { label: "Thu", values: { cursor: 9, claudeCode: 5, claudeDesktop: 4, chatgpt: 3, other: 1, }, }, { label: "Fri", values: { cursor: 14, claudeCode: 10, claudeDesktop: 6, chatgpt: 4, other: 2, }, }, { label: "Sat", values: { cursor: 5, claudeCode: 3, claudeDesktop: 2, chatgpt: 1, other: 1, }, }, { label: "Sun", values: { cursor: 17, claudeCode: 12, claudeDesktop: 7, chatgpt: 4, other: 1, }, }, ] const RECENT_ANSWERS = [ { question: "What did we decide about pricing?", answer: "Pro stays at $20/mo. No overages, top-up only.", who: "You", when: "2h ago", }, { question: "What's blocking the Acme deal?", answer: "MSA review — Jane drafting a net-30 counter.", who: "You", when: "4h ago", }, { question: "Who owns the onboarding rewrite?", answer: "Design team. Ship target Friday.", who: "Sarah Kim", when: "Yesterday", }, ] const WEEKLY_DIGEST = { range: "Mon – Fri", headline: "Your brain captured 642 items, surfaced 12 decisions, and answered 184 questions across the team.", bullets: [ { label: "5 deadlines coming up next week", tint: "text-[#4BA0FA]", }, { label: "2 conflicts surfaced between Notion and Slack", tint: "text-[#FF8A47]", }, { label: "Sarah Kim led contributions with 14 docs", tint: "text-[#A1A1AA]", }, ], } const TEAM_THIS_WEEK = [ { name: "Sarah Kim", email: "sarah@acme.com", contributions: 14, summary: "14 docs · 3 spaces", color: "#FF8A47", }, { name: "Jane Doe", email: "jane@acme.com", contributions: 11, summary: "11 docs · 2 spaces", color: "#4BA0FA", }, { name: "Mahesh S.", email: "mahesh@acme.com", contributions: 9, summary: "9 docs · 1 space", color: "#A1A1AA", }, { name: "Alex Chen", email: "alex@acme.com", contributions: 7, summary: "7 docs · 2 spaces", color: "#10A37F", }, ] const TEAM_RECENT = [ { who: "Sarah Kim", what: "added a memo to acme-deal-q2", when: "14m" }, { who: "Jane Doe", what: "updated the Acme MSA draft", when: "1h" }, { who: "You", what: 'asked "What did we decide about pricing?"', when: "2h" }, { who: "Sarah Kim", what: "connected Notion to Sales space", when: "Yesterday", }, ] const ACTIVITY = [ { when: "2m", text: "23 new docs ingested from Drive", source: "drive", }, { when: "14m", text: "Jane added a memo to acme-deal-q2", source: "notion", }, { when: "1h", text: "Decision surfaced: pricing locked at $20 Pro", source: "slack", }, { when: "3h", text: "14 Notion pages updated by Sarah Kim", source: "notion", }, { when: "5h", text: "New entity formed: pricing-v3", source: "system", }, { when: "Yesterday", text: "MSA contract uploaded · auto-tagged contracts/MSA", source: "drive", }, ] const _RECENT_ITEMS: Record = { drive: [ { title: "Q2 Roadmap.docx", meta: "Edited 1h ago · Jane" }, { title: "Acme · MSA draft v3.pdf", meta: "Added 2h ago" }, { title: "Pricing model.xlsx", meta: "Edited 4h ago · Mahesh" }, { title: "Customer feedback Q1.docx", meta: "Yesterday" }, { title: "Brand assets / logos", meta: "2 days ago" }, ], notion: [ { title: "Engineering / Weekly sync", meta: "Updated 12m ago" }, { title: "Sales / Acme account", meta: "Updated 1h ago" }, { title: "Brand / Voice & tone", meta: "Yesterday" }, { title: "Onboarding rewrite spec", meta: "2 days ago" }, ], gmail: [ { title: "Re: Acme contract review", meta: "Just now · jane@acme.com" }, { title: "Customer feedback digest", meta: "10m ago" }, { title: "Re: Pricing decision", meta: "1h ago" }, { title: "Onboarding ship plan", meta: "3h ago" }, ], } export default function BrainHomePage() { return ( ) } function BrainHomeInner() { const searchParams = useSearchParams() const empty = searchParams?.get("empty") === "1" return (
{}} onOpenSearch={() => {}} />
{}} />
) } function StatsStrip({ stats, empty }: { stats: Stat[]; empty?: boolean }) { const EMPTY_STATS: Stat[] = [ { label: "Items ingested", value: "—", delta: "Connect a source", deltaTint: "neutral", }, { label: "Agent sessions", value: "—", delta: "Install an agent", deltaTint: "neutral", }, { label: "Active contributors", value: "1", delta: "Just you so far", deltaTint: "neutral", }, { label: "Top space", value: "—", delta: "Nothing connected", deltaTint: "neutral", }, ] const visible = empty ? EMPTY_STATS : stats return (
{visible.map((s) => (

{s.label}

{s.value}

{s.delta && (

{s.delta}

)}
))}
) } function BrainActivityChart({ empty }: { empty?: boolean }) { if (empty) { return (

Sessions by agent

0 sessions yet — once you install Cursor, Claude Code, or any MCP-capable agent, usage shows up here.

{["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"].map((d) => (
{d}
))}
) } const totalsByAgent = AGENT_SERIES.map((s) => ({ ...s, total: SESSIONS_BY_DAY.reduce((sum, d) => sum + (d.values[s.key] ?? 0), 0), })) const grandTotal = totalsByAgent.reduce((sum, s) => sum + s.total, 0) const dayTotals = SESSIONS_BY_DAY.map((d) => AGENT_SERIES.reduce((sum, s) => sum + (d.values[s.key] ?? 0), 0), ) const max = Math.max(...dayTotals) return (

Sessions by agent

{grandTotal} agent sessions, last 7 days — which tool the team reached for.

{totalsByAgent.map((s) => ( {s.label}{" "} {s.total} ))}
{SESSIONS_BY_DAY.map((d, dayIdx) => { const BAR_AREA_PX = 140 const totalForDay = dayTotals[dayIdx] ?? 0 const barHeightPx = Math.max( 6, Math.round((totalForDay / max) * BAR_AREA_PX), ) return (
{AGENT_SERIES.map((series, sIdx) => { const val = d.values[series.key] ?? 0 if (val === 0) return null const segHeight = totalForDay > 0 ? (val / totalForDay) * 100 : 0 return (
) })}
{d.label}
) })}
) } function _TabButton({ active, onClick, icon, label, count, }: { active: boolean onClick: () => void icon: React.ReactNode label: string count: number }) { return ( ) } function SectionHeader({ title, cta }: { title: string; cta?: string }) { return (

{title}

{cta && ( )}
) } function BrainPulseBlock({ empty }: { empty?: boolean }) { return (
) } function RecentAnswersCard({ empty }: { empty?: boolean }) { return (

Recent answers

{!empty && ( )}
{empty ? (

No questions asked yet.

Ask the brain something below — answers and the team's history will show up here.

) : (
    {RECENT_ANSWERS.map((a) => (
  • {a.question}

    → {a.answer}

    {a.who} · {a.when}

  • ))}
)}
) } function WeeklyDigestCard({ empty }: { empty?: boolean }) { if (empty) { return (

This week

Your brain is just getting started.

Once sources are connected and the team starts asking questions, you'll see decisions, deadlines, and contributor highlights here.

) } return (

This week

{WEEKLY_DIGEST.range}

{WEEKLY_DIGEST.headline.split(/(\d+)/).map((piece, i) => /^\d+$/.test(piece) ? ( {piece} ) : ( {piece} ), )}

    {WEEKLY_DIGEST.bullets.map((b) => (
  • {b.label}
  • ))}
) } function ActivityFeedBlock({ empty }: { empty?: boolean }) { if (empty) { return (

Nothing happening yet.

As sources sync and the team starts using the brain, every event will show up here in real time.

) } const sourceIcon = (s: string) => { if (s === "drive") return if (s === "notion") return if (s === "slack") return return } return (
{ACTIVITY.map((a, i) => (
{sourceIcon(a.source)}

{a.text}

{a.when}
))}
) } function TeamActivityRail({ empty }: { empty?: boolean }) { if (empty) { return (

Just you so far

A brain gets sharper as more people contribute. Invite teammates to see who's adding what.

) } return (

Team activity

This week

What your team's been adding to the brain.

{TEAM_THIS_WEEK.map((member) => (
{member.name[0]}

{member.name}

{member.summary}

{member.contributions}
))}

Recent

    {TEAM_RECENT.map((event, i) => (
  • {event.who} {event.what} · {event.when}
  • ))}
) }