{"content":"# Better Auth Profile & Account\n\nAdd a complete account settings page with profile editing, password changes, email updates, session management, and account deletion.\n\n### User Menu Component\n\nCreate a dropdown menu that shows authentication state and user options:\n\n```tsx\n// src/components/auth/user-menu.tsx\n\"use client\";\n\nimport { useSession, signOut } from \"@/lib/auth/client\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { Skeleton } from \"@/components/ui/skeleton\";\nimport { Settings, LogOut, MessageSquare, AlertCircle } from \"lucide-react\";\nimport Link from \"next/link\";\nimport { useRouter } from \"next/navigation\";\nimport { toast } from \"sonner\";\n\nexport function UserMenu() {\n  const { data: session, isPending } = useSession();\n  const router = useRouter();\n\n  if (isPending) {\n    return <Skeleton className=\"size-9 rounded-full\" />;\n  }\n\n  if (!session) {\n    return (\n      <div className=\"flex items-center gap-2\">\n        <Link href=\"/sign-in\">\n          <Button variant=\"ghost\" size=\"sm\">\n            Sign in\n          </Button>\n        </Link>\n        <Link href=\"/sign-up\">\n          <Button size=\"sm\">Get started</Button>\n        </Link>\n      </div>\n    );\n  }\n\n  const user = session.user;\n  const initials = user.name\n    .split(\" \")\n    .map((n) => n[0])\n    .join(\"\")\n    .toUpperCase()\n    .slice(0, 2);\n\n  const handleSignOut = async () => {\n    await signOut({\n      fetchOptions: {\n        onSuccess: () => {\n          toast.success(\"Signed out successfully\");\n          router.push(\"/\");\n        },\n        onError: () => {\n          toast.error(\"Failed to sign out\");\n        },\n      },\n    });\n  };\n\n  return (\n    <DropdownMenu>\n      <DropdownMenuTrigger asChild>\n        <Button\n          variant=\"outline\"\n          size=\"icon\"\n          className=\"relative rounded-full p-0\"\n        >\n          <Avatar className=\"size-9\">\n            <AvatarImage src={user.image || undefined} alt={user.name} />\n            <AvatarFallback className=\"text-xs\">{initials}</AvatarFallback>\n          </Avatar>\n          {!user.emailVerified && (\n            <span className=\"absolute -top-0.5 -right-0.5 flex size-3\">\n              <span className=\"absolute inline-flex size-full animate-ping rounded-full bg-amber-400 opacity-75\" />\n              <span className=\"relative inline-flex size-3 rounded-full bg-amber-500\" />\n            </span>\n          )}\n        </Button>\n      </DropdownMenuTrigger>\n      <DropdownMenuContent className=\"w-56\" align=\"end\" forceMount>\n        <DropdownMenuLabel className=\"font-normal\">\n          <div className=\"flex flex-col space-y-1\">\n            <p className=\"text-sm font-medium leading-none\">{user.name}</p>\n            <p className=\"text-xs leading-none text-muted-foreground\">\n              {user.email}\n            </p>\n          </div>\n        </DropdownMenuLabel>\n        {!user.emailVerified && (\n          <>\n            <DropdownMenuSeparator />\n            <DropdownMenuItem asChild>\n              <Link\n                href=\"/profile\"\n                className=\"flex items-center text-amber-600 dark:text-amber-500\"\n              >\n                <AlertCircle className=\"mr-2 size-4\" />\n                Verify your email\n              </Link>\n            </DropdownMenuItem>\n          </>\n        )}\n        <DropdownMenuSeparator />\n        <DropdownMenuGroup>\n          <DropdownMenuItem asChild>\n            <Link href=\"/chats\">\n              <MessageSquare className=\"mr-2 size-4\" />\n              Chats\n            </Link>\n          </DropdownMenuItem>\n          <DropdownMenuItem asChild>\n            <Link href=\"/profile\">\n              <Settings className=\"mr-2 size-4\" />\n              Settings\n            </Link>\n          </DropdownMenuItem>\n        </DropdownMenuGroup>\n        <DropdownMenuSeparator />\n        <DropdownMenuItem onClick={handleSignOut} className=\"text-destructive\">\n          <LogOut className=\"mr-2 size-4\" />\n          Sign out\n        </DropdownMenuItem>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  );\n}\n```\n\nKey features:\n\n- Shows sign in/sign up buttons when logged out\n- Displays user avatar with initials fallback when logged in\n- Animated badge indicator for unverified email\n- Links to chats, settings, and sign out action\n\n---\n\n## Profile Components\n\n### Profile Header\n\nDisplays user info with inline editing for name and profile image:\n\n```tsx\n// src/components/profile/profile-header.tsx\n\"use client\";\n\nimport { useSession, authClient } from \"@/lib/auth/client\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { useState } from \"react\";\nimport { Loader2, Pencil, X, Check } from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport Image from \"next/image\";\n\nexport function ProfileHeader() {\n  const { data: session, isPending } = useSession();\n  const [isEditing, setIsEditing] = useState(false);\n  const [name, setName] = useState(\"\");\n  const [image, setImage] = useState<File | null>(null);\n  const [imagePreview, setImagePreview] = useState<string | null>(null);\n  const [loading, setLoading] = useState(false);\n\n  if (isPending) {\n    return (\n      <Card>\n        <CardContent className=\"flex items-center justify-center py-12\">\n          <Loader2 className=\"size-6 animate-spin text-muted-foreground\" />\n        </CardContent>\n      </Card>\n    );\n  }\n\n  if (!session) {\n    return null;\n  }\n\n  const user = session.user;\n  const initials = user.name\n    .split(\" \")\n    .map((n) => n[0])\n    .join(\"\")\n    .toUpperCase()\n    .slice(0, 2);\n\n  const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const file = e.target.files?.[0];\n    if (file) {\n      setImage(file);\n      const reader = new FileReader();\n      reader.onloadend = () => {\n        setImagePreview(reader.result as string);\n      };\n      reader.readAsDataURL(file);\n    }\n  };\n\n  const handleStartEditing = () => {\n    setName(user.name);\n    setImagePreview(user.image || null);\n    setIsEditing(true);\n  };\n\n  const handleCancel = () => {\n    setIsEditing(false);\n    setName(\"\");\n    setImage(null);\n    setImagePreview(null);\n  };\n\n  const handleSave = async () => {\n    setLoading(true);\n    try {\n      let imageData: string | undefined;\n      if (image) {\n        imageData = await convertImageToBase64(image);\n      }\n\n      const { error } = await authClient.updateUser({\n        name: name || undefined,\n        image: imageData,\n      });\n\n      if (error) {\n        toast.error(error.message);\n        return;\n      }\n\n      toast.success(\"Profile updated successfully\");\n      setIsEditing(false);\n      setImage(null);\n      setImagePreview(null);\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  return (\n    <Card>\n      <CardHeader>\n        <div className=\"flex items-center justify-between\">\n          <div>\n            <CardTitle>Profile</CardTitle>\n            <CardDescription>Your account information</CardDescription>\n          </div>\n          {!isEditing && (\n            <Button variant=\"outline\" size=\"sm\" onClick={handleStartEditing}>\n              <Pencil className=\"size-4\" />\n              Edit\n            </Button>\n          )}\n        </div>\n      </CardHeader>\n      <CardContent>\n        {isEditing ? (\n          <div className=\"space-y-4\">\n            <div className=\"flex items-start gap-4\">\n              <div className=\"relative\">\n                {imagePreview ? (\n                  <div className=\"relative size-20 rounded-full overflow-hidden\">\n                    <Image\n                      src={imagePreview}\n                      alt=\"Profile preview\"\n                      fill\n                      className=\"object-cover\"\n                    />\n                  </div>\n                ) : (\n                  <Avatar className=\"size-20\">\n                    <AvatarFallback className=\"text-lg\">\n                      {initials}\n                    </AvatarFallback>\n                  </Avatar>\n                )}\n              </div>\n              <div className=\"flex-1 space-y-2\">\n                <Label htmlFor=\"profile-image\">Profile Image</Label>\n                <div className=\"flex items-center gap-2\">\n                  <Input\n                    id=\"profile-image\"\n                    type=\"file\"\n                    accept=\"image/*\"\n                    onChange={handleImageChange}\n                  />\n                  {imagePreview && (\n                    <Button\n                      variant=\"ghost\"\n                      size=\"icon-sm\"\n                      onClick={() => {\n                        setImage(null);\n                        setImagePreview(null);\n                      }}\n                    >\n                      <X className=\"size-4\" />\n                    </Button>\n                  )}\n                </div>\n              </div>\n            </div>\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"name\">Name</Label>\n              <Input\n                id=\"name\"\n                value={name}\n                onChange={(e) => setName(e.target.value)}\n                placeholder=\"Your name\"\n              />\n            </div>\n            <div className=\"flex gap-2\">\n              <Button onClick={handleSave} disabled={loading}>\n                {loading ? (\n                  <Loader2 className=\"size-4 animate-spin\" />\n                ) : (\n                  <Check className=\"size-4\" />\n                )}\n                Save\n              </Button>\n              <Button\n                variant=\"outline\"\n                onClick={handleCancel}\n                disabled={loading}\n              >\n                Cancel\n              </Button>\n            </div>\n          </div>\n        ) : (\n          <div className=\"flex items-center gap-4\">\n            <Avatar className=\"size-20\">\n              <AvatarImage src={user.image || undefined} alt={user.name} />\n              <AvatarFallback className=\"text-lg\">{initials}</AvatarFallback>\n            </Avatar>\n            <div className=\"space-y-1\">\n              <p className=\"text-lg font-medium\">{user.name}</p>\n              <p className=\"text-sm text-muted-foreground\">{user.email}</p>\n              <Badge variant={user.emailVerified ? \"default\" : \"secondary\"}>\n                {user.emailVerified ? \"Verified\" : \"Unverified\"}\n              </Badge>\n            </div>\n          </div>\n        )}\n      </CardContent>\n    </Card>\n  );\n}\n\nasync function convertImageToBase64(file: File): Promise<string> {\n  return new Promise((resolve, reject) => {\n    const reader = new FileReader();\n    reader.onloadend = () => resolve(reader.result as string);\n    reader.onerror = reject;\n    reader.readAsDataURL(file);\n  });\n}\n```\n\n### Change Email\n\n```tsx\n// src/components/profile/change-email.tsx\n\"use client\";\n\nimport { useSession, authClient } from \"@/lib/auth/client\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { useState } from \"react\";\nimport { Loader2 } from \"lucide-react\";\nimport { toast } from \"sonner\";\n\nexport function ChangeEmail() {\n  const { data: session } = useSession();\n  const [newEmail, setNewEmail] = useState(\"\");\n  const [loading, setLoading] = useState(false);\n\n  const handleSubmit = async (e: React.FormEvent) => {\n    e.preventDefault();\n\n    if (!newEmail) {\n      toast.error(\"Please enter a new email address\");\n      return;\n    }\n\n    if (newEmail === session?.user.email) {\n      toast.error(\"New email must be different from current email\");\n      return;\n    }\n\n    setLoading(true);\n    try {\n      const { error } = await authClient.changeEmail({\n        newEmail,\n        callbackURL: \"/profile\",\n      });\n\n      if (error) {\n        toast.error(error.message);\n        return;\n      }\n\n      toast.success(\n        \"A confirmation email has been sent to your current email address\",\n      );\n      setNewEmail(\"\");\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  return (\n    <Card>\n      <CardHeader>\n        <CardTitle>Change Email</CardTitle>\n        <CardDescription>\n          Update your email address. You&apos;ll need to verify both your\n          current and new email.\n        </CardDescription>\n      </CardHeader>\n      <CardContent>\n        <form onSubmit={handleSubmit} className=\"space-y-4\">\n          <div className=\"space-y-2\">\n            <Label htmlFor=\"current-email\">Current Email</Label>\n            <Input\n              id=\"current-email\"\n              type=\"email\"\n              value={session?.user.email || \"\"}\n              disabled\n              className=\"bg-muted\"\n            />\n          </div>\n          <div className=\"space-y-2\">\n            <Label htmlFor=\"new-email\">New Email</Label>\n            <Input\n              id=\"new-email\"\n              type=\"email\"\n              value={newEmail}\n              onChange={(e) => setNewEmail(e.target.value)}\n              placeholder=\"new@example.com\"\n              required\n            />\n          </div>\n          <Button type=\"submit\" disabled={loading}>\n            {loading && <Loader2 className=\"size-4 animate-spin\" />}\n            Change Email\n          </Button>\n        </form>\n      </CardContent>\n    </Card>\n  );\n}\n```\n\n### Change Password\n\n```tsx\n// src/components/profile/change-password.tsx\n\"use client\";\n\nimport { authClient } from \"@/lib/auth/client\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport { useState } from \"react\";\nimport { Loader2 } from \"lucide-react\";\nimport { toast } from \"sonner\";\n\nexport function ChangePassword() {\n  const [currentPassword, setCurrentPassword] = useState(\"\");\n  const [newPassword, setNewPassword] = useState(\"\");\n  const [confirmPassword, setConfirmPassword] = useState(\"\");\n  const [revokeOtherSessions, setRevokeOtherSessions] = useState(true);\n  const [loading, setLoading] = useState(false);\n\n  const handleSubmit = async (e: React.FormEvent) => {\n    e.preventDefault();\n\n    if (newPassword !== confirmPassword) {\n      toast.error(\"New passwords do not match\");\n      return;\n    }\n\n    if (newPassword.length < 8) {\n      toast.error(\"Password must be at least 8 characters\");\n      return;\n    }\n\n    setLoading(true);\n    try {\n      const { error } = await authClient.changePassword({\n        currentPassword,\n        newPassword,\n        revokeOtherSessions,\n      });\n\n      if (error) {\n        toast.error(error.message);\n        return;\n      }\n\n      toast.success(\"Password changed successfully\");\n      setCurrentPassword(\"\");\n      setNewPassword(\"\");\n      setConfirmPassword(\"\");\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  return (\n    <Card>\n      <CardHeader>\n        <CardTitle>Change Password</CardTitle>\n        <CardDescription>\n          Update your password to keep your account secure\n        </CardDescription>\n      </CardHeader>\n      <CardContent>\n        <form onSubmit={handleSubmit} className=\"space-y-4\">\n          <div className=\"space-y-2\">\n            <Label htmlFor=\"current-password\">Current Password</Label>\n            <Input\n              id=\"current-password\"\n              type=\"password\"\n              value={currentPassword}\n              onChange={(e) => setCurrentPassword(e.target.value)}\n              autoComplete=\"current-password\"\n              required\n            />\n          </div>\n          <div className=\"space-y-2\">\n            <Label htmlFor=\"new-password\">New Password</Label>\n            <Input\n              id=\"new-password\"\n              type=\"password\"\n              value={newPassword}\n              onChange={(e) => setNewPassword(e.target.value)}\n              autoComplete=\"new-password\"\n              required\n            />\n          </div>\n          <div className=\"space-y-2\">\n            <Label htmlFor=\"confirm-password\">Confirm New Password</Label>\n            <Input\n              id=\"confirm-password\"\n              type=\"password\"\n              value={confirmPassword}\n              onChange={(e) => setConfirmPassword(e.target.value)}\n              autoComplete=\"new-password\"\n              required\n            />\n          </div>\n          <div className=\"flex items-center gap-2\">\n            <Checkbox\n              id=\"revoke-sessions\"\n              checked={revokeOtherSessions}\n              onCheckedChange={(checked) =>\n                setRevokeOtherSessions(checked === true)\n              }\n            />\n            <Label htmlFor=\"revoke-sessions\" className=\"text-sm font-normal\">\n              Sign out from all other devices\n            </Label>\n          </div>\n          <Button type=\"submit\" disabled={loading}>\n            {loading && <Loader2 className=\"size-4 animate-spin\" />}\n            Change Password\n          </Button>\n        </form>\n      </CardContent>\n    </Card>\n  );\n}\n```\n\n### Session Management\n\n```tsx\n// src/components/profile/sessions.tsx\n\"use client\";\n\nimport { authClient } from \"@/lib/auth/client\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\";\nimport { useState } from \"react\";\nimport { Loader2, LogOut } from \"lucide-react\";\nimport { toast } from \"sonner\";\n\nexport function Sessions() {\n  const [loading, setLoading] = useState(false);\n\n  const handleRevokeOtherSessions = async () => {\n    setLoading(true);\n    try {\n      const { error } = await authClient.revokeOtherSessions();\n\n      if (error) {\n        toast.error(error.message);\n        return;\n      }\n\n      toast.success(\"All other sessions have been signed out\");\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  return (\n    <Card>\n      <CardHeader>\n        <CardTitle>Active Sessions</CardTitle>\n        <CardDescription>\n          Manage your active sessions across devices\n        </CardDescription>\n      </CardHeader>\n      <CardContent className=\"space-y-4\">\n        <p className=\"text-sm text-muted-foreground\">\n          If you notice any suspicious activity or want to secure your account,\n          you can sign out from all other devices.\n        </p>\n        <Button\n          variant=\"outline\"\n          onClick={handleRevokeOtherSessions}\n          disabled={loading}\n        >\n          {loading ? (\n            <Loader2 className=\"size-4 animate-spin\" />\n          ) : (\n            <LogOut className=\"size-4\" />\n          )}\n          Sign out other devices\n        </Button>\n      </CardContent>\n    </Card>\n  );\n}\n```\n\n### Resend Verification\n\nShows only when email is not verified:\n\n```tsx\n// src/components/profile/resend-verification.tsx\n\"use client\";\n\nimport { useSession, authClient } from \"@/lib/auth/client\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\";\nimport { useState } from \"react\";\nimport { Loader2, Mail, CheckCircle } from \"lucide-react\";\nimport { toast } from \"sonner\";\n\nexport function ResendVerification() {\n  const { data: session } = useSession();\n  const [loading, setLoading] = useState(false);\n\n  if (!session || session.user.emailVerified) {\n    return null;\n  }\n\n  const handleResend = async () => {\n    setLoading(true);\n    try {\n      const { error } = await authClient.sendVerificationEmail({\n        email: session.user.email,\n        callbackURL: \"/profile\",\n      });\n\n      if (error) {\n        toast.error(error.message);\n        return;\n      }\n\n      toast.success(\"Verification email sent\");\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  return (\n    <Card className=\"border-amber-500/50 bg-amber-500/5\">\n      <CardHeader>\n        <CardTitle className=\"flex items-center gap-2\">\n          <Mail className=\"size-5 text-amber-600\" />\n          Verify Your Email\n        </CardTitle>\n        <CardDescription>\n          Your email address has not been verified yet. Please check your inbox\n          for a verification link.\n        </CardDescription>\n      </CardHeader>\n      <CardContent className=\"flex items-center gap-4\">\n        <Button onClick={handleResend} disabled={loading}>\n          {loading ? (\n            <Loader2 className=\"size-4 animate-spin\" />\n          ) : (\n            <CheckCircle className=\"size-4\" />\n          )}\n          Resend Verification Email\n        </Button>\n      </CardContent>\n    </Card>\n  );\n}\n```\n\n### Delete Account\n\n```tsx\n// src/components/profile/delete-account.tsx\n\"use client\";\n\nimport { authClient } from \"@/lib/auth/client\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport {\n  AlertDialog,\n  AlertDialogAction,\n  AlertDialogCancel,\n  AlertDialogContent,\n  AlertDialogDescription,\n  AlertDialogFooter,\n  AlertDialogHeader,\n  AlertDialogTitle,\n  AlertDialogTrigger,\n} from \"@/components/ui/alert-dialog\";\nimport { useState } from \"react\";\nimport { Loader2, AlertTriangle } from \"lucide-react\";\nimport { toast } from \"sonner\";\n\nexport function DeleteAccount() {\n  const [password, setPassword] = useState(\"\");\n  const [confirmText, setConfirmText] = useState(\"\");\n  const [loading, setLoading] = useState(false);\n  const [open, setOpen] = useState(false);\n\n  const canDelete = confirmText === \"DELETE\";\n\n  const handleDelete = async () => {\n    if (!canDelete) return;\n\n    setLoading(true);\n    try {\n      const { error } = await authClient.deleteUser({\n        password,\n        callbackURL: \"/\",\n      });\n\n      if (error) {\n        toast.error(error.message);\n        return;\n      }\n\n      toast.success(\n        \"A confirmation email has been sent to verify account deletion\",\n      );\n      setOpen(false);\n      setPassword(\"\");\n      setConfirmText(\"\");\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  return (\n    <Card className=\"border-destructive/50\">\n      <CardHeader>\n        <CardTitle className=\"text-destructive\">Delete Account</CardTitle>\n        <CardDescription>\n          Permanently delete your account and all associated data. This action\n          cannot be undone.\n        </CardDescription>\n      </CardHeader>\n      <CardContent>\n        <AlertDialog open={open} onOpenChange={setOpen}>\n          <AlertDialogTrigger asChild>\n            <Button variant=\"destructive\">\n              <AlertTriangle className=\"size-4\" />\n              Delete Account\n            </Button>\n          </AlertDialogTrigger>\n          <AlertDialogContent>\n            <AlertDialogHeader>\n              <AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>\n              <AlertDialogDescription>\n                This action cannot be undone. This will permanently delete your\n                account and remove all your data from our servers.\n              </AlertDialogDescription>\n            </AlertDialogHeader>\n            <div className=\"space-y-4 py-4\">\n              <div className=\"space-y-2\">\n                <Label htmlFor=\"delete-password\">Enter your password</Label>\n                <Input\n                  id=\"delete-password\"\n                  type=\"password\"\n                  value={password}\n                  onChange={(e) => setPassword(e.target.value)}\n                  placeholder=\"Your password\"\n                />\n              </div>\n              <div className=\"space-y-2\">\n                <Label htmlFor=\"confirm-delete\">\n                  Type <span className=\"font-mono font-bold\">DELETE</span> to\n                  confirm\n                </Label>\n                <Input\n                  id=\"confirm-delete\"\n                  type=\"text\"\n                  value={confirmText}\n                  onChange={(e) => setConfirmText(e.target.value)}\n                  placeholder=\"DELETE\"\n                />\n              </div>\n            </div>\n            <AlertDialogFooter>\n              <AlertDialogCancel\n                onClick={() => {\n                  setPassword(\"\");\n                  setConfirmText(\"\");\n                }}\n              >\n                Cancel\n              </AlertDialogCancel>\n              <AlertDialogAction\n                onClick={handleDelete}\n                disabled={!canDelete || loading || !password}\n                className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n              >\n                {loading && <Loader2 className=\"size-4 animate-spin\" />}\n                Delete Account\n              </AlertDialogAction>\n            </AlertDialogFooter>\n          </AlertDialogContent>\n        </AlertDialog>\n      </CardContent>\n    </Card>\n  );\n}\n```\n\n---\n\n## Profile Page\n\nCreate the account settings page that combines all profile components:\n\n```tsx\n// src/app/profile/page.tsx\nimport type { Metadata } from \"next\";\nimport { headers } from \"next/headers\";\nimport { redirect } from \"next/navigation\";\nimport { auth } from \"@/lib/auth/server\";\nimport { ProfileHeader } from \"@/components/profile/profile-header\";\nimport { ChangePassword } from \"@/components/profile/change-password\";\nimport { ChangeEmail } from \"@/components/profile/change-email\";\nimport { DeleteAccount } from \"@/components/profile/delete-account\";\nimport { Sessions } from \"@/components/profile/sessions\";\nimport { ResendVerification } from \"@/components/profile/resend-verification\";\nimport { Button } from \"@/components/ui/button\";\nimport { ArrowLeft } from \"lucide-react\";\nimport Link from \"next/link\";\n\nexport const metadata: Metadata = {\n  title: \"Account Settings\",\n  description:\n    \"Manage your profile, security settings, email preferences, and active sessions.\",\n};\n\nexport default async function ProfilePage() {\n  const session = await auth.api.getSession({\n    headers: await headers(),\n  });\n\n  if (!session) {\n    redirect(\"/sign-in\");\n  }\n\n  return (\n    <div className=\"min-h-dvh bg-muted/30\">\n      <header className=\"sticky top-0 z-50 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60\">\n        <div className=\"container flex h-14 items-center gap-4 max-w-2xl\">\n          <Link href=\"/chats\">\n            <Button variant=\"ghost\" size=\"icon-sm\">\n              <ArrowLeft className=\"size-4\" />\n            </Button>\n          </Link>\n          <h1 className=\"font-semibold\">Account Settings</h1>\n        </div>\n      </header>\n      <main className=\"container max-w-2xl py-8 px-4\">\n        <div className=\"space-y-6\">\n          <ResendVerification />\n          <ProfileHeader />\n          <ChangeEmail />\n          <ChangePassword />\n          <Sessions />\n          <DeleteAccount />\n        </div>\n      </main>\n    </div>\n  );\n}\n```\n\n---\n\n## File Structure\n\n```\nsrc/components/auth/\n  user-menu.tsx       # Dropdown with auth state\n\nsrc/components/profile/\n  profile-header.tsx    # User info with edit mode\n  change-email.tsx      # Email change form\n  change-password.tsx   # Password change form\n  sessions.tsx          # Session management\n  resend-verification.tsx # Email verification reminder\n  delete-account.tsx    # Account deletion with confirmation\n\nsrc/app/\n  profile/page.tsx    # Account settings page (protected)\n```"}