From a365fef170313e3d99dda78b1d52c0c63831bc14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Guti=C3=A9rrez?= <35082514+alezmad@users.noreply.github.com> Date: Mon, 13 Apr 2026 08:51:18 +0100 Subject: [PATCH] feat(web): dedicated CLI auth page with inline login/register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No more redirect to generic /auth/login. The /cli-auth?code=XXXX page now shows auth forms inline (Google, GitHub, email) with device code context — like Anthropic's "Build with Claude" page. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../app/[locale]/cli-auth/cli-auth-login.tsx | 60 +++++++++++++++++++ apps/web/src/app/[locale]/cli-auth/page.tsx | 41 ++++++++----- 2 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 apps/web/src/app/[locale]/cli-auth/cli-auth-login.tsx diff --git a/apps/web/src/app/[locale]/cli-auth/cli-auth-login.tsx b/apps/web/src/app/[locale]/cli-auth/cli-auth-login.tsx new file mode 100644 index 0000000..8445174 --- /dev/null +++ b/apps/web/src/app/[locale]/cli-auth/cli-auth-login.tsx @@ -0,0 +1,60 @@ +"use client"; + +import { SocialProvider } from "@turbostarter/auth"; + +import { authConfig } from "~/config/auth"; +import { SocialProviders } from "~/modules/auth/form/social-providers"; +import { RegisterForm } from "~/modules/auth/form/register-form"; +import { AuthDivider } from "~/modules/auth/layout/divider"; + +interface Props { + code: string; +} + +export function CliAuthLogin({ code }: Props) { + const redirectTo = `/cli-auth?code=${encodeURIComponent(code)}`; + + return ( +
+ {/* Header */} +
+
+ cm +
+

+ Connect to claudemesh CLI +

+

+ Sign in or create an account to connect your terminal session. +

+
+ + {/* Social providers */} + + + + + {/* Email + password form */} + + + {/* Device code footer */} +
+
+ {code} +
+

+ Confirm this code matches your terminal +

+
+
+ ); +} diff --git a/apps/web/src/app/[locale]/cli-auth/page.tsx b/apps/web/src/app/[locale]/cli-auth/page.tsx index 6e2377c..5c2ea52 100644 --- a/apps/web/src/app/[locale]/cli-auth/page.tsx +++ b/apps/web/src/app/[locale]/cli-auth/page.tsx @@ -1,14 +1,13 @@ -import { redirect } from "next/navigation"; - import { getSession } from "~/lib/auth/server"; import { getMetadata } from "~/lib/metadata"; import { CliAuthFlow } from "./cli-auth-flow"; import { DeviceCodeApproval } from "./device-code-approval"; +import { CliAuthLogin } from "./cli-auth-login"; export const generateMetadata = getMetadata({ - title: "Sync with CLI", - description: "Link your claudemesh CLI to your account.", + title: "Connect CLI", + description: "Sign in to connect your claudemesh CLI.", }); export default async function CliAuthPage({ @@ -17,24 +16,24 @@ export default async function CliAuthPage({ searchParams: Promise<{ code?: string; port?: string }>; }) { const { user } = await getSession(); - - if (!user) { - const sp = await searchParams; - const qs = new URLSearchParams(); - if (sp.code) qs.set("code", sp.code); - if (sp.port) qs.set("port", sp.port); - const returnTo = `/cli-auth${qs.size ? `?${qs}` : ""}`; - return redirect(`/auth/login?redirectTo=${encodeURIComponent(returnTo)}`); - } - const { code, port } = await searchParams; // Device-code flow: code contains "-" (e.g. "ABCD-EFGH"), no port const isDeviceCode = code && code.includes("-") && !port; if (isDeviceCode) { + if (!user) { + // NOT logged in → show inline auth form with device code context + return ( +
+ +
+ ); + } + + // Logged in → auto-approve return ( -
+