Skip to main content

Authentication Pages

The authentication pages live under the (auth) route group and handle login, registration, password recovery, and error display. All auth pages are public (no authentication required) and share a common AuthLayout wrapper. Each page follows the server component + client component split pattern.

Route Structure

/[locale]/(auth)/
login/
page.tsx # Server: redirect if authenticated, render LoginClient
login-client.tsx # Client: login form with social login
register/
page.tsx # Server: render RegisterForm
register-form.tsx # Client: registration form with validation
forgot-password/
page.tsx # Server: render ForgotPasswordForm
forgot-password-form.tsx # Client: email input with success state
reset-password/
page.tsx # Server: render ResetPasswordForm
reset-password-form.tsx # Client: new password form with token validation
auth/error/
page.tsx # Server: render AuthErrorClient
auth-error-content.tsx # Client: error display with contextual actions

Login Page

Route: /login

Server Component (page.tsx)

Checks authentication status before rendering. If the user is already authenticated, redirects to the dashboard using the locale-aware redirect() from next-intl/navigation.

const user = await getAuthFromCookie();
if (user) {
return redirect({ locale, href: ROUTES.DASHBOARD });
}

Wraps LoginClient in a Suspense boundary with a loading placeholder (pulsing circle).

Client Component (login-client.tsx)

Form Fields:

FieldTypeValidation
EmailemailRequired, HTML5 email validation
PasswordpasswordRequired

Features:

FeatureDescription
Password reset bannerShown when ?reset=true query param is present; auto-hides after 10 seconds
Redirect supportReads redirect_uri from search params; passes to login server action
Social loginRenders SocialLoginButtons component below a divider
Forgot password linkInline link next to the password label
Registration linkFooter link to the register page
Theme toggleThemeToggle component in the form header

Server Action: login(email, password, redirectUrl) from src/app/actions/auth.ts. On success, the server action sets auth cookies and redirects. On failure, an error banner is shown.

State Management: Uses useTransition for the form submission, disabling all inputs and showing a loading state on the submit button.

Register Page

Route: /register

Client Component (register-form.tsx)

Form Fields:

FieldTypeValidation
NametextRequired
EmailemailRequired
PasswordpasswordRequired, minimum 8 characters
Confirm PasswordpasswordRequired, must match password
Terms CheckboxcheckboxRequired (HTML5 required attribute)

Client-Side Validations (before calling server action):

  1. Password and confirm password must match
  2. Password must be at least 8 characters

Additional Elements:

  • Terms of service and privacy policy links (to /terms and /privacy)
  • Social sign-up buttons via SocialLoginButtons
  • Login link in the footer for existing users

Server Action: register(name, email, password) from src/app/actions/auth.ts. On success, the server action sets auth cookies and redirects to the dashboard.

Forgot Password Page

Route: /forgot-password

Client Component (forgot-password-form.tsx)

States:

StateDisplay
InitialEmail input form with submit button
SuccessEmail sent confirmation with check-spam note and back-to-login link
ErrorRed error banner above the form

Form Fields:

FieldTypeValidation
EmailemailRequired

Server Action: forgotPassword(email) from src/app/actions/auth.ts. On success, transitions to the success view showing which email address received the reset link.

Submit Button: Disabled when the email field is empty or the submission is pending.

Reset Password Page

Route: /reset-password

Client Component (reset-password-form.tsx)

Reads the token query parameter from the URL via useSearchParams(). The component is wrapped in a Suspense boundary because useSearchParams() requires it.

Token Validation:

ConditionDisplay
No token in URLError panel with "Request new link" button linking to forgot-password
Token presentPassword reset form
Submission successfulSuccess panel with "Log in" button

Form Fields:

FieldTypeValidation
New PasswordpasswordRequired
Confirm PasswordpasswordRequired, must match new password

Server Action: resetPassword(token, password) from src/app/actions/auth.ts. On success, redirects to /login?reset=true which triggers the success banner on the login page.

Auth Error Page

Route: /auth/error

Client Component (auth-error-content.tsx)

A centralized error display page that handles 16 distinct error types based on the ?error query parameter.

Error Categories:

CategoryError TypesIcon Color
OAuthoauth_missing_code, oauth_invalid_state, oauth_unsupported_provider, oauth_callbackWarning (yellow)
Credentialsinvalid_credentialsDanger (red)
Accountemail_not_verified, account_lockedDanger (red)
Sessionsession_expiredDanger (red)
Networknetwork_errorDanger (red)
Password Resetreset_password_missing_token, reset_password_invalid_token, reset_password_expired_token, reset_password_failedWarning (yellow)
Email Verificationverify_email_missing_token, verify_email_invalid_token, verify_email_expired_token, verify_email_failedWarning (yellow)
Authorizationauthorize_invalid_redirect_urlWarning (yellow)
GenericAny unknown error typeDanger (red)

Contextual Action Buttons: The page dynamically renders action buttons based on the error type:

Error TypePrimary ActionSecondary Action
email_not_verifiedResend verification emailBack to login
account_lockedContact supportBack to login
reset_password_*Request new reset linkBack to login
verify_email_*Resend verification emailBack to login
oauth_*Back to loginTry register
OtherBack to login--

Shared Components

AuthLayout

All auth pages wrap their content in AuthLayout, which provides a centered card layout with a title and subtitle.

interface AuthLayoutProps {
title: string;
subtitle: string;
children: React.ReactNode;
}

SocialLoginButtons

Renders OAuth login/signup buttons (currently GitHub and Google). Each button initiates the OAuth flow via the connectProvider server action from src/app/actions/auth.ts.

Server Actions Summary

ActionDescription
loginAuthenticates with email/password, sets cookies, redirects
registerCreates account, sets cookies, redirects
forgotPasswordSends password reset email
resetPasswordValidates token and sets new password
connectProviderInitiates OAuth flow for social login

Common Patterns

Error Display: All forms use the same error banner pattern:

{
error && (
<div className="bg-danger/10 border border-danger/20 text-danger px-4 py-3 rounded-lg text-sm">{error}</div>
);
}

Pending State: Every form uses useTransition with startTransition to handle server action calls. During pending state, all inputs are disabled and the submit button shows a loading indicator.

Navigation: All internal links use the locale-aware Link component from @/i18n/navigation and reference routes from ROUTES constants. This ensures links automatically include the current locale prefix.