Zalt/docs
INTEGRATION GUIDE

React / Next.js Integration

Complete guide to integrating Zalt authentication in your React application.

Installation

bash
npm install @zalt/auth-sdk @zalt/react

Setup Provider

app/providers.tsx
import { ZaltProvider } from '@zalt/react';

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <ZaltProvider
      realmId={process.env.NEXT_PUBLIC_ZALT_REALM_ID!}
      clientId={process.env.NEXT_PUBLIC_ZALT_CLIENT_ID!}
    >
      {children}
    </ZaltProvider>
  );
}

Login Component

components/LoginForm.tsx
'use client';

import { useState } from 'react';
import { useZalt } from '@zalt/react';

export function LoginForm() {
  const { login, isLoading, error } = useZalt();
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    
    const result = await login({ email, password });
    
    if (result.requiresMfa) {
      // Redirect to MFA verification
      router.push('/mfa-verify');
    } else if (result.success) {
      // Redirect to dashboard
      router.push('/dashboard');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
        required
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Password"
        required
      />
      {error && <p className="error">{error.message}</p>}
      <button type="submit" disabled={isLoading}>
        {isLoading ? 'Signing in...' : 'Sign in'}
      </button>
    </form>
  );
}

Protected Routes

middleware.ts (Next.js)
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { verifyToken } from '@zalt/auth-sdk/server';

export async function middleware(request: NextRequest) {
  const token = request.cookies.get('zalt_access_token')?.value;

  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  try {
    await verifyToken(token, {
      realmId: process.env.ZALT_REALM_ID!,
    });
    return NextResponse.next();
  } catch {
    return NextResponse.redirect(new URL('/login', request.url));
  }
}

export const config = {
  matcher: ['/dashboard/:path*', '/settings/:path*'],
};

useZalt Hook

Available methods
const {
  // State
  user,           // Current user object
  isAuthenticated,// Boolean auth status
  isLoading,      // Loading state
  error,          // Last error

  // Methods
  login,          // Login with email/password
  logout,         // Logout and clear tokens
  register,       // Create new account
  refreshToken,   // Manually refresh tokens
  verifyMfa,      // Verify MFA code
  
  // WebAuthn
  registerPasskey,// Register new passkey
  loginWithPasskey,// Login with passkey
} = useZalt();

Environment Variables

.env.local
NEXT_PUBLIC_ZALT_REALM_ID=your-realm-id
NEXT_PUBLIC_ZALT_CLIENT_ID=your-client-id
ZALT_REALM_ID=your-realm-id  # Server-side only