Skip to main content

Pre-Built SignIn Components

The ZewstID SDK provides pre-built, customizable sign-in components that handle the complete authentication flow. These components are designed to match the quality of Auth0's Universal Login and Clerk's

<SignIn />
.

Quick Start

The easiest way to add authentication to your Next.js app:

// app/signin/page.tsx import { SignIn } from '@zewstid/nextjs'; export default function SignInPage() { return ( <SignIn callbackUrl="/dashboard" appearance={{ primaryColor: '#0066FF', logo: '/my-logo.svg', }} /> ); }

That's it! You now have a complete sign-in flow with:

  • Email entry and validation
  • Multiple authentication methods (password, OTP, magic link)
  • MFA/2FA verification
  • Error handling
  • Loading states

Installation

npm install @zewstid/nextjs@latest

Components Overview

<SignIn />

The main component that orchestrates the entire sign-in flow.

import { SignIn } from '@zewstid/nextjs'; // or import { SignIn } from '@zewstid/nextjs/components';

Props

PropTypeDefaultDescription
callbackUrl
string
'/'
URL to redirect after sign-in
appearance
SignInAppearance
{}
Visual customization
methods
AuthMethod[]
All availableAuth methods to show
labels
SignInLabels
{}
Custom text labels
onSignIn
(user) => void
-Success callback
onError
(error) => void
-Error callback
allowSignUp
boolean
true
Show sign-up link
showMFABadge
boolean
true
Show MFA indicator
signUpUrl
string
'/register'
Sign-up page URL
forgotPasswordUrl
string
'/forgot-password'
Password reset URL
apiBasePath
string
'/api/zewstid'
API routes base path
clientId
string
-ZewstID Client ID

Appearance Customization

<SignIn appearance={{ // Logo logo: '/logo.svg', logoAlt: 'My Company', // Colors primaryColor: '#0066FF', backgroundColor: '#f5f5f5', // Shape borderRadius: '12px', // Typography fontFamily: 'Inter, sans-serif', // Theme darkMode: false, // CSS Classes className: 'custom-signin', containerClassName: 'signin-container', cardClassName: 'signin-card', }} />

Color Examples

// Blue theme (default) appearance={{ primaryColor: '#3b82f6' }} // Green theme appearance={{ primaryColor: '#10b981' }} // Purple theme appearance={{ primaryColor: '#8b5cf6' }} // Brand color appearance={{ primaryColor: '#FF5A00' }}

Custom Labels

<SignIn labels={{ title: 'Welcome to MyApp', subtitle: 'Sign in to continue', emailPlaceholder: 'Enter your work email', passwordPlaceholder: 'Enter your password', continueButton: 'Continue', signInButton: 'Sign In', signUpLink: 'Create an account', forgotPasswordLink: 'Forgot your password?', mfaTitle: 'Verify Your Identity', mfaSubtitle: 'Enter the code from your authenticator app', }} />

Authentication Methods

Control which methods are available:

// All methods <SignIn methods={['password', 'otp', 'magic-link', 'passkey']} /> // Password only <SignIn methods={['password']} /> // Passwordless only <SignIn methods={['otp', 'magic-link']} />

Individual Components

For more control, use the individual step components:

<SignInEmail />

Email entry step:

import { SignInEmail } from '@zewstid/nextjs'; <SignInEmail onSubmit={(email, exists) => { if (exists) { setStep('verify'); setEmail(email); } else { router.push('/register?email=' + email); } }} appearance={{ primaryColor: '#0066FF' }} allowSignUp={true} signUpUrl="/register" />

<SignInVerify />

Method selection and authentication:

import { SignInVerify } from '@zewstid/nextjs'; <SignInVerify email="user@example.com" availableMethods={{ password: true, otp: true, magicLink: true, passkey: false, push: false, }} mfaInfo={{ enabled: true, totp: true, push: false }} onSuccess={(data) => { if (data.mfaRequired) { setMfaSessionId(data.mfaSessionId); setStep('mfa'); } else { window.location.href = data.redirectUrl; } }} onBack={() => setStep('email')} methods={['password', 'otp', 'magic-link']} showMFABadge={true} />

<SignInMFA />

MFA verification:

import { SignInMFA } from '@zewstid/nextjs'; <SignInMFA email="user@example.com" mfaSessionId={mfaSessionId} mfaInfo={{ enabled: true, totp: true, push: false }} onSuccess={(data) => { window.location.href = data.redirectUrl || '/dashboard'; }} onBack={() => setStep('verify')} />

API Route Handlers

The SignIn components need API routes. Use the SDK's pre-built handlers:

// app/api/zewstid/[...zewstid]/route.ts import { createZewstIDHandlers } from '@zewstid/nextjs/handlers'; const handlers = createZewstIDHandlers({ clientId: process.env.ZEWSTID_CLIENT_ID!, clientSecret: process.env.ZEWSTID_CLIENT_SECRET!, }); export const GET = handlers.GET; export const POST = handlers.POST;

This creates all required endpoints:

EndpointMethodDescription
/api/zewstid/check-email
POSTCheck if user exists
/api/zewstid/methods
POSTGet available auth methods
/api/zewstid/password
POSTPassword authentication
/api/zewstid/otp/send
POSTSend OTP code
/api/zewstid/otp/verify
POSTVerify OTP
/api/zewstid/magic-link/send
POSTSend magic link
/api/zewstid/magic-link/verify
POSTVerify magic link
/api/zewstid/mfa/verify
POSTVerify MFA code
/api/zewstid/establish-sso
GETEstablish SSO session

SSO Establishment

When users authenticate via password, OTP, or magic link, the SDK automatically establishes a ZewstID SSO session. This enables:

  • Cross-Portal SSO: Sign in once, access all connected apps
  • Silent Authentication: Users can navigate between apps without re-authenticating
  • Session Sharing: All ZewstID apps share the same session

This happens automatically - no additional configuration needed.

Complete Example

// app/signin/page.tsx 'use client'; import { SignIn } from '@zewstid/nextjs'; import { useSearchParams } from 'next/navigation'; export default function SignInPage() { const searchParams = useSearchParams(); const callbackUrl = searchParams.get('callbackUrl') || '/dashboard'; return ( <SignIn callbackUrl={callbackUrl} appearance={{ logo: '/logo.svg', logoAlt: 'MyApp', primaryColor: '#0066FF', borderRadius: '12px', }} methods={['password', 'otp', 'magic-link']} labels={{ title: 'Welcome to MyApp', subtitle: 'Sign in to continue', }} onSignIn={(user) => { console.log('User signed in:', user.email); }} allowSignUp={true} signUpUrl="/register" forgotPasswordUrl="/forgot-password" /> ); }

Shared UI Components

The SDK also exports the underlying UI primitives:

import { Input, Button, ErrorMessage, Spinner, Icon, } from '@zewstid/nextjs/components'; // Input with icon <Input type="email" placeholder="Email" icon={<Icon name="mail" />} primaryColor="#0066FF" /> // Button variants <Button variant="primary">Submit</Button> <Button variant="secondary">Cancel</Button> <Button variant="ghost">Back</Button> // Loading state <Button loading>Submitting...</Button> // Error message <ErrorMessage message="Invalid credentials" /> // Spinner <Spinner size={24} color="#0066FF" /> // Icons available: mail, key, smartphone, fingerprint, shield, // arrow-right, arrow-left, eye, eye-off, check, x, loader <Icon name="shield" size={20} color="#3b82f6" />

TypeScript Types

All types are exported for TypeScript users:

import type { SignInProps, SignInAppearance, SignInLabels, AuthMethod, AuthMethods, MFAInfo, } from '@zewstid/nextjs';

Migration from Custom Sign-In

If you have a custom sign-in implementation:

  1. Install the latest SDK:
    npm install @zewstid/nextjs@latest
  2. Add the API handlers:
    app/api/zewstid/[...zewstid]/route.ts
  3. Replace your sign-in page with
    <SignIn />
  4. Customize appearance and labels as needed

The SDK components handle all the complexity of:

  • Email validation
  • Method detection
  • Authentication flows
  • MFA verification
  • SSO establishment
  • Error handling
  • Loading states

Troubleshooting

Components not rendering

Make sure you're using the

'use client'
directive:

'use client'; import { SignIn } from '@zewstid/nextjs';

API routes returning 404

Ensure your handler file is at

app/api/zewstid/[...zewstid]/route.ts
(note the spread syntax in the folder name).

SSO not working

Check that

enableSSOEstablishment
is
true
(default) in your handler config.

Was this page helpful?

Let us know how we can improve our documentation