"use client"
import { Logo } from "@ui/assets/Logo"
import { useAuth } from "@lib/auth-context"
import {
Plus,
SearchIcon,
Settings,
Home,
Code2,
Sun,
ExternalLink,
MenuIcon,
MessageCircleIcon,
LifeBuoy,
LayoutGrid,
ChevronRight,
} from "lucide-react"
import { Button } from "@ui/components/button"
import { cn } from "@lib/utils"
import { dmSansClassName } from "@/lib/fonts"
import { getBillingSettingsUrl } from "@/lib/url-helpers"
import { GraphIcon, IntegrationsIcon } from "@/components/integration-icons"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@ui/components/dropdown-menu"
import { Tooltip, TooltipContent, TooltipTrigger } from "@ui/components/tooltip"
import { useProject } from "@/stores"
import Link from "next/link"
import { SpaceSelector } from "./space-selector"
import { useIsMobile } from "@hooks/use-mobile"
import { useLocalStorageUsername } from "@hooks/use-local-storage-username"
import { UserProfileMenu } from "@/components/user-profile-menu"
import { FeedbackModal } from "./feedback-modal"
import { useViewMode } from "@/lib/view-mode-context"
import { useQueryState } from "nuqs"
import { feedbackParam } from "@/lib/search-params"
import { useCustomer } from "autumn-js/react"
import { useTokenUsage } from "@/hooks/use-token-usage"
import { useOrgSummaries } from "@/hooks/use-org-summaries"
import { OrgPlanBadge, resolveOrgPlan } from "@/components/org-plan-badge"
import { useSettingsModal } from "@/components/settings/settings-modal"
import { useHasCompanyBrain } from "@/hooks/use-company-brain"
import { CompanyBrainHeader } from "@/components/company-brain-header"
interface HeaderProps {
onAddMemory?: () => void
onOpenSearch?: () => void
}
const brainItemClass = (active: boolean) =>
cn(
"gap-2.5 rounded-lg px-2 py-1.5 text-sm font-medium cursor-pointer transition-colors",
"hover:bg-white/[0.06] focus:bg-white/[0.06] focus:text-white",
active ? "bg-white/[0.06] text-white" : "text-white/85",
)
const brainTileClass = (active: boolean) =>
cn(
"flex size-7 shrink-0 items-center justify-center rounded-lg border text-[11px] font-semibold",
active
? "border-[#2261CA66] bg-[#0B2A57] text-[#7EB0FF]"
: "border-white/[0.08] bg-white/[0.04] text-white/70",
)
export function Header(props: HeaderProps) {
const hasCompanyBrain = useHasCompanyBrain()
if (hasCompanyBrain) {
return
}
return
}
function PersonalBrainHeader({ onAddMemory, onOpenSearch }: HeaderProps) {
const { user, isRestoring, org, organizations, setActiveOrg } = useAuth()
const autumn = useCustomer()
const { currentPlan } = useTokenUsage(autumn)
const { data: orgSummaries } = useOrgSummaries()
const planByOrgId = new Map(
(orgSummaries ?? []).map((s) => [s.orgId, s.plan] as const),
)
const { selectedProjects, setSelectedProjects } = useProject()
const { openSettings } = useSettingsModal()
const isMobile = useIsMobile()
const [feedbackOpen, setFeedbackOpen] = useQueryState(
"feedback",
feedbackParam,
)
const { viewMode, setViewMode } = useViewMode()
const billingSettingsUrl = getBillingSettingsUrl()
const handleFeedback = () => setFeedbackOpen(true)
const localStorageUsername = useLocalStorageUsername()
const displayName =
user?.displayUsername ||
(isRestoring ? localStorageUsername : "") ||
user?.name ||
user?.email?.split("@")[0] ||
""
const userName = displayName ? `${displayName.split(" ")[0]}'s` : "My"
const orgLabel = org?.name.replace(/\s*organizations?\s*$/i, "").trim()
const topLabel = orgLabel || userName
const hasOrgs = (organizations?.length ?? 0) > 0
const selectOrg = (slug: string, isActive: boolean) => {
if (isActive) return
void setActiveOrg(slug).then(() => window.location.reload())
}
return (
{hasOrgs && (
<>
Switch brain
{organizations?.map((o) => {
const active = org?.id === o.id
const plan = resolveOrgPlan(
o.id,
active,
currentPlan,
planByOrgId,
)
return (
selectOrg(o.slug, active)}
className={cn(brainItemClass(active))}
>
{o.name?.trim().charAt(0).toUpperCase() || "?"}
{o.name}
)
})}
>
)}
Home
Developer console
supermemory.ai
{!isMobile && (
<>
>
)}
{!isMobile && (
Home
{(
[
{
mode: "integrations" as const,
label: "Integrations",
icon: IntegrationsIcon,
},
{ mode: "graph" as const, label: "Graph", icon: GraphIcon },
{
mode: "list" as const,
label: "Memories",
icon: LayoutGrid,
},
] as const
).map(({ mode, label, icon: Icon }) => (
))}
Chat
)}
{isMobile ? (
<>
Upgrade
Add memory
void setViewMode("dashboard")}
className="gap-2.5 rounded-lg px-2.5 py-2 text-sm font-medium text-white/85 hover:bg-white/[0.06] focus:bg-white/[0.06] focus:text-white cursor-pointer"
>
Home
setViewMode("integrations")}
className="gap-2.5 rounded-lg px-2.5 py-2 text-sm font-medium text-white/85 hover:bg-white/[0.06] focus:bg-white/[0.06] focus:text-white cursor-pointer"
>
Integrations
void setViewMode("graph")}
className="gap-2.5 rounded-lg px-2.5 py-2 text-sm font-medium text-white/85 hover:bg-white/[0.06] focus:bg-white/[0.06] focus:text-white cursor-pointer"
>
Graph
onOpenSearch?.()}
className="gap-2.5 rounded-lg px-2.5 py-2 text-sm font-medium text-white/85 hover:bg-white/[0.06] focus:bg-white/[0.06] focus:text-white cursor-pointer"
>
Search
void setViewMode("list")}
className="gap-2.5 rounded-lg px-2.5 py-2 text-sm font-medium text-white/85 hover:bg-white/[0.06] focus:bg-white/[0.06] focus:text-white cursor-pointer"
>
Memories
void setViewMode("chat")}
className="gap-2.5 rounded-lg px-2.5 py-2 text-sm font-medium text-white/85 hover:bg-white/[0.06] focus:bg-white/[0.06] focus:text-white cursor-pointer"
>
Chat with Nova
Feedback
openSettings()}
className="gap-2.5 rounded-lg px-2.5 py-2 text-sm font-medium text-white/85 hover:bg-white/[0.06] focus:bg-white/[0.06] focus:text-white cursor-pointer"
>
Settings
>
) : (
<>
Upgrade
Add memory (C)
Search (⌘K)
>
)}
setFeedbackOpen(false)}
/>
)
}
export function PublicHeader({
variant = "default",
}: {
variant?: "default" | "integrations"
}) {
if (variant === "integrations") {
return (
supermemory
)
}
return (
Connect your tools, search everything.
)
}