Claude-skill-registry auth-pages
Create and manage authentication pages with server-side session handling. Use when adding login, register, or protected pages WITHOUT flicker/skeleton.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/auth-pages" ~/.claude/skills/majiayu000-claude-skill-registry-auth-pages && rm -rf "$T"
manifest:
skills/data/auth-pages/SKILL.mdsource content
Authentication Pages (FSD)
Better Auth integration with Next.js 16 - Magic Link (passwordless) authentication.
Authentication Method
This project uses Magic Link authentication - users sign in by clicking a link sent to their email. No passwords!
FSD Paths
src/ ├── app/(auth)/ │ ├── login/ # Magic Link Login Page │ ├── magic-link/verify/ # Magic Link Verification UI │ └── verify-email/ # Email Verification UI ├── app/(protected)/ │ ├── dashboard/ # Protected Dashboard │ └── settings/ # Session Management ├── features/auth/ # Auth Feature │ ├── ui/ │ │ ├── login-form.tsx # Orchestrates login flow │ │ ├── login-card.tsx # Email input form │ │ └── email-sent-card.tsx # "Check your email" UI │ ├── model/ │ │ ├── use-login.ts # Login state & logic │ │ └── use-auth-sync.ts # Cross-tab sync │ └── index.ts ├── features/user-settings/ # Session Management │ ├── ui/ │ │ ├── sessions-list.tsx │ │ └── session-card.tsx │ ├── model/ │ │ └── use-sessions.ts │ └── index.ts ├── shared/lib/ │ ├── auth-client/ # Client: signIn.magicLink, signOut │ ├── auth-server/ # Server: getSession, auth config │ └── geo/ # User Agent parsing └── widgets/header/ # Header with UserMenu
Magic Link Login Flow
1. User enters email → /login 2. signIn.magicLink() called 3. Backend webhook sends email 4. User clicks link → /magic-link/verify?token=... 5. Token verified → Session created → Redirect to /dashboard 6. Login notification sent (new device only)
Auth Client (Magic Link)
import { signIn, signOut } from "@shared/lib/auth-client" // Request Magic Link await signIn.magicLink({ email, callbackURL: "/dashboard", newUserCallbackURL: "/dashboard", errorCallbackURL: "/login?error=verification_failed", }) // Sign Out await signOut()
Server-Side Session (NO FLICKER!)
Protected Page Pattern
// app/(protected)/dashboard/page.tsx - SERVER COMPONENT import { getSession } from "@shared/lib/auth-server" import { redirect } from "next/navigation" import { Header } from "@widgets/header" export default async function DashboardPage() { // Server-side Session Check - NO Flicker! const session = await getSession() if (!session) redirect("/login") return ( <div className="min-h-screen bg-background"> <Header user={session.user} /> {/* Content */} </div> ) }
Session Management
Users can view and revoke sessions at
/settings:
import { useSessions } from "@features/user-settings" export function SessionsList() { const { sessions, revokeSession, revokeOtherSessions } = useSessions() return ( <div> {sessions.map((session) => ( <SessionCard key={session.id} session={session} onRevoke={revokeSession} /> ))} <Button onClick={revokeOtherSessions}> Alle anderen Sessions beenden </Button> </div> ) }
Backend Webhooks
All emails are sent by the Go backend (Clean Architecture):
POST /api/v1/webhooks/send-magic-link POST /api/v1/webhooks/send-verification-email POST /api/v1/webhooks/session-created
Protected by
X-Webhook-Secret header.
Rate Limiting
- Magic Link: 3 requests per minute
- Verification Email: 3 requests per minute
Cross-Tab Synchronization
// features/auth/model/use-auth-sync.ts import { useAuthSync, broadcastSignOut } from "@features/auth" // In Header component useAuthSync() // Listen for auth changes // On sign out await signOut() await broadcastSignOut() // Notify other tabs
Magic Link Verify Page
Custom UI for
/magic-link/verify:
- Loading: Spinner while verifying
- Success: Immediate redirect to dashboard
- Rate Limited: "Zu viele Anfragen" message
- Expired: "Link abgelaufen" message
- Invalid: "Ungültiger Link" message
Login Notifications
Email sent on new device/IP:
- Checks if device/IP combination is known
- Only sends notification for NEW devices
- Includes "Sessions verwalten" button to
/settings
IMPORTANT: What NOT to do
❌ DO NOT use
useSession() in Protected Pages → Causes flicker
❌ DO NOT use password fields → Magic Link only
❌ DO NOT send emails from frontend → Use backend webhooks
❌ DO NOT use direct SQL in auth hooks → Use webhooks
✅ INSTEAD:
- Server Component checks session with
getSession()
if no sessionredirect()- Pass user as prop to Client Components
- All emails via backend webhooks