diff --git a/src/app/portal/onboarding/page.tsx b/src/app/portal/onboarding/page.tsx
index 1d7516e..712098d 100644
--- a/src/app/portal/onboarding/page.tsx
+++ b/src/app/portal/onboarding/page.tsx
@@ -1,6 +1,6 @@
"use client";
-import { useEffect } from "react";
+import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { useAuth, useAppShell } from "@abe-kap/appshell-sdk/react";
import { PortalAside, PanelBrand } from "@/components/portal/parts";
@@ -10,18 +10,34 @@ import { isShellConfigured } from "@/lib/appshell";
/**
* Post-OAuth onboarding — a first-time Google user completes their CRM profile
- * (everything except email, which Google already verified). Only reachable while
- * authenticated; unauthenticated visitors are sent back to sign in.
+ * (everything except email, which Google already verified).
+ *
+ * This screen is ONLY a step in the OAuth → onboarding handoff: the login page
+ * stashes the verified email in `sessionStorage` right before routing here. Any
+ * other way in — a typed URL, a fresh tab, a lost session — has no handoff hint
+ * (and possibly no session), so we bounce back to sign in rather than showing an
+ * empty form.
*/
export default function OnboardingPage() {
const router = useRouter();
const { status } = useAuth();
const { ready } = useAppShell();
+ const [allowed, setAllowed] = useState(false);
useEffect(() => {
- if (isShellConfigured() && ready && status === "unauthenticated") router.replace("/portal/login");
+ if (!isShellConfigured()) { setAllowed(true); return; } // local dev without the Shell
+ if (!ready) return; // wait for session restore
+ let hasHandoff = false;
+ try { hasHandoff = !!sessionStorage.getItem("onboard_email"); } catch { /* ignore */ }
+ if (status === "unauthenticated" || !hasHandoff) {
+ router.replace("/portal/login");
+ return;
+ }
+ setAllowed(true);
}, [ready, status, router]);
+ if (!allowed) return ;
+
return (
diff --git a/src/components/portal/register-flow.tsx b/src/components/portal/register-flow.tsx
index 762457e..c498991 100644
--- a/src/components/portal/register-flow.tsx
+++ b/src/components/portal/register-flow.tsx
@@ -120,6 +120,8 @@ export function RegisterFlow({ mode = "register" }: { mode?: "register" | "onboa
// register mode: non-fatal — the auth account exists; the profile can be filled in later.
}
}
+ // Consume the OAuth→onboarding handoff so a stale hint can't re-open onboarding.
+ try { sessionStorage.removeItem("onboard_email"); } catch { /* ignore */ }
router.push("/dashboard");
}