From 0f3f17b68c93047ce1e2609e13fb5d34eec1a7d9 Mon Sep 17 00:00:00 2001 From: Vorflux AI Date: Fri, 1 May 2026 19:22:22 +0000 Subject: [PATCH] fix: redirect new users to onboarding from plugin connect page New users arriving at /auth/connect (e.g. from OpenCode CLI) had no organization yet, causing the 'Approve Connection' button to silently fail. The handleConnect guard 'if (!session || !org) return' would fire with no feedback, leading to rage-clicking. Changes: - Detect logged-in users with no org on the connect page and redirect them to onboarding, stashing the connect URL in sessionStorage. - After onboarding completes, redirect back to the connect page so the plugin auth flow finishes automatically. - Show an error message instead of silently returning when session/org is missing and the user clicks 'Approve Connection'. - Extract PENDING_CONNECT_URL_KEY to a shared constants file. --- .../app/(app)/old/onboarding/setup/layout.tsx | 7 +- apps/web/app/(app)/onboarding/page.tsx | 13 ++- apps/web/app/auth/connect/page.tsx | 45 +++++++- apps/web/components/initial-header.tsx | 4 +- .../components/onboarding/setup/header.tsx | 4 +- .../onboarding/setup/integrations-step.tsx | 4 +- apps/web/lib/__tests__/constants.test.ts | 106 ++++++++++++++++++ apps/web/lib/constants.ts | 28 +++++ 8 files changed, 199 insertions(+), 12 deletions(-) create mode 100644 apps/web/lib/__tests__/constants.test.ts create mode 100644 apps/web/lib/constants.ts diff --git a/apps/web/app/(app)/old/onboarding/setup/layout.tsx b/apps/web/app/(app)/old/onboarding/setup/layout.tsx index d68f4325..ebff2cdf 100644 --- a/apps/web/app/(app)/old/onboarding/setup/layout.tsx +++ b/apps/web/app/(app)/old/onboarding/setup/layout.tsx @@ -11,6 +11,7 @@ import { import { useRouter, useSearchParams } from "next/navigation" import { useOnboardingContext, type MemoryFormData } from "../layout" import { analytics } from "@/lib/analytics" +import { consumePendingConnectUrl } from "@/lib/constants" export const SETUP_STEPS = ["integrations"] as const export type SetupStep = (typeof SETUP_STEPS)[number] @@ -61,7 +62,11 @@ export default function SetupLayout({ children }: { children: ReactNode }) { const finishOnboarding = useCallback(() => { resetOnboarding() - router.push("/") + + // If the user arrived from the plugin connect page (e.g. OpenCode), + // redirect back there so the auth flow can complete automatically. + const pendingPath = consumePendingConnectUrl() + router.push(pendingPath ?? "/") }, [router, resetOnboarding]) useEffect(() => { diff --git a/apps/web/app/(app)/onboarding/page.tsx b/apps/web/app/(app)/onboarding/page.tsx index fac8cc40..e3d7245e 100644 --- a/apps/web/app/(app)/onboarding/page.tsx +++ b/apps/web/app/(app)/onboarding/page.tsx @@ -32,6 +32,7 @@ import { import { GoogleDrive, Notion, OneDrive } from "@ui/assets/icons" import { Sparkles, ChevronLeft, ChevronRight } from "lucide-react" import { analytics } from "@/lib/analytics" +import { consumePendingConnectUrl } from "@/lib/constants" type DetectedSource = "x" | "linkedin" | "resume" | null type Status = "idle" | "processing" | "done" | "error" @@ -373,6 +374,12 @@ export default function OnboardingPage() { const pollingRef = useRef | null>(null) const [spotlightCategory, setSpotlightCategory] = useState("productivity") + + /** Navigate home, or back to the plugin connect page if one is pending. */ + const goHomeOrPendingConnect = useCallback(() => { + const pendingPath = consumePendingConnectUrl() + router.push(pendingPath ?? "/") + }, [router]) const [pauseSpotlight, setPauseSpotlight] = useState(false) const spotlightCatalog = useMemo( @@ -620,7 +627,7 @@ export default function OnboardingPage() {