Skip to content

Next.js

  • A Next.js 16 app with the App Router, on Node.js 24 or later.
  • An application in the dashboard. Its development instance is ready at once; its keys are on the instance’s API keys page.
Terminal window
npm i @zautha/nextjs @zautha/ui

Put the publishable key (pk_test_…) and a secret key (sk_test_…, shown once when you create it) in .env.local. proxy.ts makes the session available to the server and protects /dashboard; the layout shows a sign-in button or the user button; the page reads the user on the server.

.env.local
NEXT_PUBLIC_ZAUTHA_PUBLISHABLE_KEY=pk_test_...
# Create one under API keys:
ZAUTHA_SECRET_KEY=sk_test_...
proxy.ts
import { createRouteMatcher, zauthaProxy } from "@zautha/nextjs/server";
const isProtected = createRouteMatcher(["/dashboard(.*)"]);
export default zauthaProxy(async (auth, req) => {
if (isProtected(req)) await auth.protect();
});
export const config = { matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"] };
app/layout.tsx
import type { ReactNode } from "react";
import { Show, SignInButton, UserButton, ZauthaProvider } from "@zautha/nextjs";
import "@zautha/ui/styles.css";
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<ZauthaProvider>
<header>
<Show when="signed-out">
<SignInButton />
</Show>
<Show when="signed-in">
<UserButton />
</Show>
</header>
{children}
</ZauthaProvider>
</body>
</html>
);
}
app/dashboard/page.tsx
import { currentUser } from "@zautha/nextjs/server";
export default async function Dashboard() {
const user = await currentUser();
return <p>Signed in as {user?.primary_email_address}</p>;
}
Terminal window
npm run dev

Open http://localhost:3000, sign in, then open /dashboard. A development instance accepts localhost as it is; on a development instance, addresses ending in +zautha_test before the @ (such as jane+zautha_test@example.com) get no email and verify with the code 424242.

In production, also set ZAUTHA_AUTHORIZED_PARTIES to every origin your app is served from, so session tokens are accepted only for them (see Environment), and use the production instance’s pk_live_… and sk_live_… keys.

  • @zautha/nextjs: auth(), roles and permissions, reverification, social sign-in.
  • Sessions and tokens: what the session token says and how the server reads it.
  • Webhooks: hear about new users on your server.

Zautha’s end-to-end tests run this setup in a Next.js example app.