Auth

Production-ready email/password auth. Login, signup, session management, and route protection — server and client — powered by Better Auth and Zod.

better-authzodlucide-react@prisma/client@prisma/adapter-pgpgdotenvprisma@types/pg
shadcn/uibuttoncardinputfieldbadgeauto-installed by CLI

Preview

Add these to your .env before installing

The CLI checks for these at install time — missing values mean the database step gets skipped, and the feature won't work until it's added.

  • DATABASE_URLrequired

    PostgreSQL connection string.

    e.g. postgresql://user:pass@localhost:5432/mydb
  • BETTER_AUTH_SECRETrequired

    Random secret for signing sessions. Generate one here →

  • BETTER_AUTH_URLrequired

    Your app's public URL.

    e.g. http://localhost:3000

Install via CLI

npx feature101@latest add auth

PostInstall Guides

  1. 01/login and /signup pages are ready to use out of the box
  2. 02/dashboard is protected via proxy & requireSession() — visit it logged out to see the redirect

Data Flow

client

What the user clicks and types.

server

Validates and saves the change securely.

prisma

Your data, permanently written to the database.

Files20
app/(auth)/login/page.tsx
import { GalleryVerticalEnd } from "lucide-react";
import { LoginForm } from "@/features/auth";
import Image from "next/image";
import Link from "next/link";

export default function LoginPage() {
  return (
    <div className="grid min-h-svh lg:grid-cols-2">
      <div className="flex flex-col gap-4 p-6 md:p-10">
        <div className="flex justify-center gap-2 md:justify-start">
          <Link href="#" className="flex items-center gap-2 font-medium">
            <div className="flex size-6 items-center justify-center rounded-md bg-primary text-primary-foreground">
              <GalleryVerticalEnd className="size-4" />
            </div>
            Acme Inc.
          </Link>
        </div>
        <div className="flex flex-1 items-center justify-center">
          <div className="w-full max-w-xs">
            <LoginForm />
          </div>
        </div>
      </div>
      <div className="relative hidden lg:block overflow-hidden">
        <Image
          src="/jonatan-pie-unsplash.jpg"
          alt="Off-road car silhouette"
          fill
          priority
          sizes="50vw"
          className="object-cover object-[55%_70%]"
        />
      </div>
    </div>
  );
}