diff --git a/apps/web/app/(app)/brain/page.tsx b/apps/web/app/(app)/brain/page.tsx index 3a96950d..97dce105 100644 --- a/apps/web/app/(app)/brain/page.tsx +++ b/apps/web/app/(app)/brain/page.tsx @@ -5,24 +5,14 @@ import { useRouter } from "next/navigation" import { LogoFull } from "@ui/assets/Logo" import { Button } from "@ui/components/button" import { AlertTriangle, ChevronRight, Loader2, RotateCw } from "lucide-react" -import { authClient } from "@lib/auth" import { useAuth } from "@lib/auth-context" -import { SHARED_TEAM_BRAIN_TAG } from "@lib/constants" import { cn } from "@lib/utils" -import { analytics } from "@/lib/analytics" import { type BrainEntryOrganization, resolveCompanyBrainEntry, } from "@/lib/company-brain-entry" import { dmSans125ClassName, dmSansClassName } from "@/lib/fonts" -import { - detectModeFromEmail, - generateOrgSlug, - workspaceDomainFromEmail, - workspaceNameFromDomain, - workspaceNameFromEmail, - type BrainMetadata, -} from "@/components/onboarding-brain/types" +import { generateOrgSlug } from "@/components/onboarding-brain/types" const BACKEND = process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai" @@ -37,21 +27,13 @@ const inputBevelStyle = { "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)", } -// No forms: sign up → org auto-created → Slack install. -// After OAuth, mono attaches api_scale (14d trial) + company_brain (200 credits). export default function BrainEntryPage() { const router = useRouter() - const { - user, - org, - organizations, - isRestoring, - setActiveOrg, - refetchOrganizations, - } = useAuth() + const { user, org, organizations, isRestoring, setActiveOrg } = useAuth() const { email = null } = user ?? {} const [error, setError] = useState(null) const [choices, setChoices] = useState(null) + const [closed, setClosed] = useState(false) const [attempt, setAttempt] = useState(0) const startedRef = useRef(false) @@ -75,43 +57,6 @@ export default function BrainEntryPage() { [org?.id, router, setActiveOrg], ) - const createCompanyBrain = useCallback(async () => { - // Personal email → shell org; the Slack workspace resolves identity later. - const domain = - detectModeFromEmail(email) === "team" - ? workspaceDomainFromEmail(email) - : null - const name = - (domain - ? workspaceNameFromDomain(domain) - : workspaceNameFromEmail(email)) || "Company Brain" - const metadata: BrainMetadata & { signupSource: string } = { - signupSource: "consumer", - brainOnboardingVersion: "v1", - brainMode: "team", - brainWorkspaceName: name, - brainWorkspaceDomain: domain, - // Always the shared Team Brain; the CB UI never selects a slug space. - brainContainerTag: SHARED_TEAM_BRAIN_TAG, - } - const result = await authClient.organization.create({ - name, - slug: generateOrgSlug(name), - metadata, - }) - if (result.error || !result.data?.slug) { - throw new Error(result.error?.message || "Could not create workspace.") - } - await setActiveOrg(result.data.slug) - await refetchOrganizations() - analytics.onboardingWorkspaceCreated({ - mode: "team", - has_about: false, - has_domain: Boolean(domain), - }) - window.location.href = `${BACKEND}/brain/slack/oauth/install` - }, [email, refetchOrganizations, setActiveOrg]) - const run = useCallback(async () => { const organizationsWithActiveMetadata = (organizations ?? []).map( (organization) => @@ -132,8 +77,8 @@ export default function BrainEntryPage() { setChoices(decision.organizations) return } - await createCompanyBrain() - }, [continueWithOrganization, createCompanyBrain, org, organizations]) + setClosed(true) + }, [continueWithOrganization, org, organizations]) const handleChoice = useCallback( (organization: BrainEntryOrganization) => { @@ -164,7 +109,32 @@ export default function BrainEntryPage() { return ( - {choices ? ( + {closed ? ( +
+

+ New signups are paused +

+

+ Company Brain isn't accepting new workspaces right now. If you have + questions, reach us at support@supermemory.com. +

+ +
+ ) : choices ? (
(detectedMode) + + const hasCompanyBrainOrg = useMemo( + () => + (organizations ?? []).some((o) => + hasCompanyBrain( + (o as { metadata?: Record | string | null }) + .metadata, + ), + ), + [organizations], + ) + useEffect(() => { + if (mode === "team" && organizations != null && !hasCompanyBrainOrg) { + setMode("personal") + } + }, [mode, organizations, hasCompanyBrainOrg]) const [about, setAbout] = useState({ name: user?.name ?? "", about: "", @@ -280,12 +297,9 @@ export default function BrainOnboardingPage() { const metadata: BrainMetadata & { signupSource: string } = { signupSource: "consumer", brainOnboardingVersion: "v1", - brainMode: mode, + brainMode: "personal", brainWorkspaceName: name, - brainWorkspaceDomain: - mode === "team" - ? domainOverride || about.workspaceDomain || domain - : null, + brainWorkspaceDomain: null, brainContainerTag: containerTag, ...(about.about.trim() ? { brainAbout: about.about.trim() } : {}), } @@ -368,7 +382,7 @@ export default function BrainOnboardingPage() { setCreatingOrg(false) } }, [ensureOrg, goNext, forceCreate, organizations, router]) - const isCompanyBrain = mode === "team" + const isCompanyBrain = mode === "team" && hasCompanyBrainOrg const handleBrainConfirm = useCallback( async ( @@ -385,10 +399,17 @@ export default function BrainOnboardingPage() { workspaceDomain: confirmedDomain, workspaceName: workspaceName || a.workspaceName, })) - let orgCreated = false + const signupsPaused = () => { + toast.error("New Company Brain signups are paused", { + description: "Questions? Reach us at support@supermemory.com.", + }) + return { ok: false as const } + } + const orgCreated = false if (forceCreate) { - orgCreated = await ensureOrg(confirmedDomain, true) - } else if (organizationId) { + return signupsPaused() + } + if (organizationId) { const selected = organizations?.find( (organization) => organization.id === organizationId, ) @@ -418,7 +439,7 @@ export default function BrainOnboardingPage() { if (decision.action === "switch") { await setActiveOrg(decision.organization.slug) } else if (decision.action === "create") { - orgCreated = await ensureOrg(confirmedDomain, true) + return signupsPaused() } } // Re-entering onboarding on an existing org ("Try onboarding") must @@ -475,15 +496,7 @@ export default function BrainOnboardingPage() { setCreatingOrg(false) } }, - [ - ensureOrg, - forceCreate, - org, - organizations, - queryClient, - setActiveOrg, - router, - ], + [forceCreate, org, organizations, queryClient, setActiveOrg, router], ) const [sendingInvites, setSendingInvites] = useState(false) @@ -541,6 +554,10 @@ export default function BrainOnboardingPage() { const mcpUrl = "https://mcp.supermemory.ai/mcp" + if (mode === "team" && organizations == null) { + return null + } + if (isCompanyBrain) { return ( { - analytics.onboardingModeSelected({ mode: m }) - setMode(m) - }} domain={domain} suggestedWorkspaceName={suggestedWorkspaceName} defaultName={user?.name ?? ""} diff --git a/apps/web/components/app-experience.tsx b/apps/web/components/app-experience.tsx index 1ebdaa8a..f0d25daa 100644 --- a/apps/web/components/app-experience.tsx +++ b/apps/web/components/app-experience.tsx @@ -16,7 +16,6 @@ import { ChatSidebar, HomeChatComposer } from "@/components/chat" import type { ChatAttachmentDraft } from "@/components/chat/attachments" import { DashboardView } from "@/components/dashboard-view" import { BrainHomeView } from "@/components/brain-home/brain-home-view" -import { CompanyBrainPromo } from "@/components/company-brain-promo" import { useHasCompanyBrain } from "@/hooks/use-company-brain" import { MemoriesGrid } from "@/components/memories-grid" import { GraphLayoutView } from "@/components/graph-layout-view" @@ -830,7 +829,6 @@ export function AppExperience() { ) : ( } highlights={highlightsData?.highlights ?? []} isLoadingHighlights={isLoadingHighlights} onAddMemory={handleAddMemory} diff --git a/apps/web/components/brain-home/brain-home-view.tsx b/apps/web/components/brain-home/brain-home-view.tsx index 18e5b6f1..8aa3bc8b 100644 --- a/apps/web/components/brain-home/brain-home-view.tsx +++ b/apps/web/components/brain-home/brain-home-view.tsx @@ -8,8 +8,6 @@ import { ArrowRight, Check, FileText, Loader2, UserPlus } from "lucide-react" import { useQueryState } from "nuqs" import { useSettingsModal } from "@/components/settings/settings-modal" import { useBrainTrial } from "@/hooks/use-brain-trial" -import { TrialSetupBanner } from "@/components/trial-setup-banner" -import { BrainSetupModal } from "@/components/brain-setup-modal" import { useTrialStatus } from "@/hooks/use-trial-status" import { dmSans125ClassName } from "@/lib/fonts" import { useViewMode } from "@/lib/view-mode-context" @@ -17,7 +15,6 @@ import { AskInSlackCard, CONNECT_TOOLS_CARD_ID, ConnectToolsCard, - SlackBanner, useConnectionsBoard, } from "./connections-board" @@ -173,8 +170,6 @@ export function BrainHomeView() { const o = useBrainOverview() const trial = useBrainTrial() const board = useConnectionsBoard() - const { data: trialStatus } = useTrialStatus() - const { org: activeOrg } = useAuth() // Rows with no reported state (older orgs, pre-Slack) don't count or render. const milestones = [ ...(o.researchStatus != null ? [o.researchStatus === "done"] : []), @@ -186,16 +181,11 @@ export function BrainHomeView() { ] const milestonesDone = milestones.filter(Boolean).length const milestonesTotal = milestones.length - // Positive gate: a slow trial request would otherwise prompt an expired org. - const showSetupPrompt = Boolean( - board.slack && !board.slack.connected && trialStatus?.active, - ) const showTimeline = !o.loading && (trial.state !== "none" || milestonesDone < milestonesTotal) return (
- -
{board.showBoard && } @@ -227,7 +216,6 @@ export function BrainHomeView() {
- {showSetupPrompt && }
) } diff --git a/apps/web/components/brain-home/connections-board.tsx b/apps/web/components/brain-home/connections-board.tsx index 7124781a..b000a917 100644 --- a/apps/web/components/brain-home/connections-board.tsx +++ b/apps/web/components/brain-home/connections-board.tsx @@ -442,71 +442,3 @@ function TileSkeleton({ showDivider = false }: { showDivider?: boolean }) { ) } - -export function SlackBanner() { - const { needsSetup } = useTrialStatus() - return ( -
-
-
-
-
- -
-
-

- Slack agent - Company Brain in Slack -

-

- - Ask @supermemory from - any channel. - - - Install Supermemory so your team can{" "} - @supermemory in any - channel. - -

-
-
- - - {needsSetup ? ( - Start trial - ) : ( - <> - - Add - Add to Slack - - )} - -
-
- ) -} diff --git a/apps/web/components/brain-setup-modal.tsx b/apps/web/components/brain-setup-modal.tsx deleted file mode 100644 index f20a1816..00000000 --- a/apps/web/components/brain-setup-modal.tsx +++ /dev/null @@ -1,178 +0,0 @@ -"use client" - -import { Check } from "lucide-react" -import { useEffect, useState } from "react" -import { Dialog, DialogContent, DialogTitle } from "@ui/components/dialog" -import { cn } from "@lib/utils" -import { SlackMark } from "@/components/brain-connector-icons" -import { cardStyle, tileStyle } from "@/components/brain-home/connections-board" -import { analytics } from "@/lib/analytics" -import { COMPANY_BRAIN_CAL_HREF } from "@/lib/cal" -import { dmSans125ClassName, dmSansClassName } from "@/lib/fonts" - -const BACKEND = - process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai" -const dismissKey = (orgId: string) => `sm_brain_setup_modal_dismissed:${orgId}` - -const CALL_FEATURES = [ - "We install Slack with you, live", - "Connect Gmail, Notion, Linear and the rest", - "Wire up plugins and answer your questions", -] - -export function BrainSetupModal({ - enabled, - orgId, -}: { - enabled: boolean - orgId: string | undefined -}) { - const [open, setOpen] = useState(false) - - useEffect(() => { - // Also closes if the org stops being eligible while the dialog is open. - if (!enabled || !orgId) { - setOpen(false) - return - } - let dismissed = false - try { - dismissed = localStorage.getItem(dismissKey(orgId)) === "1" - } catch {} - if (dismissed) return - setOpen(true) - analytics.brainSetupModalSeen() - }, [enabled, orgId]) - - const close = () => { - setOpen(false) - if (!orgId) return - try { - localStorage.setItem(dismissKey(orgId), "1") - } catch {} - } - - return ( - !next && close()}> - - Get set up - -
-

- Get set up -

-

- Your brain is ready. Let's get it working where your team is. -

-
- - - - - - -
-
- ) -} diff --git a/apps/web/components/company-brain-header.tsx b/apps/web/components/company-brain-header.tsx index 07c8215b..287272b1 100644 --- a/apps/web/components/company-brain-header.tsx +++ b/apps/web/components/company-brain-header.tsx @@ -462,7 +462,7 @@ export function CompanyBrainHeader({ Integrations - {slackConnected ? ( + {slackConnected && ( Slack connected - ) : ( - - - - Add to Slack - - )} {canInvite && ( @@ -582,28 +575,9 @@ function SlackNavButton({ active: boolean onManage: () => void }) { - const label = connected - ? `Slack${teamName ? ` · ${teamName}` : ""}` - : "Add to Slack" + const label = `Slack${teamName ? ` · ${teamName}` : ""}` - if (!connected) { - return ( - - - - - - - - Add to Slack - - - ) - } + if (!connected) return null return ( diff --git a/apps/web/components/company-brain-promo.tsx b/apps/web/components/company-brain-promo.tsx deleted file mode 100644 index 3bda29a8..00000000 --- a/apps/web/components/company-brain-promo.tsx +++ /dev/null @@ -1,91 +0,0 @@ -"use client" - -import { useEffect, useState } from "react" -import { useRouter } from "next/navigation" -import { ArrowRight, XIcon } from "lucide-react" -import { Logo } from "@ui/assets/Logo" -import { Button } from "@repo/ui/components/button" -import { cn } from "@lib/utils" -import { analytics } from "@/lib/analytics" -import { dmSansClassName } from "@/lib/fonts" -import { useHasCompanyBrain } from "@/hooks/use-company-brain" - -const DISMISS_KEY = "supermemory-company-brain-promo-dismissed-v1" - -export function CompanyBrainPromo() { - const router = useRouter() - const hasCompanyBrain = useHasCompanyBrain() - const [dismissed, setDismissed] = useState(true) - - useEffect(() => { - if (hasCompanyBrain) return - try { - setDismissed(localStorage.getItem(DISMISS_KEY) === "1") - } catch { - setDismissed(false) - } - }, [hasCompanyBrain]) - - const visible = !hasCompanyBrain && !dismissed - - useEffect(() => { - if (visible) analytics.companyBrainPromoSeen() - }, [visible]) - - if (!visible) return null - - const dismiss = () => { - setDismissed(true) - try { - localStorage.setItem(DISMISS_KEY, "1") - } catch {} - analytics.companyBrainPromoDismissed() - } - - return ( -
-
- -
-
-
-

- Give your team a Company Brain -

-

- Lives in your Slack. Answers from your team's tools, and brings - things up before you ask. -

-
- -
- -
- ) -} diff --git a/apps/web/components/dashboard-view.tsx b/apps/web/components/dashboard-view.tsx index 12c76a86..d6a344a7 100644 --- a/apps/web/components/dashboard-view.tsx +++ b/apps/web/components/dashboard-view.tsx @@ -31,8 +31,6 @@ import { import { StaticGraphPreview } from "@/components/memory-graph/graph-card" import { Tooltip, TooltipContent, TooltipTrigger } from "@ui/components/tooltip" import { ChromeIcon, RaycastIcon } from "@/components/integration-icons" -import { SlackConnectCard } from "@/components/slack-connect-card" -import { TrialSetupBanner } from "@/components/trial-setup-banner" import { GoogleDrive, Notion, MCPIcon } from "@ui/assets/icons" import { analytics } from "@/lib/analytics" import type { IntegrationParamValue } from "@/lib/search-params" @@ -1345,8 +1343,6 @@ export function DashboardView({ )} >
- - {headerNotice ?
{headerNotice}
: null} {/* Header */} diff --git a/apps/web/components/onboarding-brain/step-about.tsx b/apps/web/components/onboarding-brain/step-about.tsx index e7ea8648..eb4a3c27 100644 --- a/apps/web/components/onboarding-brain/step-about.tsx +++ b/apps/web/components/onboarding-brain/step-about.tsx @@ -33,7 +33,6 @@ export interface AboutValues { interface Props { mode: BrainMode - onModeChange: (m: BrainMode) => void domain: string | null suggestedWorkspaceName: string defaultName: string @@ -60,7 +59,6 @@ export const inputClass = export function StepAbout({ mode, - onModeChange, domain, suggestedWorkspaceName, defaultName, @@ -165,9 +163,7 @@ export function StepAbout({ className="rounded-[22px] bg-[#1B1F24] p-6 md:p-8" style={cardSurfaceStyle} > - - -
+
void -}) { - const items: { id: BrainMode; label: string }[] = [ - { id: "personal", label: "Personal" }, - { id: "team", label: "Team" }, - ] - return ( -
- - {items.map((item) => { - const isActive = mode === item.id - return ( - - ) - })} -
- ) -} - export function UserAvatar({ url, name, diff --git a/apps/web/components/onboarding-brain/step-trial.tsx b/apps/web/components/onboarding-brain/step-trial.tsx index 5dd1ce64..df956ab5 100644 --- a/apps/web/components/onboarding-brain/step-trial.tsx +++ b/apps/web/components/onboarding-brain/step-trial.tsx @@ -2,36 +2,12 @@ import { Gmail, GoogleDrive, Granola, MCPIcon, Notion } from "@ui/assets/icons" import { GradientLogo } from "@ui/assets/Logo" -import { Button } from "@ui/components/button" import { cn } from "@lib/utils" -import { ArrowRight, Loader2, ShieldCheck } from "lucide-react" -import { useState } from "react" -import { toast } from "sonner" import { SlackMark } from "@/components/brain-connector-icons" -import { analytics } from "@/lib/analytics" import { dmSans125ClassName } from "@/lib/fonts" -const BACKEND = - process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai" - export const CHECKOUT_RETURN_PARAM = "brainTrial" -const TRIAL_DAYS = 14 -/** The only reminder that lands before the charge; 15 and 17 are post-trial. */ -const REMINDER_DAY = 12 -const MONTHLY_PRICE = "$100" - -function checkoutReturnUrl(): string { - const url = new URL(window.location.href) - url.searchParams.set(CHECKOUT_RETURN_PARAM, "complete") - return url.toString() -} - -function dayOffset(days: number): string { - const at = new Date(Date.now() + days * 24 * 60 * 60 * 1000) - return at.toLocaleDateString(undefined, { month: "short", day: "numeric" }) -} - const ORBIT = [ { key: "slack", r: 74, deg: 0, node: }, { key: "gmail", r: 74, deg: 128, node: }, @@ -85,91 +61,11 @@ function BrainPanel() { ) } -function TimelineRow({ - date, - title, - value, - current, -}: { - date: string - title: string - value?: string - current?: boolean -}) { - return ( -
  • -
  • - ) -} - -export function StepTrial({ onActive }: { onActive: () => void }) { - const [starting, setStarting] = useState(false) - - const start = async () => { - if (starting) return - setStarting(true) - analytics.brainTrialCheckoutStarted() - try { - const res = await fetch(`${BACKEND}/brain/trial/start`, { - method: "POST", - credentials: "include", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ successUrl: checkoutReturnUrl() }), - }) - const data = (await res.json()) as { - checkoutUrl?: string | null - status?: string - error?: string - } - if (res.status === 409 || data.error === "trial_unavailable") { - throw new Error( - "This workspace has already used its free trial. Upgrade from billing to continue.", - ) - } - if (!res.ok) throw new Error(data.error ?? "Couldn't start the trial.") - if (data.checkoutUrl) { - window.location.href = data.checkoutUrl - return - } - if (data.status === "already_active" || data.status === "attached") { - onActive() - return - } - throw new Error("Couldn't start the trial.") - } catch (error) { - console.error("Failed to start trial:", error) - toast.error( - error instanceof Error ? error.message : "Couldn't start the trial.", - ) - setStarting(false) - } - } - +// Trial checkout is disabled while new Company Brain signups are paused. +export function StepTrial(_props: { onActive: () => void }) { return (
    -
    +

    void }) { "text-[22px] leading-tight font-medium text-[#fafafa]", )} > - Start your {TRIAL_DAYS}-day free trial + New signups are paused

    - Add a payment method to start. You will not be charged today. We - will email you before your first payment. -

    -
    - -
      -
    - -
    - -

    - - Secured by Stripe · Cancel in one click + Company Brain isn't accepting new workspaces right now. If you have + questions, reach us at support@supermemory.com.

    diff --git a/apps/web/components/slack-connect-card.tsx b/apps/web/components/slack-connect-card.tsx deleted file mode 100644 index 03cb8e29..00000000 --- a/apps/web/components/slack-connect-card.tsx +++ /dev/null @@ -1,120 +0,0 @@ -"use client" - -import { useEffect, useState } from "react" -import { useHasCompanyBrain } from "@/hooks/use-company-brain" - -const BACKEND = - process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai" - -type SlackStatus = { connected: boolean; teamName: string | null } - -function SlackMark({ className }: { className?: string }) { - return ( - - ) -} - -export function SlackConnectCard() { - const isCompanyBrain = useHasCompanyBrain() - const [status, setStatus] = useState(null) - const [trialActive, setTrialActive] = useState(true) - const [loading, setLoading] = useState(true) - - useEffect(() => { - if (!isCompanyBrain) return - let active = true - ;(async () => { - try { - const [slackRes, trialRes] = await Promise.all([ - fetch(`${BACKEND}/brain/slack/status`, { credentials: "include" }), - fetch(`${BACKEND}/brain/trial/status`, { credentials: "include" }), - ]) - if (!active) return - if (slackRes.ok) setStatus((await slackRes.json()) as SlackStatus) - if (trialRes.ok) { - const trial = (await trialRes.json()) as { active?: boolean } - setTrialActive(Boolean(trial.active)) - } - } finally { - if (active) setLoading(false) - } - })() - return () => { - active = false - } - }, [isCompanyBrain]) - - if (!isCompanyBrain || loading) return null - - const connected = status?.connected - - return ( -
    -
    -

    - Add Supermemory to your Slack -

    -

    - {connected - ? `Connected to ${status?.teamName ?? "your workspace"}.` - : "Answer from your company brain and act on connected apps — right inside Slack."} -

    -
    - {connected ? ( - - - Connected - - ) : trialActive ? ( - - - Add to Slack - - ) : ( - - Finish setting up - - )} -
    - ) -} diff --git a/apps/web/components/trial-setup-banner.tsx b/apps/web/components/trial-setup-banner.tsx deleted file mode 100644 index b96e5c38..00000000 --- a/apps/web/components/trial-setup-banner.tsx +++ /dev/null @@ -1,41 +0,0 @@ -"use client" - -import { ArrowRight, CreditCard } from "lucide-react" -import Link from "next/link" -import { useTrialStatus } from "@/hooks/use-trial-status" - -export function TrialSetupBanner() { - const { needsSetup, data } = useTrialStatus() - if (!needsSetup) return null - - const endedTrial = data?.reason === "trial_ended" - - return ( -
    -
    - - - -
    -

    - {endedTrial - ? "Your Company Brain trial has ended" - : "Finish setting up Company Brain"} -

    -

    - {endedTrial - ? "Move to Max or Scale to switch the brain back on." - : "Add a card to start your 14-day trial. $0 today."} -

    -
    -
    - - {endedTrial ? "Upgrade" : "Add card"} - - -
    - ) -} diff --git a/apps/web/components/user-profile-menu.tsx b/apps/web/components/user-profile-menu.tsx index fc43255d..f14eba41 100644 --- a/apps/web/components/user-profile-menu.tsx +++ b/apps/web/components/user-profile-menu.tsx @@ -13,7 +13,6 @@ import { import { authClient } from "@lib/auth" import { useRouter } from "next/navigation" import { - Brain, CalendarClock, LogOut, Settings, @@ -168,18 +167,6 @@ export function UserProfileMenu({ Settings - {isCompanyBrain ? null : ( - { - analytics.companyBrainPromoClicked({ source: "profile_menu" }) - router.push("/onboarding?new=1&mode=team") - }} - 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" - > - - Set up Company Brain - - )} {isCompanyBrain ? ( void setViewMode("configure")} diff --git a/apps/web/lib/company-brain-entry.ts b/apps/web/lib/company-brain-entry.ts index 5e0d516e..4427961a 100644 --- a/apps/web/lib/company-brain-entry.ts +++ b/apps/web/lib/company-brain-entry.ts @@ -1,4 +1,4 @@ -import { getBrainWorkspaceDomain, isCompanyBrainOrg } from "./billing-utils" +import { getBrainWorkspaceDomain, hasCompanyBrain } from "./billing-utils" export type BrainEntryOrganization = { id: string @@ -13,11 +13,12 @@ export type CompanyBrainEntryDecision = | { action: "choose"; organizations: BrainEntryOrganization[] } | { action: "create" } +// Paid add-on or concierge override only; never-activated shell orgs fall to "create". export function getCompanyBrainOrganizations( organizations: BrainEntryOrganization[], ): BrainEntryOrganization[] { return organizations.filter((organization) => - isCompanyBrainOrg(organization.metadata), + hasCompanyBrain(organization.metadata), ) }