Version: 2.0
Last Updated: November 16, 2025
Inspired by: blocks.so/login
The @hyperyai/sdk package now includes modern, beautiful authentication components that you can drop into any React app. Choose between modal-based or embedded forms based on your needs.
<AuthButton />- Trigger auth modal from anywhere<AuthModal />- Standalone modal dialog<ModernAuthForm />- Embeddable form for login pages
npm install @hyperyai/sdkimport { HyperyProvider } from '@hyperyai/sdk';
function App() {
return (
<HyperyProvider
config={{
clientId: 'your-app-id',
redirectUri: 'https://yourapp.com/auth/callback',
gatewayUrl: 'https://hypery.ai',
}}
>
<YourApp />
</HyperyProvider>
);
}Drop a button anywhere in your app that triggers a beautiful auth modal:
import { AuthButton } from '@hyperyai/sdk';
export function Navbar() {
return (
<nav>
<AuthButton>Sign In</AuthButton>
</nav>
);
}import { AuthButton } from '@hyperyai/sdk';
import { useRouter } from 'next/navigation';
export function Hero() {
const router = useRouter();
return (
<div className="hero">
<h1>Welcome to My App</h1>
<AuthButton
variant="primary"
size="lg"
mode="signup"
onSuccess={() => {
console.log('User signed up!');
router.push('/dashboard');
}}
branding={{
logo: '/logo.png',
appName: 'My Amazing App',
primaryColor: '#8b5cf6',
}}
>
Get Started Free
</AuthButton>
</div>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
children |
ReactNode | 'Sign In' | Button text |
variant |
'primary' | 'secondary' | 'outline' | 'ghost' | 'primary' | Button style |
size |
'sm' | 'md' | 'lg' | 'md' | Button size |
mode |
'signin' | 'signup' | 'signin' | Initial auth mode |
onSuccess |
() => void | - | Called after auth success |
showSocial |
boolean | true | Show Google/GitHub |
showEmailPassword |
boolean | true | Show email form |
branding |
BrandingConfig | - | Custom branding |
// Primary (Purple, elevated)
<AuthButton variant="primary">Sign In</AuthButton>
// Secondary (Gray, elevated)
<AuthButton variant="secondary">Sign In</AuthButton>
// Outline (Border only)
<AuthButton variant="outline">Sign In</AuthButton>
// Ghost (Minimal)
<AuthButton variant="ghost">Sign In</AuthButton>For more control, use the modal directly:
import { AuthModal } from '@hyperyai/sdk';
import { useState } from 'react';
export function MyComponent() {
const [showAuth, setShowAuth] = useState(false);
return (
<>
<button onClick={() => setShowAuth(true)}>
Login
</button>
<AuthModal
isOpen={showAuth}
onClose={() => setShowAuth(false)}
onSuccess={() => {
setShowAuth(false);
// Handle successful auth
}}
/>
</>
);
}import { AuthModal } from '@hyperyai/sdk';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
export function ProtectedFeature() {
const [showAuth, setShowAuth] = useState(false);
const router = useRouter();
const handleUpgrade = () => {
setShowAuth(true);
};
return (
<div>
<button onClick={handleUpgrade}>
Upgrade to Pro
</button>
<AuthModal
isOpen={showAuth}
onClose={() => setShowAuth(false)}
initialMode="signup"
onSuccess={() => {
setShowAuth(false);
router.push('/billing/upgrade');
}}
onError={(error) => {
console.error('Auth failed:', error);
}}
branding={{
logo: '/logo.png',
appName: 'My App',
primaryColor: '#ec4899',
}}
showSocial={true}
showEmailPassword={false} // Social only
/>
</div>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
isOpen |
boolean | required | Modal visibility |
onClose |
() => void | required | Close handler |
initialMode |
'signin' | 'signup' | 'signin' | Starting mode |
onSuccess |
() => void | - | Auth success callback |
onError |
(error) => void | - | Error callback |
showSocial |
boolean | true | Show social buttons |
showEmailPassword |
boolean | true | Show email form |
branding |
BrandingConfig | - | Custom branding |
Use this for full-page auth experiences:
// app/login/page.tsx
import { ModernAuthForm } from '@hyperyai/sdk';
import { useRouter } from 'next/navigation';
export default function LoginPage() {
const router = useRouter();
return (
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-purple-50 to-blue-50 dark:from-gray-900 dark:to-gray-800 p-4">
<ModernAuthForm
mode="signin"
showCard={true}
allowModeSwitch={true}
onSuccess={() => router.push('/dashboard')}
branding={{
logo: '/logo.png',
appName: 'My App',
primaryColor: '#8b5cf6',
}}
/>
</div>
);
}export function LoginSection() {
return (
<div className="max-w-md mx-auto">
<ModernAuthForm
mode="signin"
showCard={false}
showSocial={true}
showEmailPassword={true}
/>
</div>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
mode |
'signin' | 'signup' | 'signin' | Auth mode |
allowModeSwitch |
boolean | true | Show switch link |
showCard |
boolean | true | Wrap in card |
showSocial |
boolean | true | Social buttons |
showEmailPassword |
boolean | true | Email form |
onSuccess |
() => void | - | Success callback |
onError |
(error) => void | - | Error callback |
branding |
BrandingConfig | - | Custom branding |
interface BrandingConfig {
logo?: string; // URL to logo image
appName?: string; // Your app name
primaryColor?: string; // Hex color (e.g., '#8b5cf6')
}// Purple (default)
const purpleBranding = {
primaryColor: '#8b5cf6',
appName: 'My SaaS',
};
// Pink
const pinkBranding = {
primaryColor: '#ec4899',
appName: 'Creative App',
};
// Blue
const blueBranding = {
primaryColor: '#3b82f6',
appName: 'Enterprise Tool',
};
// Teal
const tealBranding = {
primaryColor: '#06b6d4',
appName: 'Developer Platform',
};import { AuthButton, SignedIn, SignedOut, UserButton } from '@hyperyai/sdk';
export function Navbar() {
return (
<nav className="flex items-center justify-between p-4">
<Logo />
<div>
<SignedOut>
<AuthButton variant="outline" size="sm">
Sign In
</AuthButton>
</SignedOut>
<SignedIn>
<UserButton />
</SignedIn>
</div>
</nav>
);
}import { AuthButton } from '@hyperyai/sdk';
export function Hero() {
return (
<section className="text-center py-20">
<h1 className="text-5xl font-bold mb-6">
Build Amazing AI Apps
</h1>
<p className="text-xl text-gray-600 mb-8">
Connect to 100+ AI models with one API
</p>
<div className="flex gap-4 justify-center">
<AuthButton
variant="primary"
size="lg"
mode="signup"
>
Get Started Free
</AuthButton>
<AuthButton
variant="outline"
size="lg"
mode="signin"
>
Sign In
</AuthButton>
</div>
</section>
);
}import { Protect, AuthButton } from '@hyperyai/sdk';
export function PremiumFeature() {
return (
<Protect
fallback={
<div className="text-center p-12 bg-gray-50 rounded-xl">
<h3 className="text-2xl font-bold mb-4">
Sign in to access this feature
</h3>
<AuthButton mode="signin">
Sign In to Continue
</AuthButton>
</div>
}
>
<PremiumContent />
</Protect>
);
}import { AuthModal } from '@hyperyai/sdk';
import { useState } from 'react';
export function PricingCard() {
const [showAuth, setShowAuth] = useState(false);
return (
<>
<div className="pricing-card">
<h3>Pro Plan</h3>
<p>$29/month</p>
<button onClick={() => setShowAuth(true)}>
Start Free Trial
</button>
</div>
<AuthModal
isOpen={showAuth}
onClose={() => setShowAuth(false)}
initialMode="signup"
onSuccess={() => {
setShowAuth(false);
// Redirect to checkout
}}
/>
</>
);
}// app/login/page.tsx
import { ModernAuthForm } from '@hyperyai/sdk';
import { useRouter } from 'next/navigation';
export default function LoginPage() {
const router = useRouter();
return (
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-purple-50 via-white to-blue-50 dark:from-gray-900 dark:via-gray-900 dark:to-gray-800">
<ModernAuthForm
mode="signin"
allowModeSwitch={true}
onSuccess={() => router.push('/dashboard')}
branding={{
logo: '/logo.svg',
appName: 'Hypery',
primaryColor: '#8b5cf6',
}}
/>
</div>
);
}✨ Modern Design
- Rounded corners (2xl)
- Subtle shadows
- Smooth transitions
- Hover effects
🎨 Dark Mode Support
- Automatic theme detection
- Proper contrast ratios
- Beautiful in both modes
🎯 Accessibility
- Keyboard navigation
- ARIA labels
- Focus management
- Screen reader support
⚡ Animations
- Fade in backdrop
- Zoom in modal
- Smooth button states
- Loading spinners
<AuthButton
branding={{
primaryColor: '#ec4899', // Pink
}}
>
Sign In
</AuthButton><AuthButton
showSocial={true}
showEmailPassword={false}
>
Quick Sign In
</AuthButton><AuthButton
showSocial={false}
showEmailPassword={true}
>
Email Sign In
</AuthButton><AuthButton
mode="signup"
branding={{ appName: 'My App' }}
>
Create Account
</AuthButton>import { SignInForm } from '@hyperyai/sdk';
<SignInForm
showCard
showTitle
onSuccess={handleSuccess}
/>Option A: Embedded Form
import { ModernAuthForm } from '@hyperyai/sdk';
<ModernAuthForm
showCard
onSuccess={handleSuccess}
branding={{ primaryColor: '#8b5cf6' }}
/>Option B: Modal Button (Recommended)
import { AuthButton } from '@hyperyai/sdk';
<AuthButton
onSuccess={handleSuccess}
branding={{ primaryColor: '#8b5cf6' }}
>
Sign In
</AuthButton>Why:
- Cleaner UX (modal doesn't take up page space)
- Works anywhere (navbar, hero, cards, etc.)
- Better mobile experience
// ✅ Recommended
<AuthButton>Sign In</AuthButton>
// ❌ Not recommended (unless you need dedicated page)
<SignInForm showCard />Good use cases:
/loginpage/signuppage/authpage
// app/login/page.tsx
export default function LoginPage() {
return (
<div className="auth-page-layout">
<ModernAuthForm mode="signin" />
</div>
);
}Create a config file:
// config/auth-branding.ts
export const AUTH_BRANDING = {
logo: '/logo.svg',
appName: 'My App',
primaryColor: '#8b5cf6',
};Use everywhere:
import { AUTH_BRANDING } from '@/config/auth-branding';
<AuthButton branding={AUTH_BRANDING}>Sign In</AuthButton>
<ModernAuthForm branding={AUTH_BRANDING} />import { useRouter } from 'next/navigation';
import { AuthButton } from '@hyperyai/sdk';
export function MyComponent() {
const router = useRouter();
return (
<AuthButton
onSuccess={() => {
// Option 1: Redirect
router.push('/dashboard');
// Option 2: Reload data
router.refresh();
// Option 3: Show notification
toast.success('Welcome back!');
// Option 4: Track analytics
analytics.track('user_signed_in');
}}
>
Sign In
</AuthButton>
);
}All components accept a primaryColor for consistent branding:
const myBranding = {
primaryColor: '#your-brand-color',
};
<AuthButton branding={myBranding} />
<ModernAuthForm branding={myBranding} />
<AuthModal branding={myBranding} />The components use Tailwind classes internally. Make sure Tailwind is configured:
// tailwind.config.js
module.exports = {
content: [
'./node_modules/@hyperyai/sdk/**/*.{js,ts,jsx,tsx}',
// ... your app paths
],
};Components automatically adapt to dark mode:
// Works automatically with Tailwind dark mode
<html className="dark">
<AuthButton>Sign In</AuthButton>
</html>Full TypeScript support with intellisense:
import {
AuthButton,
AuthModal,
ModernAuthForm,
type AuthButtonProps,
type AuthModalProps,
type ModernAuthFormProps,
} from '@hyperyai/sdk';
// Type-safe props
const buttonProps: AuthButtonProps = {
variant: 'primary',
size: 'lg',
onSuccess: () => console.log('Success!'),
};
<AuthButton {...buttonProps}>Sign In</AuthButton>| Component | Use Case | Best For |
|---|---|---|
| AuthButton | Anywhere auth is needed | Navbars, CTAs, features |
| AuthModal | Programmatic modal control | Complex flows, conditions |
| ModernAuthForm | Dedicated auth pages | /login, /signup routes |
export function Homepage() {
return (
<div>
{/* Navbar */}
<nav className="flex justify-between p-4">
<Logo />
<AuthButton variant="outline">Sign In</AuthButton>
</nav>
{/* Hero */}
<section className="text-center py-20">
<h1>Build Better with AI</h1>
<AuthButton
variant="primary"
size="lg"
mode="signup"
>
Start Building Free
</AuthButton>
</section>
</div>
);
}export function PricingPage() {
return (
<div className="grid grid-cols-3 gap-6">
{plans.map(plan => (
<PricingCard key={plan.id} plan={plan}>
<AuthButton
mode="signup"
variant={plan.popular ? 'primary' : 'outline'}
onSuccess={() => {
// Pre-select plan after signup
router.push(`/billing?plan=${plan.id}`);
}}
>
{plan.cta}
</AuthButton>
</PricingCard>
))}
</div>
);
}import { SignedIn, SignedOut, AuthButton } from '@hyperyai/sdk';
export function Article() {
return (
<article>
<h1>Premium Article</h1>
{/* First paragraph free */}
<p>This is the introduction...</p>
<SignedIn>
{/* Full content for logged-in users */}
<div>
<p>Premium content here...</p>
</div>
</SignedIn>
<SignedOut>
{/* Paywall for anonymous users */}
<div className="bg-gradient-to-t from-white to-transparent p-8 text-center">
<p className="mb-4 font-medium">
Sign in to read the full article
</p>
<AuthButton mode="signin">
Continue Reading
</AuthButton>
</div>
</SignedOut>
</article>
);
}<AuthButton
onSuccess={async () => {
// 1. Track conversion
await analytics.track('signup_completed');
// 2. Identify user
const user = await getUser();
analytics.identify(user.id, {
email: user.email,
name: user.name,
});
// 3. Show welcome message
toast.success(`Welcome, ${user.name}!`);
// 4. Navigate to onboarding
router.push('/onboarding');
}}
>
Get Started
</AuthButton><AuthModal
isOpen={showAuth}
onClose={() => setShowAuth(false)}
onError={(error) => {
// Log to error tracking
Sentry.captureException(new Error(error));
// Show user-friendly message
if (error.includes('network')) {
toast.error('Connection issue. Please try again.');
} else {
toast.error(error);
}
}}
/>const variant = useABTest('auth_button_variant', {
control: 'primary',
variant: 'outline',
});
<AuthButton variant={variant}>
Sign In
</AuthButton>| Component | Size (gzipped) |
|---|---|
| AuthButton | ~2KB |
| AuthModal | ~3KB |
| ModernAuthForm | ~3KB |
| Total (all) | ~8KB |
import { lazy, Suspense } from 'react';
const AuthButton = lazy(() =>
import('@hyperyai/sdk').then(mod => ({ default: mod.AuthButton }))
);
<Suspense fallback={<button>Loading...</button>}>
<AuthButton>Sign In</AuthButton>
</Suspense>- Tab: Navigate between buttons/inputs
- Enter: Submit form or click button
- Escape: Close modal
- Space: Activate buttons
- Proper ARIA labels
- Role attributes
- Focus management
- Error announcements
Modal automatically:
- Traps focus within dialog
- Returns focus on close
- Highlights active element
Q: Do I need to install shadcn/ui?
A: No, these components are self-contained.
Q: Can I use without Tailwind?
A: Tailwind is recommended but not required. Components include inline styles as fallback.
Q: How do I customize button styles?
A: Use the className prop or branding.primaryColor.
Q: Does this work with Next.js App Router?
A: Yes! All components are marked with 'use client'.
Q: Can I use multiple auth buttons on the same page?
A: Yes, they share the same modal instance.
Q: How do I add more OAuth providers?
A: Currently supports Google and GitHub. More providers coming soon.
// ❌ Wrong - modal wrapped in container with overflow hidden
<div className="overflow-hidden">
<AuthButton>Sign In</AuthButton>
</div>
// ✅ Correct - modal renders at document level
<AuthButton>Sign In</AuthButton>// If global styles interfere, use the provided class names
<AuthButton className="your-custom-class">
Sign In
</AuthButton>// Ensure Tailwind dark mode is configured
// tailwind.config.js
module.exports = {
darkMode: 'class', // or 'media'
};- Magic link authentication
- SMS/Phone authentication
- Passkey/WebAuthn support
- Multi-factor authentication (MFA)
- Social: LinkedIn, Twitter, Facebook
- SAML/SSO for enterprise
- Biometric authentication
- Session management UI
Documentation: https://docs.hypery.ai/auth
Examples: https://github.com/hypery/examples
Discord: https://discord.gg/hypery
Email: support@hypery.ai
Happy Building! 🚀