diff options
| author | MaheshtheDev <[email protected]> | 2026-01-25 01:04:15 +0000 |
|---|---|---|
| committer | MaheshtheDev <[email protected]> | 2026-01-25 01:04:15 +0000 |
| commit | 6834bc687609ec28aff0280df367f5bec6d0e275 (patch) | |
| tree | 6dac32e6551cb2ea580df784decadad9aebd91c8 /apps/web/app | |
| parent | feat: added advanced analytics events (#702) (diff) | |
| download | supermemory-6834bc687609ec28aff0280df367f5bec6d0e275.tar.xz supermemory-6834bc687609ec28aff0280df367f5bec6d0e275.zip | |
feat: onboarding config, reset onboarding, xai agentic migration (#701)01-24-feat_onboarding_config_reset_onboarding_xai_agentic_migration
- Created a new `useOrgOnboarding` hook that uses `org.metadata.isOnboarded` to track onboarding state
- Updated the home page to conditionally use either the old localStorage-based onboarding or the new DB-backed onboarding based on feature flag
- Added a "Restart Onboarding" option in the user dropdown menu
- Improved the onboarding chat sidebar with per-link loading indicators
- Enhanced the X/Twitter research API to better handle different URL formats
- Updated the integrations step to use the new onboarding completion method
- Added `updateOrgMetadata` function to the auth context for easier metadata updates
Diffstat (limited to 'apps/web/app')
| -rw-r--r-- | apps/web/app/(navigation)/page.tsx | 41 | ||||
| -rw-r--r-- | apps/web/app/api/onboarding/research/route.ts | 57 |
2 files changed, 57 insertions, 41 deletions
diff --git a/apps/web/app/(navigation)/page.tsx b/apps/web/app/(navigation)/page.tsx index 73da4f3c..39b6f47c 100644 --- a/apps/web/app/(navigation)/page.tsx +++ b/apps/web/app/(navigation)/page.tsx @@ -1,10 +1,11 @@ "use client" import { useOnboardingStorage } from "@hooks/use-onboarding-storage" +import { useOrgOnboarding } from "@hooks/use-org-onboarding" import { useAuth } from "@lib/auth-context" import { ChevronsDown, LoaderIcon } from "lucide-react" import { useRouter } from "next/navigation" -import { useEffect } from "react" +import { useEffect, useMemo } from "react" import { InstallPrompt } from "@/components/install-prompt" import { ChromeExtensionButton } from "@/components/chrome-extension-button" import { ChatInput } from "@/components/chat-input" @@ -14,11 +15,37 @@ import { useFeatureFlagEnabled } from "posthog-js/react" export default function Page() { const { user, session } = useAuth() - const { shouldShowOnboarding, isLoading: onboardingLoading } = - useOnboardingStorage() const router = useRouter() const flagEnabled = useFeatureFlagEnabled("nova-alpha-access") + // TODO: remove this flow after the feature flag is removed + // Old app: localStorage-backed onboarding + const { + shouldShowOnboarding: shouldShowOldOnboarding, + isLoading: oldOnboardingLoading, + } = useOnboardingStorage() + + // New app: DB-backed onboarding (org.metadata.isOnboarded) + const { + shouldShowOnboarding: shouldShowNewOnboarding, + isLoading: newOnboardingLoading, + } = useOrgOnboarding() + + // Select the appropriate onboarding state based on feature flag + const isOnboardingLoading = useMemo(() => { + if (flagEnabled) { + return newOnboardingLoading + } + return oldOnboardingLoading + }, [flagEnabled, newOnboardingLoading, oldOnboardingLoading]) + + const shouldShowOnboarding = useMemo(() => { + if (flagEnabled) { + return shouldShowNewOnboarding() + } + return shouldShowOldOnboarding() + }, [flagEnabled, shouldShowNewOnboarding, shouldShowOldOnboarding]) + useEffect(() => { const url = new URL(window.location.href) const authenticateChromeExtension = url.searchParams.get( @@ -46,16 +73,16 @@ export default function Page() { }, [user, session]) useEffect(() => { - if (user && !onboardingLoading && shouldShowOnboarding()) { + if (user && !isOnboardingLoading && shouldShowOnboarding) { if (flagEnabled) { router.push("/new/onboarding?step=input&flow=welcome") } else { router.push("/onboarding") } } - }, [user, shouldShowOnboarding, onboardingLoading, router, flagEnabled]) + }, [user, shouldShowOnboarding, isOnboardingLoading, router, flagEnabled]) - if (!user || onboardingLoading) { + if (!user || isOnboardingLoading) { return ( <div className="min-h-screen flex items-center justify-center bg-[#0f1419]"> <div className="flex flex-col items-center gap-4"> @@ -66,7 +93,7 @@ export default function Page() { ) } - if (shouldShowOnboarding()) { + if (shouldShowOnboarding) { return null } diff --git a/apps/web/app/api/onboarding/research/route.ts b/apps/web/app/api/onboarding/research/route.ts index 5e9b933e..67bf4654 100644 --- a/apps/web/app/api/onboarding/research/route.ts +++ b/apps/web/app/api/onboarding/research/route.ts @@ -7,11 +7,22 @@ interface ResearchRequest { email?: string } -// prompt to get user context from X/Twitter profile -function finalPrompt(xUrl: string, userContext: string) { +function extractHandle(url: string): string { + const cleaned = url + .toLowerCase() + .replace("https://x.com/", "") + .replace("https://twitter.com/", "") + .replace("http://x.com/", "") + .replace("http://twitter.com/", "") + .replace("@", "") + + return (cleaned.split("/")[0] ?? cleaned).split("?")[0] ?? cleaned +} + +function finalPrompt(handle: string, userContext: string) { return `You are researching a user based on their X/Twitter profile to help personalize their experience. -X/Twitter Profile URL: ${xUrl}${userContext} +X Handle: @${handle}${userContext} Please analyze this X/Twitter profile and provide a comprehensive but concise summary of the user. Include: - Professional background and current role (if available) @@ -29,18 +40,12 @@ export async function POST(req: Request) { if (!xUrl?.trim()) { return Response.json( - { error: "X/Twitter URL is required" }, + { error: "X/Twitter URL or handle is required" }, { status: 400 }, ) } - const lowerUrl = xUrl.toLowerCase() - if (!lowerUrl.includes("x.com") && !lowerUrl.includes("twitter.com")) { - return Response.json( - { error: "URL must be an X/Twitter profile link" }, - { status: 400 }, - ) - } + const handle = extractHandle(xUrl) const contextParts: string[] = [] if (name) contextParts.push(`Name: ${name}`) @@ -51,29 +56,13 @@ export async function POST(req: Request) { : "" const { text } = await generateText({ - model: xai("grok-4-1-fast-reasoning"), - prompt: finalPrompt(xUrl, userContext), - providerOptions: { - xai: { - searchParameters: { - mode: "on", - sources: [ - { - type: "web", - safeSearch: true, - }, - { - type: "x", - includedXHandles: [ - lowerUrl - .replace("https://x.com/", "") - .replace("https://twitter.com/", ""), - ], - postFavoriteCount: 10, - }, - ], - }, - }, + model: xai.responses("grok-4-fast"), + prompt: finalPrompt(handle, userContext), + tools: { + web_search: xai.tools.webSearch(), + x_search: xai.tools.xSearch({ + allowedXHandles: [handle], + }), }, }) |