Auth

UniversalNew

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/uibuttoncardinputfieldbadge— auto-installed by CLI
20 files generated
Before running the command, ensure these are in your.env

Without these in your.env your database won't be set up — the feature will break at runtime.

  • 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
File layers:clientui componentzustandhook / storeserverserver actionprismaprisma model
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 bg-muted lg:block">
        <Image
          src="/jonatan-pie-unsplash.jpg"
          alt="Off-road car silhouette"
          fill
          priority
          sizes="50vw"
          className="object-cover "
        />
      </div>
    </div>
  );
}