LoginGen Dokumentation

Einführung

LoginGen ist eine Vorlagen-Website für Login-Seiten. Der Grund für die Entwicklung dieses Projekts ist, dass es zwar viele Vorlagen-Websites auf dem Markt gibt, die meisten jedoch keine ausreichende Unterstützung für Login-Seiten bieten oder nur ein oder zwei einfache Vorlagen enthalten, oft ohne vollständige Frontend-Logik. Obwohl Login-Seiten in Bezug auf die Interaktionsgewichtung möglicherweise nicht so wichtig sind wie Landing Pages, kann eine ansprechende Login-Seite den ersten Eindruck der Nutzer von einer Website deutlich verbessern.

Die Technologie-Stack basiert hauptsächlich auf Next.js und Shadcn/ui. Neben den Vorlagen bietet LoginGen auch eine vollständige Frontend-Logik und nutzt die Server Actions-Funktionalität von Next.js für eine einheitliche serverseitige Authentifizierung (mit Ausnahme der sozialen Anmeldung, die aus Gründen der Benutzerfreundlichkeit als Client-seitiges Ereignis implementiert ist).

Der gesamte Code ist offen und kann wie bei Shadcn einfach kopiert und eingefügt werden, sodass Sie ihn nach den Anforderungen Ihres Projekts anpassen können – was auch empfohlen wird. Zur Vereinfachung wurden zudem einige häufig verwendete Eigenschaften der Formularkomponenten extrahiert, sodass sie sofort einsatzbereit sind.

In Zukunft werden kontinuierlich weitere Vorlagen hinzugefügt, verbessert und optimiert. Bleiben Sie gespannt!

Installation

Die Vorlagen basieren auf Next.js und Shadcn. Daher benötigen Sie zunächst die entsprechende Projektumgebung:

Shadcn-Komponenten

Falls Sie andere Paketmanager verwenden oder die Komponenten manuell installieren möchten, lesen Sie bitte die Shadcn-Dokumentation.

pnpm dlx shadcn@latest add card tabs form button input input-otp separator sonner

Fügen Sie die folgenden CSS-Animationen zu Ihrer tailwind.config.js-Datei hinzu:

// for input-otp
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    extend: {
      keyframes: {
        'caret-blink': {
          '0%,70%,100%': { opacity: '1' },
          '20%,50%': { opacity: '0' }
        }
      },
      animation: {
        'caret-blink': 'caret-blink 1.25s ease-out infinite'
      }
    }
  }
}

Für Sonner müssen Sie die folgende Komponente hinzufügen:

import { Toaster } from '@/components/ui/sonner'
 
export default function RootLayout({ children }) {
  return (
    <html lang='en'>
      <head />
      <body>
        <main>{children}</main>
        <Toaster />
      </body>
    </html>
  )
}

Drittanbieter-Bibliotheken

pnpm add react-hook-form@7.52.2 zod motion @zxcvbn-ts/core @zxcvbn-ts/language-common @zxcvbn-ts/language-en embla-carousel-react embla-carousel-autoplay embla-carousel-fade lucide-react
pnpm add -D embla-carousel
  • react-hook-form + zod – Client-seitige Formularvalidierung
  • motion – Animationsbibliothek
  • @zxcvbn-* – Bibliothek zur Passwortstärkeüberprüfung
  • embla-carousel-* – Karussell-Bibliothek (embla-carousel muss in devDependencies installiert werden, um die TypeScript-Typen korrekt zu erhalten)
  • lucide-react – Icon-Bibliothek

Code kopieren und einfügen

Jede Vorlagen-Vorschauseite zeigt den vollständigen Code an. Sie können den benötigten Code einfach kopieren und an der entsprechenden Stelle in Ihrem Projekt einfügen. Die in den Vorlagen enthaltenen Bilder können direkt heruntergeladen werden, und Videos werden über CDN bereitgestellt.

Derzeit gibt es keine npx-ähnliche Ein-Klick-Installationsfunktion, dies könnte jedoch in Zukunft implementiert werden.

Design

Jede Vorlage enthält eine styles/theme.module.css-Datei, die alle Designvariablen sowie die für die Vorlage erforderlichen Stile und Animationen enthält. Sie können die Stile in dieser Datei anpassen, um das Design zu ändern oder es an die UI-Ästhetik Ihrer Website anzupassen.

Dunkelmodus

Für den Dunkelmodus folgen Sie bitte der Shadcn-Dokumentation. In den theme.module.css-Dateien der Vorlagen wird das Dunkeldesign mit dem :global(.dark)-CSS-Selektor versehen, um auf den globalen Dunkelmodus der Website zu reagieren.

I18n (TODO)

Derzeit wird die Mehrsprachigkeit noch nicht unterstützt, Sie können sie jedoch manuell hinzufügen, auch wenn dies etwas aufwändiger sein kann. Diese Funktion wird möglicherweise in Zukunft implementiert.

Formulareigenschaften

Es gibt fünf Formulare: Anmeldung, Registrierung, Passwort vergessen, Passwort zurücksetzen und OTP (One-Time Password)-Verifizierung. Jedes Formular verfügt über einige Parameter, die sofort einsatzbereit sind. Die meisten Parameter sind allgemein gültig.

Obwohl in den Vorlagen jedes Formular standardmäßig eine separate Route ist und die Navigation zwischen den Formularseiten serverseitig über Weiterleitungen erfolgt, sind alle Komponenten so gestaltet, dass sie Eigenschaften übergeben können. Das bedeutet, dass Sie auch Client-seitiges Routing verwenden können.

Anmeldung

Die Schnittstelle ist wie folgt definiert:

const _auths = ['social', 'email', 'password'] as const
type Auth = (typeof _auths)[number]
 
export interface SignInFormProps {
  auths?: Readonly<Auth[]>
  socials?: SocialKey[]
  email?: string
  emailStrategy?: 'magic-link' | 'one-time-pwd'
  socialHandler?: (event: MouseEvent<HTMLButtonElement>, key: SocialKey) => void | Promise<void>
  forgetHandler?: string | ((event: React.MouseEvent<HTMLAnchorElement>) => void | Promise<void>) // for more convenient use
  serverAction?: (
    formType: 'email' | 'password',
    currentState: SignInActionState,
    formData: FormData
  ) => Promise<SignInActionState>
  serverStateSuccessHandler?: (formType: 'email' | 'password', email: string) => void | Promise<void>
}
ParameterStandardwertErklärung
auths['social', 'password', 'email']Authentifizierungsmethoden: Soziale Anmeldung, E-Mail-Anmeldung, Passwort-Anmeldung
socials['google', 'github']Arten der sozialen Anmeldung (das Layout passt sich automatisch an die Anzahl der ausgewählten Optionen und die Formularbreite an)
emailInitiale E-Mail-Adresse, kann auch zur Vorabfüllung verwendet werden, wenn von der OTP-Verifizierungsseite zurückgekehrt wird
emailStrategy'magic-link'Art der gesendeten E-Mail: Bei 'magic-link' erfolgt keine Seitenumleitung, sondern ein Sonner-Popup. Andernfalls wird zur OTP-Verifizierungsseite weitergeleitet
socialHandlerCallback-Funktion beim Klicken auf den sozialen Anmeldebutton (z. B. mit Bibliotheken wie Auth.js implementierbar)
forgetHandler'#'Callback beim Klicken auf "Passwort vergessen" (dient hauptsächlich der Benutzerfreundlichkeit)
serverActionAlle Formulare (außer soziale Anmeldung) werden über Server Actions serverseitig übermittelt
serverStateSuccessHandlerNormalerweise erfolgt nach erfolgreicher serverseitiger Authentifizierung eine serverseitige Weiterleitung. Falls Sie Client-seitige Weiterleitungslogik implementieren möchten, können Sie diesen Callback verwenden

Hinweise:

  1. socials – Jede Vorlage enthält eine config/social.tsx-Konfigurationsdatei, die Sie bearbeiten können, um zusätzliche soziale Anmeldemethoden hinzuzufügen. Sie können den key an Ihr Authentifizierungsframework anpassen und das SVG-Icon nach Belieben ändern.
  2. email – In der verify-otp-Formular-UI gibt es eine Schaltfläche zum Ändern der E-Mail-Adresse. Wenn der Benutzer darauf klickt, sollte er zur vorherigen Seite zurückkehren, um die E-Mail-Adresse zu korrigieren. Der email-Parameter dient dazu, die vorherige E-Mail-Adresse vorab anzuzeigen.

Registrierung

Die Schnittstelle ist wie folgt definiert:

export interface SignUpFormProps {
  email?: string
  serverAction: (currentState: SignUpActionState, formData: FormData) => Promise<SignUpActionState>
  serverStateSuccessHandler?: (email: string) => void | Promise<void>
}
ParameterStandardwertErklärung
emailInitiale E-Mail-Adresse, kann auch zur Vorabfüllung verwendet werden, wenn von der OTP-Verifizierungsseite zurückgekehrt wird
serverActionFormulardaten werden über Server Actions serverseitig übermittelt
serverStateSuccessHandlerNormalerweise erfolgt nach erfolgreicher serverseitiger Authentifizierung eine serverseitige Weiterleitung. Falls Sie Client-seitige Weiterleitungslogik implementieren möchten, können Sie diesen Callback verwenden

Passwort vergessen

Die Schnittstelle ist wie folgt definiert:

export interface ForgetPasswordProps {
  email?: string
  emailStrategy?: 'magic-link' | 'one-time-pwd'
  serverAction: (
    currentState: ForgetPasswordActionState,
    formData: FormData
  ) => Promise<ForgetPasswordActionState>
  serverStateSuccessHandler?: (email: string) => void | Promise<void>
}
ParameterStandardwertErklärung
emailInitiale E-Mail-Adresse, kann auch zur Vorabfüllung verwendet werden, wenn von der OTP-Verifizierungsseite zurückgekehrt wird
emailStrategy'magic-link'Art der gesendeten E-Mail: Bei 'magic-link' erfolgt keine Seitenumleitung, sondern ein Sonner-Popup. Andernfalls wird zur OTP-Verifizierungsseite weitergeleitet
serverActionFormulardaten werden über Server Actions serverseitig übermittelt
serverStateSuccessHandlerNormalerweise erfolgt nach erfolgreicher serverseitiger Authentifizierung eine serverseitige Weiterleitung. Falls Sie Client-seitige Weiterleitungslogik implementieren möchten, können Sie diesen Callback verwenden

Passwort zurücksetzen

Die Schnittstelle ist wie folgt definiert:

export interface ResetPasswordFormProps {
  email?: string // Only used to test password strength
  resetToken?: string
  serverAction: (
    resetToken: string,
    currentState: ResetPasswordActionState,
    formData: FormData
  ) => Promise<ResetPasswordActionState>
  serverStateSuccessHandler?: () => void | Promise<void>
}
ParameterStandardwertErklärung
emailDiese E-Mail dient nur zur Überprüfung der Passwortstärke (empfohlen für bessere Passworteingaben der Benutzer)
resetTokenVom Server generiertes Token zur Verfolgung des Formularablaufs
serverActionFormulardaten werden über Server Actions serverseitig übermittelt
serverStateSuccessHandlerNormalerweise erfolgt nach erfolgreicher serverseitiger Authentifizierung eine serverseitige Weiterleitung. Falls Sie Client-seitige Weiterleitungslogik implementieren möchten, können Sie diesen Callback verwenden

resetToken Im Passwort-zurücksetzen-Ablauf generiert der Server normalerweise ein token, um den Absender des Formulars und dessen Status sicher zu verfolgen und zu bestätigen.

Der Server übermittelt das token typischerweise auf zwei Arten: entweder als URL-Abfrageparameter oder im cookie. Beim Absenden des Formulars überträgt der Browser automatisch den aktuellen cookie.

Im ersten Fall können Sie searchParams oder useSearchParams() verwenden, um den resetToken aus den Abfrageparametern abzurufen und an das Formular zu übergeben. Das Formular leitet den resetToken dann beim Absenden automatisch an die Server Action weiter.

Im zweiten Fall können Sie diesen Parameter ignorieren.

OTP-Verifizierung

Die Schnittstelle ist wie folgt definiert:

export interface VerifyOTPFormProps {
  email: string
  verifyToken?: string
  editEmailHandler?: (event: MouseEvent<HTMLButtonElement>) => void
  serverAction: (
    email: string,
    verifyToken: string,
    currentState: VerifyOTPActionState,
    formData: FormData
  ) => Promise<VerifyOTPActionState>
  codeResendAction: (email: string, verifyToken: string) => Promise<VerifyOTPActionState>
  serverStateSuccessHandler?: () => void | Promise<void>
}
ParameterStandardwertErklärung
emailInitiale E-Mail-Adresse, die in der UI angezeigt wird, damit Benutzer sie bearbeiten können
verifyTokenVom Server generiertes Token zur Verfolgung des Formularablaufs
editEmailHandlerEvent-Handler für den "E-Mail bearbeiten"-Button
codeResendActionFunktion zum erneuten Senden des Codes (die Sekunden können über die Konstante code_resend_max_seconds in verify-otp-form.tsx eingestellt werden)
serverActionFormulardaten werden über Server Actions serverseitig übermittelt
serverStateSuccessHandlerNormalerweise erfolgt nach erfolgreicher serverseitiger Authentifizierung eine serverseitige Weiterleitung. Falls Sie Client-seitige Weiterleitungslogik implementieren möchten, können Sie diesen Callback verwenden

verifyToken Bei der Verifizierung eines One-Time Passwords generiert der Server normalerweise ein token, um den Absender des Formulars und dessen Status sicher zu verfolgen und zu bestätigen.

Der Server übermittelt das token typischerweise auf zwei Arten: entweder als URL-Abfrageparameter oder im cookie. Beim Absenden des Formulars überträgt der Browser automatisch den aktuellen cookie.

Im ersten Fall können Sie searchParams oder useSearchParams() verwenden, um den verifyToken aus den Abfrageparametern abzurufen und an das Formular zu übergeben. Das Formular leitet den verifyToken dann beim Absenden automatisch an die Server Action weiter.

Im zweiten Fall können Sie diesen Parameter ignorieren.

Serverseitige Logik

Mit Ausnahme der sozialen Anmeldung werden alle Authentifizierungsoptionen nach der Client-seitigen Validierung über Server Actions an die serverseitige Logik übermittelt. Dabei kommen Reacts useFormState und useFormStatus für die Formularübermittlung zum Einsatz.

In der Vorlagendatei types/action-state.ts ist das Datenformat für Server Actions grundlegend definiert, das Sie bei Bedarf erweitern können.

Hier ist ein Beispielcode für eine Server Action:

sign-in-action.ts

'use server'
 
import type { FormType, SignInActionState } from '@/types/server'
import { redirect } from 'next/navigation'
import { revalidatePath } from 'next/cache'
 
export async function signInAction(
  formType: FormType,
  currentState: SignInActionState,
  formData: FormData
): Promise<SignInActionState> {
  switch (formType) {
    case 'email':
      return await emailAction(formData)
    case 'password':
      return await passwordAction(formData)
  }
}
 
async function emailAction(formData: FormData): Promise<SignInActionState> {
  const data = Object.fromEntries(formData)
  const parsed = signInSchemas.email.safeParse(data)
 
  // Die Formularvalidierung ist auch serverseitig erforderlich
  if (!parsed.success) {
    const issues: Record<string, string> = {}
    parsed.error.issues.map((issue) => (issues[issue.path[0]] = issue.message))
    return {
      success: false,
      formIssues: issues
    }
  }
 
  // Führen Sie serverseitige Operationen durch, z.B. E-Mails versenden, Datenbankoperationen etc.
 
  // Die Weiterleitung kann serverseitig erfolgen
  revalidatePath('/auth/sign-in')
  redirect(`/auth/verify-otp`)
 
  // Oder direkt an den Client zurückgeben
  // return { success: true }
}
 
async function passwordAction(formData: FormData): Promise<SignInActionState> {
  const data = Object.fromEntries(formData)
  // Mock-Verzögerung
  await new Promise((resolve) => setTimeout(resolve, 2000))
  console.log('Sign in password server action form data : ' + JSON.stringify(data, null, 2))
 
  return { success: true }
}