Verified against v0 · 2026-08-04
Build login, signup, and reset screens that match an existing design system
A v0 brief for auth screens built from an app's existing component library and design tokens instead of shadcn's defaults, with account-enumeration-safe error messages on both login and password reset.
The prompt
Ready to copy — highlighted parts are example details you can swap.
Generate three auth screens — Login, Sign up, and Forgot password — for a Next.js App Router app, matching an EXISTING design system already in this codebase. Do not default to shadcn/ui's out-of-the-box look; match what's actually already here. EXISTING DESIGN SYSTEM Button (variant: "primary" | "secondary" | "ghost"), Input (with built-in label and error-message slots), Checkbox — all in components/ui/, built on Radix primitives with the app's own Tailwind classes, not shadcn's default styling — use these exact components and their existing prop APIs; do not generate a parallel set of new Input or Button components that happen to look similar, since that produces two different button styles living side by side in the same app the moment this gets merged. DESIGN TOKENS primary color var(--brand-600), border radius var(--radius-md) = 10px, font family already set globally via next/font — no new font import needed — use these values via the existing Tailwind config or CSS variables already defined in the project, not new hardcoded hex values that happen to look close. SCREENS 1. Login: email and password fields, a "remember me" checkbox, a primary submit button, and a "Forgot password?" link. Show a field-level error for an invalid email format before submit, and a single non-field-specific error banner for a failed login attempt (wrong credentials) — do not reveal whether the email or the password was the specific problem, which is a real account-enumeration risk if the two are distinguished. 2. Sign up: name, email, password, and a password-confirmation field with a live match/mismatch indicator as the user types the second field. Show password strength requirements (at least 10 characters, one number, one symbol) as a checklist that updates live as the user types, not only as an error after a failed submit attempt. 3. Forgot password: an email field and a submit button leading to a confirmation state that says a reset link was sent — this confirmation message must be shown whether or not the email actually exists in the system, since revealing "no account found for that email" on a password-reset form is the same account-enumeration risk as the login error above. SHARED BEHAVIOR All three screens should share one AuthLayout component for the surrounding page structure — the same centered card, the same logo placement (the existing <Logo /> component from components/brand/logo.tsx, rendered at 32px height), the same background — rather than three screens that each rebuild the layout slightly differently. Every submit button must show a pending state and be disabled while its request is in flight, and every form must be operable via keyboard alone, including submitting with Enter from any field. CONSTRAINTS Login lives at /login, Sign up at /signup, Forgot password at /forgot-password — after a successful login, redirect to /dashboard Use the existing component library exactly as specified above — if a needed element genuinely doesn't exist in the existing system (for example, no password-strength-checklist component exists yet), say so explicitly and build a minimal new one that visually matches the existing tokens, rather than silently reaching for a shadcn default that will look inconsistent next to it.
Customize
Optional — swap in your own details for the highlighted parts above.
Why this works
v0's default behavior, with no explicit existing-component instruction, is to generate its own shadcn/ui-styled elements from scratch, because that's the stack it's tuned to produce well by default. For a genuinely new project that's fine; for an existing codebase with its own Button and Input components already in use elsewhere, an unscoped prompt produces auth screens that look like a different app was pasted in. Naming the exact existing components and their prop APIs is what actually gets v0 to compose with what's already there instead of quietly duplicating it with a second, slightly different set of primitives. The non-specific login error and the always-shown reset-confirmation both target the same real vulnerability class: account enumeration. A login form that says "no account found" versus "wrong password" as two distinct messages lets an attacker efficiently discover which emails have accounts on the system by testing responses one at a time, and a password-reset flow that reveals "no account with that email" has exactly the same leak through a different door. Naming this explicitly as a security requirement, rather than an incidental UX choice left to the model's taste, is what keeps a generated auth flow from accidentally becoming a data-enumeration tool for anyone who probes it. The shared AuthLayout requirement addresses a specific, common generation artifact: when a model is asked to build three related screens in one pass, each screen individually looks reasonable on its own, but small inconsistencies creep in between them — a slightly different card width, a logo placed a few pixels off — because each was generated as its own self-contained unit rather than composed from one shared piece. Forcing a shared layout component guarantees pixel-consistency between the three screens by construction, rather than by hoping the model happened to reproduce the same values three separate times.
Verified against
v0 v0 by Vercel (Next.js + shadcn/ui default stack) · 2026-08-04
Changelog
- 2026-08-04 — Initial publish, verified against v0 with an existing-component-library constraint and enumeration-safe error messaging on both flows.
Need this built into your business?
If a prompt isn't enough — custom software, built and maintained for you — that's Scult's day job.
EXPLORE CUSTOM SOFTWARE
