⚔️CritForge
🔔

Authentication & Notifications

Configure authentication and notification settings

authnotificationssettings

Overview

CritForge's auth notification system provides visual feedback for authentication events using toast notifications. It addresses the UX gap where users received no confirmation after completing auth actions like email verification or password reset.

Architecture

Components

AuthNotifications Component

Location: src/components/auth/AuthNotifications.tsx

Client component that monitors URL query parameters and displays toast notifications for auth events.

Features:

  • Monitors URL query params for auth success/error states
  • Uses Sonner toast library (already integrated in CritForge)
  • Themed toasts with parchment gradient backgrounds
  • Custom icons per auth event type
  • Auto-dismisses after 4-5 seconds
  • No visual UI - pure side-effects component

Supported Query Parameters:

ParameterTriggerNotification
verified=trueEmail verification (new user)Email verification success
welcome=trueNew user signupEnhanced welcome message
password_reset=truePassword reset completionPassword updated confirmation
email_updated=trueEmail change confirmationEmail update success
magic_link=trueMagic link authenticationMagic link login success
reauth=trueSession renewalSession renewed confirmation
error=*Auth errorsError notification (various types)

Toast Styling:

  • Success toasts use gradient backgrounds (green/blue/purple/amber to parchment)
  • Custom Lucide icons per event type
  • Themed to match CritForge's D&D parchment aesthetic
  • Accessible with ARIA live regions (handled by Sonner)

Integration Points

Layout Integration

Location: src/app/[locale]/layout.tsx

<Suspense fallback={null}>
  <AuthNotifications />
</Suspense>
  • Wrapped in Suspense boundary (required for useSearchParams())
  • Global scope - monitors all pages for auth params
  • Silent fallback (no loading state needed)
Auth Confirmation Route

Location: src/app/api/auth/confirm/route.ts

Enhanced to handle multiple auth types:

switch (type) {
  case 'signup':
    redirectTo.searchParams.set('welcome', 'true');
    redirectTo.searchParams.set('verified', 'true');
    break;
  case 'email_change':
    redirectTo.searchParams.set('email_updated', 'true');
    break;
  case 'recovery':
    // Redirects to reset-password page
    break;
  case 'magiclink':
    redirectTo.searchParams.set('magic_link', 'true');
    break;
}
Password Reset Flow

Location: src/app/[locale]/reset-password/page.tsx

After successful password update:

router.push("/generate/npc?password_reset=true");

Internationalization

Location: src/locales/*/auth.json

All auth notifications are fully translated across 5 locales:

  • en-US - English (United States)
  • fr-FR - French (France)
  • es-ES - Spanish (Spain)
  • de-DE - German (Germany)
  • pt-BR - Portuguese (Brazil)

Translation Keys:

{
  "auth": {
    "notifications": {
      "emailVerified": "Email Verified Successfully",
      "emailVerifiedDescription": "Your email has been confirmed...",
      "emailVerifiedWelcome": "Welcome to CritForge!",
      "emailVerifiedWelcomeDescription": "Your email is verified...",
      "passwordReset": "Password Reset Complete",
      "passwordResetDescription": "Your password has been updated...",
      "error": {
        "generic": "Authentication Error",
        "verificationFailed": "Verification Failed",
        "invalidLink": "Invalid Link",
        "sessionExpired": "Session Expired",
        "rateLimit": "Too Many Requests"
      }
    }
  }
}

User Flows

Email Verification (New User)

  1. User signs up at /signup
  2. Backend sends verification email via Supabase
  3. User clicks link in email
  4. Supabase redirects to /api/auth/confirm?token_hash=...&type=signup
  5. Backend verifies token and redirects to /generate/npc?welcome=true&verified=true
  6. AuthNotifications component detects params
  7. Toast displays: "Welcome to CritForge!" with celebratory message
  8. Auto-dismisses after 5 seconds

Password Reset

  1. User requests reset at /reset-password
  2. User receives email with recovery link
  3. User clicks link → redirects to /api/auth/confirm?token_hash=...&type=recovery
  4. Backend redirects to /reset-password?type=recovery
  5. User sets new password
  6. Page redirects to /generate/npc?password_reset=true
  7. Toast displays: "Password Reset Complete"

Email Change

  1. User changes email in settings
  2. Supabase sends confirmation email
  3. User clicks link → /api/auth/confirm?token_hash=...&type=email_change
  4. Backend redirects to /settings?email_updated=true
  5. Toast displays: "Email Address Updated"
  1. User requests magic link at login
  2. User clicks link in email → /api/auth/confirm?token_hash=...&type=magiclink
  3. Backend redirects to /dashboard?magic_link=true (or custom next URL)
  4. Toast displays: "Successfully Signed In"

Design Decisions

Why Toast Notifications?

Considered Approaches:

  1. Toast/Notification (Chosen)
  2. Banner (Persistent at top)
  3. Modal Dialog (Blocking)

Rationale:

  • Non-blocking: Users can immediately interact with the page
  • Celebratory: Success events deserve positive reinforcement
  • Consistent: Matches existing toast usage in CritForge (save success, errors, etc.)
  • Accessible: Sonner provides ARIA live regions out-of-the-box
  • Auto-dismissing: Reduces UI clutter after initial confirmation

Why Query Parameters?

Alternatives Considered:

  • Session storage (not SSR-friendly)
  • Cookies (requires additional cleanup)
  • Global state (overkill for transient notifications)

Benefits:

  • Works with server-side redirects
  • No additional state management
  • URL parameters are ephemeral (disappear on navigation)
  • Easy to debug (visible in URL)

Redirect Destinations

Auth EventRedirect ToReason
Email verification (new user)/generate/npcImmediately engage user with core feature
Password reset/generate/npcReturn to productive state
Email change/settingsKeep user in settings context
Magic link/dashboard or customFlexible based on user intent

Theme Integration

Parchment Gradients

Each auth event type uses a themed gradient that transitions to CritForge's parchment background:

// Email verification
className: "border-green-200 bg-gradient-to-br from-green-50 to-amber-50"

// Password reset
className: "border-blue-200 bg-gradient-to-br from-blue-50 to-amber-50"

// Email update
className: "border-purple-200 bg-gradient-to-br from-purple-50 to-amber-50"

// Magic link
className: "border-amber-200 bg-gradient-to-br from-amber-50 to-yellow-50"

Icons

Custom Lucide icons per event type:

  • Email verification: CheckCircle2 (green)
  • Password reset: Key (blue)
  • Email update: Mail (purple)
  • Magic link: Sparkles (amber)
  • Reauthentication: Shield (indigo)

Future Enhancements

Potential Additions

  1. OAuth Success: Add notifications for Google/Discord login
  2. 2FA Events: Confirm 2FA setup/disable
  3. Account Deletion: Confirm account deletion request sent
  4. Trial Conversion: Celebrate upgrade from trial to premium
  5. Reward Unlocks: Notify when beta tester rewards are granted

Analytics Integration

Track notification engagement:

  • Which auth events users complete most
  • Time between email send and verification click
  • A/B test different notification copy

Customization Options

Future user preferences:

  • Disable auth notifications (for power users)
  • Sound effects on success (optional)
  • Persistent notifications until dismissed (accessibility option)

Testing

Manual Testing Checklist

Email Verification:

  1. Sign up with new email
  2. Click verification link in email
  3. Verify "Welcome to CritForge!" toast appears
  4. Check toast auto-dismisses after 5 seconds

Password Reset:

  1. Request password reset
  2. Click link in email
  3. Set new password
  4. Verify "Password Reset Complete" toast appears on redirect

Error States:

  1. Use expired verification link
  2. Verify error toast appears on login page
  3. Check error message is descriptive

Automated Testing

E2E Test Pattern (Playwright):

test('email verification shows success toast', async ({ page }) => {
  await page.goto('/generate/npc?verified=true&welcome=true');

  // Wait for toast to appear
  await expect(page.getByRole('status')).toContainText('Welcome to CritForge!');

  // Verify toast auto-dismisses
  await expect(page.getByRole('status')).toBeHidden({ timeout: 6000 });
});

Troubleshooting

Toast Not Appearing

Possible Causes:

  1. Sonner not loaded (check <Toaster /> in layout)
  2. Suspense boundary missing (causes hydration error)
  3. Translation keys missing in locale file
  4. Query params not set in redirect URL

Debug Steps:

// Add to AuthNotifications component
useEffect(() => {
  console.log('[AUTH_NOTIFICATIONS] Query params:', {
    verified: searchParams?.get('verified'),
    welcome: searchParams?.get('welcome'),
    // ... other params
  });
}, [searchParams]);

Duplicate Toasts

Cause: React Strict Mode triggers effects twice in development

Solution: Sonner automatically deduplicates, but verify with:

toast.success(message, {
  id: 'email-verified', // Unique ID prevents duplicates
  // ... other options
});

Translation Missing

Error: [missing: "auth.notifications.emailVerified" translation]

Fix: Ensure all locale files have complete auth.notifications object.

  • Sonner Configuration: src/components/ui/sonner.tsx
  • Auth Flow: src/app/api/auth/confirm/route.ts
  • Theme System: docs/architecture/design-system.md
  • i18n Setup: src/i18n/routing.ts

Changelog

2026-02-04 - Initial Implementation

  • Created AuthNotifications component
  • Added i18n translations for 5 locales
  • Enhanced auth confirmation route
  • Integrated into layout with Suspense boundary
  • Documented auth notification system