aboutsummaryrefslogtreecommitdiff
path: root/apps/web/app
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/app')
-rw-r--r--apps/web/app/(navigation)/page.tsx41
-rw-r--r--apps/web/app/api/onboarding/research/route.ts57
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],
+ }),
},
})