ZenoZENO

Authentication

Drop-in Supabase auth flows via the registry, plus the server-side confirm handler

Zeno ships the standard Supabase auth flows: magic-link and password sign-in, sign-up, email verification, password recovery and reset, and sign-out. The UI flows are shadcn-style components you install from the registry and own; the server-side OTP confirm handler is headless and ships on npm as @zeno-lib/authentication.

Install

Add the flows you need from the registry. Each one installs into @/components/auth/* and brings in the shadcn primitives it uses:

pnpm dlx shadcn@latest add zeno-lib/zeno/sign-in zeno-lib/zeno/auth-layout

Other flows: sign-up, email-sent, verify, error, recover-password, reset-password, sign-out. Then install the server handler and the Supabase client:

pnpm add @zeno-lib/authentication @zeno-lib/supabase

Wire the provider

Mount AuthProvider once, in the auth route group's layout, and pass it a Supabase client. It provides the form state and the per-flow submit handlers through React context:

app/(auth)/layout.tsx
"use client"

import { AuthProvider } from "@/components/auth/components/context"
import { createClient } from "@zeno-lib/supabase/next-client"

export default function AuthLayout({ children }: { children: React.ReactNode }) {
  return <AuthProvider supabase={createClient()}>{children}</AuthProvider>
}

Render each flow on its route:

app/(auth)/sign-in/page.tsx
import { SignIn } from "@/components/auth/sign-in"

export default function Page() {
  return <SignIn />
}

The flows report errors with toast from sonner, so mount <Toaster /> (add it with pnpm dlx shadcn@latest add sonner) in your root layout.

The confirm route (server)

The confirm handler verifies magic links and OTPs on the server, never in a client component. Mount it from the npm package at /confirm:

app/confirm/route.ts
export { getRoute as GET } from "@zeno-lib/authentication/confirm/index"

Route contract

The flows navigate to hard-coded paths, so mount these routes (or wire your own equivalents):

  • After sending a magic link, the sign-in flow pushes to /email-sent.
  • The verify screen's button opens /confirm?token_hash=…&type=….
  • The middleware (@zeno-lib/supabase/next-middleware) redirects unauthenticated users to /sign-in.

Don't auto-redirect from the verify screen. The manual button click is a security measure. Email link scanners (such as Microsoft Safe Links) prefetch URLs and would consume a one-time OTP before the user clicks. Verification must stay behind the click.