Files

72 lines
2.6 KiB
Markdown

# Wiring the routes (do this once)
**Live-preview popup is PRE-WIRED — do not create it.**
`signIn` opens `/auth/popup`; the template Vite plugin
(`authPopupPlugin` in `vite.config.ts`) serves it via `popup.server.ts`.
**Never** add `src/routes/auth/popup.tsx` (or any React page / client OAuth at
that path). Doing so loads the full app shell in the popup ("the app opened
instead of Google") — that is always wrong.
**1. Mount Better Auth** — create the catch-all API route (this is what makes
`/api/auth/*` work; the broker's OAuth callback lands here):
```ts
// src/routes/api/auth/$.ts
import { createFileRoute } from "@tanstack/react-router";
import { auth } from "@/lib/auth/server";
export const Route = createFileRoute("/api/auth/$")({
server: {
handlers: {
GET: ({ request }) => auth.handler(request),
POST: ({ request }) => auth.handler(request),
},
},
});
```
**2. Add a sign-in page** — buttons that kick off the broker flow. Import from
`@/lib/auth/client`. With the flag on, `authEnabled` is true in preview and
deployed, so the buttons show and work in the live preview; the `else` branch
shows while auth is still disabled (`VITE_AUTH_ENABLED=false`):
```tsx
// src/routes/login.tsx
import { createFileRoute } from "@tanstack/react-router";
import { GROK_PROVIDERS, authEnabled, signIn } from "@/lib/auth/client";
export const Route = createFileRoute("/login")({ component: Login });
function Login() {
return (
<main className="grid min-h-screen place-items-center p-6">
<div className="w-full max-w-sm space-y-3">
<h1 className="text-xl font-semibold">Sign in</h1>
{authEnabled ? (
GROK_PROVIDERS.map((p) => (
<button
key={p.providerId}
type="button"
onClick={() => signIn(p.providerId, { callbackURL: "/" })}
className="w-full cursor-pointer rounded-md border border-neutral-300 px-4 py-2 hover:bg-neutral-100 dark:border-neutral-700 dark:hover:bg-neutral-900"
>
Continue with {p.label}
</button>
))
) : (
<p className="text-sm text-neutral-500">Sign-in is disabled.</p>
)}
</div>
</main>
);
}
```
`RedirectToSignIn` sends signed-out users to `/login` by default (override with
`<RedirectToSignIn to="/somewhere" />`). Style the page however you like — see
the `design-ui` skill.
That's it — call `signIn(providerId)` from your sign-in buttons. The popup,
bearer-token hand-off, and request attachment are all inside `src/lib/auth` +
the Vite plugin; leave them alone.