diff --git a/CHANGELOG.md b/CHANGELOG.md
index b5d8dae6..f4e157cf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+### Added
+- Added seperate page for signup. [#311](https://github.com/sourcebot-dev/sourcebot/pull/331)
+
## [4.1.1] - 2025-06-03
### Added
diff --git a/packages/web/src/app/login/components/loginForm.tsx b/packages/web/src/app/login/components/loginForm.tsx
index bce69025..721af536 100644
--- a/packages/web/src/app/login/components/loginForm.tsx
+++ b/packages/web/src/app/login/components/loginForm.tsx
@@ -22,9 +22,10 @@ interface LoginFormProps {
callbackUrl?: string;
error?: string;
providers: Array<{ id: string; name: string }>;
+ context: "login" | "signup";
}
-export const LoginForm = ({ callbackUrl, error, providers }: LoginFormProps) => {
+export const LoginForm = ({ callbackUrl, error, providers, context }: LoginFormProps) => {
const captureEvent = useCaptureEvent();
const onSignInWithOauth = useCallback((provider: string) => {
signIn(provider, {
@@ -77,9 +78,11 @@ export const LoginForm = ({ callbackUrl, error, providers }: LoginFormProps) =>
-
Sign in to your account
+
+ {context === "login" ? "Sign in to your account" : "Create a new account"}
+
{env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT !== undefined && (
@@ -120,6 +123,17 @@ export const LoginForm = ({ callbackUrl, error, providers }: LoginFormProps) =>
] : [])
]}
/>
+
+ {context === "login" ?
+ <>
+ No account yet? Sign up
+ >
+ :
+ <>
+ Already have an account? Sign in
+ >
+ }
+
{env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT !== undefined && (
By signing in, you agree to the Terms of Service and Privacy Policy.
diff --git a/packages/web/src/app/login/page.tsx b/packages/web/src/app/login/page.tsx
index 4fc6f9c4..a948a464 100644
--- a/packages/web/src/app/login/page.tsx
+++ b/packages/web/src/app/login/page.tsx
@@ -40,6 +40,7 @@ export default async function Login({ searchParams }: LoginProps) {
callbackUrl={searchParams.callbackUrl}
error={searchParams.error}
providers={providerData}
+ context="login"
/>
diff --git a/packages/web/src/app/signup/page.tsx b/packages/web/src/app/signup/page.tsx
new file mode 100644
index 00000000..7c59899c
--- /dev/null
+++ b/packages/web/src/app/signup/page.tsx
@@ -0,0 +1,48 @@
+import { auth } from "@/auth";
+import { LoginForm } from "../login/components/loginForm";
+import { redirect } from "next/navigation";
+import { getProviders } from "@/auth";
+import { Footer } from "@/app/components/footer";
+import { createLogger } from "@sourcebot/logger";
+
+const logger = createLogger('signup-page');
+
+interface LoginProps {
+ searchParams: {
+ callbackUrl?: string;
+ error?: string;
+ }
+}
+
+export default async function Signup({ searchParams }: LoginProps) {
+ const session = await auth();
+ if (session) {
+ logger.info("Session found in signup page, redirecting to home");
+ return redirect("/");
+ }
+
+ const providers = getProviders();
+ const providerData = providers
+ .map((provider) => {
+ if (typeof provider === "function") {
+ const providerInfo = provider()
+ return { id: providerInfo.id, name: providerInfo.name }
+ } else {
+ return { id: provider.id, name: provider.name }
+ }
+ });
+
+ return (
+
+ )
+}
diff --git a/packages/web/src/middleware.ts b/packages/web/src/middleware.ts
index e8476db5..d20c6c5c 100644
--- a/packages/web/src/middleware.ts
+++ b/packages/web/src/middleware.ts
@@ -10,7 +10,11 @@ export async function middleware(request: NextRequest) {
return NextResponse.next();
}
- if (url.pathname.startsWith('/login') || url.pathname.startsWith('/redeem')) {
+ if (
+ url.pathname.startsWith('/login') ||
+ url.pathname.startsWith('/redeem') ||
+ url.pathname.startsWith('/signup')
+ ) {
return NextResponse.next();
}