diff --git a/src/app/dev/login/buttons.tsx b/src/app/dev/login/buttons.tsx
index 86bd1bcc..2648b4f3 100644
--- a/src/app/dev/login/buttons.tsx
+++ b/src/app/dev/login/buttons.tsx
@@ -13,7 +13,13 @@ type Persona = {
const DEV_PASSWORD = 'dev-password-only';
-export default function DevLoginButtons({ personas }: { personas: Persona[] }) {
+export default function DevLoginButtons({
+ personas,
+ next = '/dashboard',
+}: {
+ personas: Persona[];
+ next?: string;
+}) {
const router = useRouter();
const [pending, setPending] = useState(null);
const [error, setError] = useState(null);
@@ -37,7 +43,7 @@ export default function DevLoginButtons({ personas }: { personas: Persona[] }) {
return;
}
router.refresh();
- router.push('/dashboard');
+ router.push(next);
}
return (
diff --git a/src/app/dev/login/page.tsx b/src/app/dev/login/page.tsx
index 78f342d3..132f3e8f 100644
--- a/src/app/dev/login/page.tsx
+++ b/src/app/dev/login/page.tsx
@@ -8,11 +8,13 @@ export const dynamic = 'force-dynamic';
* Used by contributors and CI to sign in as one of the seeded test users
* without needing real GitHub OAuth.
*/
-export default function DevLoginPage() {
+export default function DevLoginPage({ searchParams }: { searchParams: { next?: string } }) {
if (process.env.NODE_ENV === 'production') {
notFound();
}
+ const next = searchParams.next ?? '/dashboard';
+
const personas = [
{ email: 'alice@test.local', level: 'L0', label: 'Alice', blurb: 'Brand new, no audit yet' },
{ email: 'bob@test.local', level: 'L1', label: 'Bob', blurb: 'Audited, has active recs' },
@@ -38,7 +40,7 @@ export default function DevLoginPage() {
-
+
);
diff --git a/src/app/onboarding/page.tsx b/src/app/onboarding/page.tsx
new file mode 100644
index 00000000..aa2b02dc
--- /dev/null
+++ b/src/app/onboarding/page.tsx
@@ -0,0 +1,92 @@
+import Link from 'next/link';
+
+export default function OnboardingPage() {
+ return (
+
+
+
+ WELCOME TO MERGESHIP
+
+
+ How are you joining?
+
+ Pick your path to streamline your open-source journey.
+
+
+
+
+
+ FIRST PR
+
+ ▸_
+
+ +50 XP
+
+
+
+
FOR CONTRIBUTORS
+
I want to contribute
+
+
+ Get a structured path into open source. Find mentored issues, track your impact, and
+ build your profile.
+
+
+
+ - ✓ Match with mentored issues
+ - ✓ Step-by-step PR guidance
+ - ✓ Build a verified portfolio
+
+
+
+ Continue as Contributor →
+
+
+
+
+
+
+ AI FLAGGED
+
+ ▦+
+
+ -74% NOISE
+
+
+
+
FOR MAINTAINERS
+
I maintain a project
+
+
+ Connect your org and get a smart PR queue. Reduce noise, onboard contributors faster,
+ and ship clean code.
+
+
+
+ - ✓ Automated PR triaging
+ - ✓ AI-assisted code reviews
+ - ✓ Contributor analytics
+
+
+
+ Continue as Maintainer →
+
+
+
+
+
+ Not sure?{' '}
+
+ Start as a contributor.
+
+
+
+
+ );
+}
diff --git a/src/components/landing/LandingPage.tsx b/src/components/landing/LandingPage.tsx
index fb175c08..eaa9c8a1 100644
--- a/src/components/landing/LandingPage.tsx
+++ b/src/components/landing/LandingPage.tsx
@@ -135,13 +135,14 @@ export default function LandingPage() {
});
}, []);
- const handleLogin = () => {
+ const handleLogin = (nextPath: string | unknown = '/dashboard') => {
const sb = getBrowserSupabase();
if (!sb) return;
+ const next = typeof nextPath === 'string' ? nextPath : '/dashboard';
void sb.auth.signInWithOAuth({
provider: 'github',
options: {
- redirectTo: `${window.location.origin}/api/auth/callback?next=/dashboard`,
+ redirectTo: `${window.location.origin}/api/auth/callback?next=${encodeURIComponent(next)}`,
},
});
};
@@ -162,15 +163,17 @@ export default function LandingPage() {
);
}
+
if (localDev) {
return (
-
+
{label}
);
}
+
return (
-