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

@shyam-148/auth-next

v1.0.3

Published

Next.js App Router authentication - simple SSR, RSC, middleware support

Readme

auth-next

Simple, focused authentication for Next.js App Router. Built on top of auth-client.

Features

  • App Router Only - Designed for Next.js 14/15+ App Router
  • Server Components - Full RSC support with getSession, getUser
  • Client Components - React context with useAuth, useUser, useSession
  • Middleware - Edge-compatible route protection
  • Guards - Declarative <AuthGuard> and <GuestGuard> components
  • TypeScript - Full type safety
  • Tree-shakeable - Import only what you need

Installation

pnpm add auth-next auth-client

Quick Start

1. Create Provider Wrapper

// app/providers.tsx
'use client';

import { AuthProvider } from 'auth-next/client';

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <AuthProvider
      config={{
        baseUrl: process.env.NEXT_PUBLIC_AUTH_API_URL!,
        applicationSlug: 'my-app',
      }}
    >
      {children}
    </AuthProvider>
  );
}

2. Add to Layout

// app/layout.tsx
import { Providers } from './providers';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

3. Setup Middleware

// middleware.ts
import { createAuthMiddleware } from 'auth-next/middleware';

export default createAuthMiddleware({
  publicRoutes: ['/', '/login', '/register', '/api/public/*'],
  authRoutes: ['/login', '/register'],
  loginUrl: '/login',
  defaultRedirect: '/dashboard',
});

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

Usage

Client Components

'use client';

import { useAuth, useUser, AuthGuard, GuestGuard } from 'auth-next/client';

// Basic hook usage
function UserMenu() {
  const { user, logout, isAuthenticated } = useAuth();

  if (!isAuthenticated) return null;

  return (
    <div>
      <span>{user?.email}</span>
      <button onClick={logout}>Logout</button>
    </div>
  );
}

// Simpler user-only hook
function UserAvatar() {
  const { user, isLoading } = useUser();

  if (isLoading) return <Skeleton />;
  if (!user) return null;

  return <Avatar name={user.fullName} />;
}

// Guard component - shows content only when authenticated
function ProtectedPage() {
  return (
    <AuthGuard fallback={<Loading />} redirectTo="/login">
      <Dashboard />
    </AuthGuard>
  );
}

// Guest guard - shows content only when NOT authenticated
function LoginPage() {
  return (
    <GuestGuard redirectTo="/dashboard">
      <LoginForm />
    </GuestGuard>
  );
}

Server Components

// app/dashboard/page.tsx
import { getSession, getUser } from 'auth-next/server';
import { redirect } from 'next/navigation';

export default async function DashboardPage() {
  const session = await getSession({
    apiBase: process.env.AUTH_API_URL!,
  });

  if (!session) {
    redirect('/login');
  }

  return (
    <div>
      <h1>Welcome, {session.user.email}</h1>
      <p>Session ID: {session.session.id}</p>
    </div>
  );
}

Server Actions

// app/actions.ts
'use server';

import { requireAuth } from 'auth-next/server';

export async function updateProfile(formData: FormData) {
  // Throws if not authenticated
  const session = await requireAuth({
    apiBase: process.env.AUTH_API_URL!,
  });

  // session.user is guaranteed to exist
  await db.users.update({
    where: { id: session.user.id },
    data: { name: formData.get('name') as string },
  });
}

Route Handlers

// app/api/protected/route.ts
import { withAuth } from 'auth-next/middleware';

export const GET = withAuth(async (request, { userId }) => {
  // userId is guaranteed to exist
  const data = await fetchUserData(userId);
  return Response.json(data);
});

API Reference

Client Exports (auth-next/client)

| Export | Description | |--------|-------------| | AuthProvider | React context provider | | useAuth | Main auth hook - user, session, logout, refresh | | useUser | User-only hook - user, isLoading, isAuthenticated | | useSession | Session hook - session, user, refresh | | useAuthStatus | Status-only hook - status, isLoading, isAuthenticated | | useLogout | Logout hook - logout function with loading state | | getAuthManager | Get the underlying AuthManager for advanced operations | | AuthGuard | Show children only when authenticated | | GuestGuard | Show children only when NOT authenticated | | ShowWhenAuthenticated | Conditional render for authenticated users | | ShowWhenGuest | Conditional render for guests |

Server Exports (auth-next/server)

| Export | Description | |--------|-------------| | getSession | Get current session (user + session + token) | | getUser | Get current user only | | isAuthenticated | Check if request is authenticated | | requireAuth | Get session or throw error | | getAccessToken | Get access token from cookies | | createAuthHeaders | Create Authorization headers for API calls | | AuthenticationError | Error class for auth failures |

Middleware Exports (auth-next/middleware)

| Export | Description | |--------|-------------| | createAuthMiddleware | Create Next.js middleware | | getAuthFromRequest | Get auth status from request | | withAuth | Wrap route handler to require auth | | createMatcher | Helper to create middleware matcher config |

Configuration

AuthProvider Props

interface AuthProviderProps {
  config: {
    baseUrl: string;           // Auth API URL
    applicationSlug: string;   // Your app identifier
    // ... other auth-client config
  };
  initialUser?: User | null;      // For SSR hydration
  initialSession?: Session | null;
  loadingComponent?: ReactNode;   // Show during init
  children: ReactNode;
}

Middleware Config

interface AuthMiddlewareConfig {
  publicRoutes?: string[];     // Routes that don't require auth
  authRoutes?: string[];       // Routes that redirect if authenticated
  loginUrl?: string;           // Where to redirect unauthenticated users
  defaultRedirect?: string;    // Where to redirect authenticated users from auth routes
}

Login Flow

Since authentication strategies vary, login is handled via auth-client directly:

'use client';

import { getAuthManager } from 'auth-next/client';
import { EmailPasswordStrategy } from 'auth-client';

function LoginForm() {
  const handleSubmit = async (e: FormEvent) => {
    e.preventDefault();
    
    const manager = getAuthManager();
    const strategy = new EmailPasswordStrategy(manager.config.applicationSlug);
    
    await manager.login(strategy, {
      email: '[email protected]',
      password: 'password',
    });
    
    // Auth state updates automatically via context
    router.push('/dashboard');
  };

  return <form onSubmit={handleSubmit}>...</form>;
}

License

MIT