Documentation LoginGen

Introduction

LoginGen est un site de modèles de pages de connexion. Ce projet a été développé car bien qu'il existe de nombreux sites de modèles sur le marché, la plupart manquent de support pour les pages de connexion ou n'offrent qu'un ou deux modèles simples, souvent sans logique frontale complète. Bien que l'importance interactionnelle d'une page de connexion ne soit peut-être pas aussi grande que celle d'une Landing Page, une belle page de connexion peut néanmoins renforcer la première impression des utilisateurs sur un site.

La stack technique est principalement basée sur Next.js et Shadcn/ui. En plus de fournir des modèles de conception, elle offre une logique frontale complète et utilise la capacité Server Actions de Next.js pour un traitement unifié de l'authentification côté serveur (à l'exception de la connexion sociale, qui est gérée côté client pour plus de commodité).

Tous les codes sont ouverts, comme Shadcn, et peuvent être copiés-collés pour une utilisation immédiate. Vous pouvez donc modifier librement le code selon les besoins de votre projet, ce qui est d'ailleurs recommandé. Pour plus de commodité, les composants de formulaire incluent également des propriétés couramment utilisées, permettant une utilisation prête à l'emploi.

D'autres modèles seront continuellement ajoutés, améliorés et optimisés à l'avenir. Restez à l'écoute.

Installation

Les modèles sont développés avec Next.js et Shadcn, vous devez donc d'abord disposer de cet environnement de projet :

Composants shadcn

Si vous utilisez un autre outil de gestion de paquets ou souhaitez une installation manuelle, consultez la documentation de shadcn.

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

Ajoutez les animations CSS suivantes à votre fichier tailwind.config.js

// 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'
      }
    }
  }
}

Pour sonner, vous devez ajouter le composant suivant :

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

Bibliothèques tierces

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 -- Validation côté client des formulaires
  • motion -- Bibliothèque d'animation
  • @zxcvbn-* -- Bibliothèque de détection de force des mots de passe
  • embla-carousel-* -- Bibliothèque de carrousel (où embla-carousel doit être installé dans devDependencies pour obtenir correctement les types TypeScript)
  • lucide-react -- Bibliothèque d'icônes

Copier-coller le code

Chaque page de prévisualisation de modèle affiche le code complet. Il vous suffit de copier-coller le code nécessaire à l'emplacement correspondant de votre projet. Les images incluses dans les modèles peuvent être téléchargées directement, et les vidéos sont fournies via CDN.

Pour le moment, aucune fonctionnalité d'installation en un clic similaire à npx n'est disponible, mais cela pourrait être envisagé ultérieurement.

Thème

Chaque modèle contient un fichier de thème styles/theme.module.css qui inclut toutes les variables de thème ainsi que les styles et animations nécessaires pour le modèle. Vous pouvez modifier les styles dans ce fichier pour adapter le thème ou le faire correspondre à l'esthétique UI de votre site.

Mode sombre

Configurez le mode sombre selon la documentation de shadcn. Dans le fichier de thème theme.module.css de chaque modèle, le thème sombre utilise le préfixe de sélecteur CSS :global(.dark) pour répondre au mode sombre global du site.

I18n (TODO)

La configuration multilingue n'est pas encore prise en charge, mais vous pouvez toujours l'ajouter manuellement, bien que cela puisse être un peu fastidieux. Cette fonctionnalité pourrait être ajoutée ultérieurement.

Propriétés des formulaires

Il existe cinq formulaires : connexion, inscription, mot de passe oublié, réinitialisation du mot de passe et vérification OTP (one-time password). Chaque formulaire possède des paramètres pour une utilisation prête à l'emploi, la plupart étant communs.

Bien que dans le code des modèles, chaque page de formulaire soit une route distincte avec une redirection côté serveur pour la navigation entre les pages de formulaire, tous les composants sont conçus pour être utilisés via des propriétés transmises. Cela signifie que vous pouvez parfaitement utiliser le routage côté client.

Connexion

L'interface est définie comme suit :

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>
}
ParamètreValeur par défautExplication
auths['social', 'password', 'email']Méthodes d'authentification : connexion sociale, par e-mail, par mot de passe
socials['google', 'github']Types de connexion sociale (la mise en page s'adapte automatiquement en fonction du nombre choisi et de la largeur du formulaire)
emailE-mail initial, également utilisé pour pré-remplir l'affichage après le retour depuis le formulaire de vérification OTP lors de la modification de l'e-mail
emailStrategy'magic-link'Type d'e-mail envoyé. Si 'magic-link', aucune redirection de page n'est effectuée, mais une notification sonner est déclenchée. Sinon, une redirection vers le formulaire de vérification OTP est nécessaire
socialHandlerFonction de rappel lors du clic sur un bouton de connexion sociale. Vous pouvez utiliser des bibliothèques comme Auth.js pour implémenter cette fonctionnalité
forgetHandler'#'Fonction de rappel lors du clic sur le bouton 'Mot de passe oublié'. Ce paramètre est principalement destiné à faciliter l'utilisation
serverActionTous les formulaires, à l'exception de la connexion sociale, sont soumis au serveur via Server Actions
serverStateSuccessHandlerGénéralement, une fois l'authentification côté serveur terminée, une redirection côté serveur est effectuée. Mais si vous souhaitez implémenter une logique de redirection côté client, vous pouvez le faire via ce rappel

Remarques :

  1. socials -- Chaque modèle possède un fichier de configuration config/social.tsx. Vous pouvez modifier ce fichier pour étendre les méthodes de connexion sociale dont vous avez besoin. Vous pouvez modifier librement la key pour l'adapter à votre framework d'authentification, ou remplacer l'icône SVG par celui que vous préférez.
  2. email -- Dans l'interface du formulaire verify-otp, un bouton permet de modifier l'e-mail. Lorsque l'utilisateur clique sur ce bouton, il doit être redirigé vers la page précédente pour corriger son e-mail. Le paramètre email est conçu pour pré-remplir l'affichage de l'e-mail après ce retour.

Inscription

L'interface est définie comme suit :

export interface SignUpFormProps {
  email?: string
  serverAction: (currentState: SignUpActionState, formData: FormData) => Promise<SignUpActionState>
  serverStateSuccessHandler?: (email: string) => void | Promise<void>
}
ParamètreValeur par défautExplication
emailE-mail initial, également utilisé pour pré-remplir l'affichage après le retour depuis le formulaire de vérification OTP lors de la modification de l'e-mail
serverActionSoumission des données du formulaire au serveur via Server Actions
serverStateSuccessHandlerGénéralement, une redirection côté serveur est effectuée après l'authentification. Si une logique de redirection côté client est nécessaire, utilisez ce rappel

Mot de passe oublié

L'interface est définie comme suit :

export interface ForgetPasswordProps {
  email?: string
  emailStrategy?: 'magic-link' | 'one-time-pwd'
  serverAction: (
    currentState: ForgetPasswordActionState,
    formData: FormData
  ) => Promise<ForgetPasswordActionState>
  serverStateSuccessHandler?: (email: string) => void | Promise<void>
}
ParamètreValeur par défautExplication
emailE-mail initial, également utilisé pour pré-remplir l'affichage après le retour depuis le formulaire de vérification OTP lors de la modification de l'e-mail
emailStrategy'magic-link'Type d'e-mail envoyé. Si 'magic-link', une notification sonner est déclenchée. Sinon, redirection vers le formulaire OTP
serverActionSoumission des données du formulaire au serveur via Server Actions
serverStateSuccessHandlerGénéralement, une redirection côté serveur est effectuée après l'authentification. Si une logique de redirection côté client est nécessaire, utilisez ce rappel

Réinitialisation du mot de passe

L'interface est définie comme suit :

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>
}
ParamètreValeur par défautExplication
emailUtilisé uniquement pour tester la force du mot de passe (recommandé pour améliorer la sécurité)
resetTokenToken généré par le serveur pour suivre le processus du formulaire
serverActionSoumission des données du formulaire au serveur via Server Actions
serverStateSuccessHandlerGénéralement, une redirection côté serveur est effectuée après l'authentification. Si une logique de redirection côté client est nécessaire, utilisez ce rappel

resetToken Dans le processus de réinitialisation du mot de passe, le serveur génère généralement un token pour suivre et confirmer de manière sécurisée l'expéditeur du formulaire et son état.

Le serveur transmet généralement le token de deux manières : soit dans les paramètres de requête de l'URL, soit dans un cookie, que le navigateur inclut automatiquement lors de la soumission du formulaire.

Dans le premier cas, vous pouvez utiliser searchParams ou useSearchParams() pour récupérer le resetToken dans les paramètres de requête et le transmettre au formulaire. Le formulaire enverra automatiquement ce resetToken au Server Action du serveur lors de la soumission.

Dans le second cas, vous pouvez ignorer ce paramètre.

Vérification OTP

L'interface est définie comme suit :

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>
}
ParamètreValeur par défautExplication
emailE-mail initial affiché dans l'interface, permettant à l'utilisateur de le modifier
verifyTokenToken généré par le serveur pour suivre le processus du formulaire
editEmailHandlerFonction appelée lors du clic sur le bouton de modification d'e-mail
codeResendActionFonction pour renvoyer le code (le délai en secondes peut être défini via la constante code_resend_max_seconds dans verify-otp-form.tsx)
serverActionSoumission des données du formulaire au serveur via Server Actions
serverStateSuccessHandlerGénéralement, une redirection côté serveur est effectuée après l'authentification. Si une logique de redirection côté client est nécessaire, utilisez ce rappel

verifyToken Dans le processus de vérification du one-time password, le serveur génère généralement un token pour suivre et confirmer de manière sécurisée l'expéditeur du formulaire et son état.

Le serveur transmet généralement le token de deux manières : soit dans les paramètres de requête de l'URL, soit dans un cookie, que le navigateur inclut automatiquement lors de la soumission du formulaire.

Dans le premier cas, vous pouvez utiliser searchParams ou useSearchParams() pour récupérer le verifyToken dans les paramètres de requête et le transmettre au formulaire. Le formulaire enverra automatiquement ce verifyToken au Server Action du serveur lors de la soumission.

Dans le second cas, vous pouvez ignorer ce paramètre.

Côté serveur

À l'exception de la connexion sociale, toutes les options de connexion sont soumises aux Server Actions après validation côté client pour le traitement logique côté serveur. Les soumissions de formulaire utilisent useFormState et useFormStatus de React.

Le fichier types/action-state.ts dans le code des modèles définit simplement le format des données soumises aux Server Actions. Vous pouvez l'étendre selon vos besoins.

Voici un exemple de code pour les opérations dans une 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)
 
  // La validation du formulaire est également requise côté serveur
  if (!parsed.success) {
    const issues: Record<string, string> = {}
    parsed.error.issues.map((issue) => (issues[issue.path[0]] = issue.message))
    return {
      success: false,
      formIssues: issues
    }
  }
 
  // Effectuez des opérations côté serveur, comme l'envoi d'e-mails, l'accès aux bases de données, etc.
 
  // La redirection peut être effectuée côté serveur
  revalidatePath('/auth/sign-in')
  redirect(`/auth/verify-otp`)
 
  // Ou retournez directement au client
  // return { success: true }
}
 
async function passwordAction(formData: FormData): Promise<SignInActionState> {
  const data = Object.fromEntries(formData)
  // Simulation de délai
  await new Promise((resolve) => setTimeout(resolve, 2000))
  console.log('Sign in password server action form data : ' + JSON.stringify(data, null, 2))
 
  return { success: true }
}