npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@authon/nextjs

v0.3.0

Published

Authon Next.js SDK — middleware, server helpers, and React components

Readme

English | 한국어

@authon/nextjs

Next.js integration for Authon. Includes edge middleware, server-side helpers, and all React components and hooks.

Install

npm install @authon/nextjs @authon/js
# or
pnpm add @authon/nextjs @authon/js

Requires next >= 14.0.0.


Setup

1. Middleware

Create middleware.ts at your project root to protect routes at the edge:

// middleware.ts
import { authonMiddleware } from '@authon/nextjs';

export default authonMiddleware({
  publicRoutes: ['/', '/about', '/pricing', '/sign-in', '/sign-up'],
  signInUrl: '/sign-in',
});

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico|.*\\..*).*)'],
};

Any route not listed in publicRoutes will redirect unauthenticated users to signInUrl. The original destination is preserved as a redirect_url query parameter.

2. AuthonProvider in layout

Wrap your root layout with <AuthonProvider>:

// app/layout.tsx
import { AuthonProvider } from '@authon/nextjs';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <AuthonProvider publishableKey={process.env.NEXT_PUBLIC_AUTHON_KEY!}>
          {children}
        </AuthonProvider>
      </body>
    </html>
  );
}

Middleware

authonMiddleware(options)

import { authonMiddleware } from '@authon/nextjs';

export default authonMiddleware({
  publicRoutes: ['/', '/blog*', '/sign-in'],
  signInUrl: '/sign-in',
  secretKey: process.env.AUTHON_SECRET_KEY,
  apiUrl: 'https://api.authon.dev',
});

| Option | Type | Default | Description | |--------|------|---------|-------------| | publicRoutes | string[] | ['/'] | Routes that do not require authentication. Supports trailing * wildcard (e.g. '/blog*') | | signInUrl | string | '/sign-in' | Redirect destination for unauthenticated users | | secretKey | string (optional) | process.env.AUTHON_SECRET_KEY | Secret key for token verification | | apiUrl | string (optional) | 'https://api.authon.dev' | Authon API base URL |

The middleware automatically allows /_next/*, /api/*, and /favicon.ico through without authentication.


Server-Side Helpers

Import from @authon/nextjs/server for use in Server Components and Route Handlers.

currentUser()

Returns the authenticated user from the session cookie, or null if not signed in.

// app/api/profile/route.ts
import { currentUser } from '@authon/nextjs/server';

export async function GET() {
  const user = await currentUser();

  if (!user) {
    return new Response('Unauthorized', { status: 401 });
  }

  return Response.json({
    id: user.id,
    email: user.email,
    displayName: user.displayName,
  });
}
// app/dashboard/page.tsx (Server Component)
import { currentUser } from '@authon/nextjs/server';
import { redirect } from 'next/navigation';

export default async function DashboardPage() {
  const user = await currentUser();

  if (!user) {
    redirect('/sign-in');
  }

  return <h1>Welcome, {user.displayName}!</h1>;
}

Return type: Promise<AuthonUser | null>

auth()

Returns the full auth state including userId, user, and a getToken() function. Useful when you need to forward the token to a downstream service.

// app/api/data/route.ts
import { auth } from '@authon/nextjs/server';

export async function GET() {
  const { userId, user, getToken } = await auth();

  if (!userId) {
    return new Response('Unauthorized', { status: 401 });
  }

  const token = getToken();

  // Forward token to an internal service
  const response = await fetch('https://internal-api.example.com/data', {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  return Response.json(await response.json());
}

Return type:

Promise<{
  userId: string | null;
  user: AuthonUser | null;
  getToken: () => string | null;
}>

Client Components

All components and hooks from @authon/react are re-exported from @authon/nextjs. Add 'use client' to any component that uses them.

Components

'use client';

import {
  SignedIn,
  SignedOut,
  UserButton,
  SignIn,
  SignUp,
  Protect,
  SocialButtons,
} from '@authon/nextjs';

export function Navbar() {
  return (
    <nav>
      <SignedIn>
        <UserButton />
      </SignedIn>
      <SignedOut>
        <a href="/sign-in">Sign In</a>
      </SignedOut>
    </nav>
  );
}

Auth Page Example

// app/sign-in/page.tsx
'use client';

import { SignIn, SocialButtons } from '@authon/nextjs';

export default function SignInPage() {
  return (
    <div style={{ maxWidth: 400, margin: '80px auto', padding: 24 }}>
      <h1>Sign In</h1>
      <SocialButtons
        onSuccess={() => (window.location.href = '/dashboard')}
        onError={(err) => console.error(err)}
      />
      <SignIn mode="embedded" />
    </div>
  );
}

Role-Based Access

'use client';

import { Protect } from '@authon/nextjs';

export function AdminSection() {
  return (
    <Protect
      fallback={<p>You need admin access to view this section.</p>}
      condition={(user) => user.publicMetadata?.role === 'admin'}
    >
      <AdminPanel />
    </Protect>
  );
}

Hooks

All hooks from @authon/react are re-exported. Use them in Client Components.

useAuthon()

'use client';

import { useAuthon } from '@authon/nextjs';

export function SignOutButton() {
  const { signOut, isSignedIn } = useAuthon();

  if (!isSignedIn) return null;

  return <button onClick={() => signOut()}>Sign Out</button>;
}

useUser()

'use client';

import { useUser } from '@authon/nextjs';

export function UserGreeting() {
  const { user, isLoading } = useUser();

  if (isLoading) return <span>Loading...</span>;
  if (!user) return null;

  return <span>Hello, {user.displayName ?? user.email}!</span>;
}

useAuthonMfa()

'use client';

import { useAuthonMfa } from '@authon/nextjs';

export function MfaSettings() {
  const { setupMfa, verifyMfaSetup, disableMfa, getMfaStatus, regenerateBackupCodes, isLoading, error } =
    useAuthonMfa();

  const handleEnable = async () => {
    const result = await setupMfa();
    if (result) {
      // result.qrCodeSvg — SVG string to render QR code
      // result.backupCodes — one-time recovery codes
      // result.secret — raw TOTP secret
    }
  };

  const handleDisable = async (totpCode: string) => {
    const success = await disableMfa(totpCode);
    if (success) console.log('MFA disabled');
  };

  return (
    <div>
      <button onClick={handleEnable} disabled={isLoading}>Enable MFA</button>
      {error && <p>{error.message}</p>}
    </div>
  );
}

useAuthonPasskeys()

'use client';

import { useAuthonPasskeys } from '@authon/nextjs';

export function PasskeyManager() {
  const { registerPasskey, listPasskeys, revokePasskey, isLoading, error } = useAuthonPasskeys();

  const handleRegister = async () => {
    const passkey = await registerPasskey('My Device');
    if (passkey) console.log('Registered:', passkey.id);
  };

  return (
    <button onClick={handleRegister} disabled={isLoading}>
      Add Passkey
    </button>
  );
}

useAuthonPasswordless()

'use client';

import { useAuthonPasswordless } from '@authon/nextjs';
import { useState } from 'react';

export function MagicLinkForm() {
  const { sendMagicLink, isLoading, error } = useAuthonPasswordless();
  const [email, setEmail] = useState('');
  const [sent, setSent] = useState(false);

  const handleSubmit = async () => {
    const success = await sendMagicLink(email);
    if (success) setSent(true);
  };

  if (sent) return <p>Check your email for a sign-in link.</p>;

  return (
    <div>
      <input value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" />
      <button onClick={handleSubmit} disabled={isLoading}>Send Link</button>
      {error && <p>{error.message}</p>}
    </div>
  );
}

useAuthonWeb3()

'use client';

import { useAuthonWeb3 } from '@authon/nextjs';

export function WalletLogin() {
  const { getNonce, verify, isLoading, error } = useAuthonWeb3();

  const handleConnect = async () => {
    const address = '0xYourAddress';
    const nonceResponse = await getNonce(address, 'evm', 'metamask', 1);
    if (!nonceResponse) return;

    const signature = await window.ethereum.request({
      method: 'personal_sign',
      params: [nonceResponse.message, address],
    });

    const success = await verify(nonceResponse.message, signature, address, 'evm', 'metamask');
    if (success) console.log('Signed in with wallet!');
  };

  return (
    <button onClick={handleConnect} disabled={isLoading}>
      Connect Wallet
    </button>
  );
}

useAuthonSessions()

'use client';

import { useAuthonSessions } from '@authon/nextjs';
import { useEffect, useState } from 'react';
import type { SessionInfo } from '@authon/shared';

export function ActiveSessions() {
  const { listSessions, revokeSession, isLoading, error } = useAuthonSessions();
  const [sessions, setSessions] = useState<SessionInfo[]>([]);

  useEffect(() => {
    listSessions().then((s) => {
      if (s) setSessions(s);
    });
  }, []);

  const handleRevoke = async (id: string) => {
    const success = await revokeSession(id);
    if (success) setSessions((prev) => prev.filter((s) => s.id !== id));
  };

  if (isLoading) return <p>Loading...</p>;

  return (
    <ul>
      {sessions.map((session) => (
        <li key={session.id}>
          <span>{session.userAgent ?? 'Unknown'}</span>
          <button onClick={() => handleRevoke(session.id)}>Revoke</button>
        </li>
      ))}
      {error && <p>{error.message}</p>}
    </ul>
  );
}

Re-exported API Reference

Everything below is re-exported from @authon/react and available directly from @authon/nextjs.

Components

| Component | Description | |-----------|-------------| | <AuthonProvider> | Provides auth context — wrap your root layout | | <SignIn> | Opens sign-in modal or renders embedded form | | <SignUp> | Opens sign-up modal or renders embedded form | | <UserButton> | Avatar dropdown with user info and sign-out | | <SignedIn> | Renders children only when signed in | | <SignedOut> | Renders children only when signed out | | <Protect> | Role-based access guard with optional condition | | <SocialButton> | Single OAuth provider button | | <SocialButtons> | Auto-renders enabled OAuth provider buttons |

Hooks

| Hook | Description | |------|-------------| | useAuthon() | Full auth context: user, signOut, openSignIn, getToken, client | | useUser() | Shorthand for { user, isLoading } | | useAuthonMfa() | TOTP MFA setup, verification, and management | | useAuthonPasskeys() | WebAuthn passkey registration and authentication | | useAuthonPasswordless() | Magic link and email OTP flows | | useAuthonWeb3() | Web3 wallet sign-in and wallet management | | useAuthonSessions() | List and revoke active sessions |

Server Functions (@authon/nextjs/server)

| Function | Returns | Description | |----------|---------|-------------| | currentUser() | Promise<AuthonUser \| null> | Get the current user from the session cookie | | auth() | Promise<{ userId, user, getToken }> | Get full auth state for server-side use |


Environment Variables

# Required — your project's publishable key (safe to expose to the browser)
NEXT_PUBLIC_AUTHON_KEY=pk_live_...

# Required for server-side verification
AUTHON_SECRET_KEY=sk_live_...

# Optional — defaults to https://api.authon.dev
AUTHON_API_URL=https://api.authon.dev

Documentation

authon.dev/docs

License

MIT