Complete password-based authentication flow for React applications. Includes login and sign-up forms with built-in validation, error handling, and full Convex backend integration.
Installation
npx shadcn@latest add https://convex-ui.vercel.app/r/password-based-auth-react
This installs:
Login and sign-up form components
Convex auth configuration
User management functions
Convex client setup files
What’s Included
Login Form Email/password login with forgot password link support
Sign-Up Form User registration with password confirmation and validation
Backend Functions Complete Convex auth setup with user management
Type Safety Full TypeScript support with validated schemas
Setup
Run the Convex development server to initialize your backend:
This deploys your auth functions and schema to Convex.
Set Environment Variables
Add your Convex URL to .env:
VITE_CONVEX_URL = https://your-deployment.convex.cloud
CONVEX_DEPLOYMENT = your-deployment-name
For email verification and password reset, set up Resend in the Convex dashboard:
The ConvexClientProvider is automatically included. Wrap your app in main.tsx:
import { ConvexClientProvider } from './lib/convex/provider'
ReactDOM . createRoot ( document . getElementById ( 'root' ) ! ). render (
< ConvexClientProvider >
< App />
</ ConvexClientProvider >
)
Components
Email and password login form with error handling.
import { LoginForm } from "@/components/login-form" ;
function LoginPage () {
return (
< div className = "flex items-center justify-center min-h-screen" >
< LoginForm
onSignUpClick = { () => navigate ( '/signup' ) }
onForgotPasswordClick = { () => navigate ( '/forgot-password' ) }
/>
</ div >
);
}
Props
Callback when user clicks “Sign up” link. Use for navigation to sign-up page.
Callback when user clicks “Forgot password?” link. Use for navigation to password reset.
User registration form with password strength validation.
import { SignUpForm } from "@/components/sign-up-form" ;
function SignUpPage () {
return (
< div className = "flex items-center justify-center min-h-screen" >
< SignUpForm
onLoginClick = { () => navigate ( '/login' ) }
onSuccess = { () => navigate ( '/welcome' ) }
/>
</ div >
);
}
Props
Callback when user clicks “Sign in” link. Use for navigation to login page.
Callback after successful registration. Use for navigation or showing success message.
Usage Example
import { useState } from 'react' ;
import { LoginForm } from '@/components/login-form' ;
import { SignUpForm } from '@/components/sign-up-form' ;
function AuthPage () {
const [ view , setView ] = useState < 'login' | 'signup' >( 'login' );
return (
< div className = "min-h-screen flex items-center justify-center bg-gray-50" >
{ view === 'login' ? (
< LoginForm onSignUpClick = { () => setView ( 'signup' ) } />
) : (
< SignUpForm onLoginClick = { () => setView ( 'login' ) } />
) }
</ div >
);
}
export default AuthPage ;
Backend Functions
The component includes a complete Convex backend setup.
Auth Configuration
convex/auth.config.ts configures Convex Auth with password authentication:
import { AuthConfig } from "convex/server" ;
export default {
providers: [
{
domain: process . env . CONVEX_SITE_URL ! ,
applicationID: "convex" ,
},
] ,
} satisfies AuthConfig ;
User Queries
Get current user:
api . users . current
// Returns: { _id, name, email, image } | null
Get user by ID:
api . users . get ({ userId: "j97..." })
// Returns: { _id, name, image } | null (public fields only)
User Mutations
Update profile:
api . users . updateProfile ({
name: "Jane Doe" ,
image: "https://..."
})
Authentication Hooks
Use the useAuthActions hook from Convex Auth:
import { useAuthActions } from "@convex-dev/auth/react" ;
import { useQuery } from "convex/react" ;
import { api } from "@/convex/_generated/api" ;
function UserProfile () {
const { signOut } = useAuthActions ();
const user = useQuery ( api . users . current );
return (
< div >
< p > Logged in as { user ?. email } </ p >
< button onClick = { () => signOut () } > Sign Out </ button >
</ div >
);
}
Available Actions
signIn
(provider: string, formData: FormData) => Promise<void>
Sign in with email/password. Provider should be "password".
Sign out the current user.
Validation
Both forms include built-in validation:
Email format validation
Required fields
Error messages from backend
Password must be at least 8 characters
Password confirmation must match
Name and email required
Sanitized input (trimmed whitespace)
Environment Variables
Your Convex deployment URL from npx convex dev
Your Convex deployment name
Optional (Convex Dashboard)
Resend API key for email verification and password reset
Customization
The forms use shadcn/ui components and can be fully customized:
import { LoginForm } from "@/components/login-form" ;
// Wrap in custom container
< div className = "max-w-md mx-auto p-8 bg-gradient-to-b from-blue-50 to-white rounded-xl" >
< LoginForm />
</ div >
// Or modify the component directly in your components folder
Security Features
Input Sanitization All user inputs are trimmed and validated before processing
Password Validation Minimum length requirements and confirmation matching
Secure Sessions JWT-based authentication managed by Convex Auth
Public Data Only User lookup functions never expose email or sensitive data
Next Steps
Social Auth Add GitHub and Google sign-in
Current User Avatar Display the logged-in user’s avatar
Realtime Chat Build authenticated chat rooms