feat: replace Google OAuth with email/password authentication

Replace Google OAuth provider with email/password authentication to reduce
friction for MVP development and vibe coding workflows.

Changes:
- Remove Google OAuth configuration from auth.ts
- Add emailAndPassword provider with enabled: true
- Add email verification with sendOnSignUp: true
- Add password reset functionality
- Log verification and reset URLs to terminal (no email integration yet)

New auth pages (src/app/(auth)/):
- /login - Sign in page
- /register - Sign up page
- /forgot-password - Password reset request
- /reset-password - Password reset completion

New components (src/components/auth/):
- sign-up-form.tsx - Registration form
- forgot-password-form.tsx - Password reset request form
- reset-password-form.tsx - Password reset form

Updated components:
- sign-in-button.tsx - Now email/password form instead of Google button
- user-profile.tsx - Shows Sign in/Sign up buttons when logged out

Bug fixes:
- Fix React render error in profile page by wrapping router.push in useEffect

Config updates:
- Remove GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET from env.example
- Update CLAUDE.md documentation to reflect email/password auth
- Add requestPasswordReset, resetPassword, sendVerificationEmail to auth-client exports

All changes applied to both main project and create-agentic-app template.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Auto
2025-12-26 05:50:43 +02:00
parent 5cd66b245e
commit f29d296816
45 changed files with 2231 additions and 91 deletions

View File

@@ -1,6 +1,6 @@
"use client";
import { useState } from "react";
import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import { Mail, Calendar, User, Shield, ArrowLeft, Lock, Smartphone } from "lucide-react";
import { toast } from "sonner";
@@ -33,7 +33,13 @@ export default function ProfilePage() {
const [securityOpen, setSecurityOpen] = useState(false);
const [emailPrefsOpen, setEmailPrefsOpen] = useState(false);
if (isPending) {
useEffect(() => {
if (!isPending && !session) {
router.push("/");
}
}, [isPending, session, router]);
if (isPending || !session) {
return (
<div className="flex items-center justify-center min-h-screen">
<div>Loading...</div>
@@ -41,11 +47,6 @@ export default function ProfilePage() {
);
}
if (!session) {
router.push("/");
return null;
}
const user = session.user;
const createdDate = user.createdAt
? new Date(user.createdAt).toLocaleDateString("en-US", {