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

@bastionauth/nextjs

v0.1.7

Published

Next.js integration for BastionAuth - Server components, middleware, and API routes

Readme

Complete Next.js integration for BastionAuth with edge middleware, server components support, and API route helpers.

🏰 What is BastionAuth?

BastionAuth is a complete, self-hostable enterprise authentication system. Think Clerk, but you own your data.

  • 🔐 Email/password, OAuth, magic links, passkeys
  • 🔑 Multi-factor authentication (TOTP, backup codes)
  • 🏢 Organizations & RBAC
  • ⚡ Edge-ready middleware
  • 🎨 Beautiful React components
  • 🔒 Enterprise security (Argon2id, RS256 JWT)

Learn more: https://bastionauth.dev


Installation

npm install @bastionauth/nextjs
# or
pnpm add @bastionauth/nextjs
# or
yarn add @bastionauth/nextjs

Quick Start

1. Environment Variables

Create .env.local:

NEXT_PUBLIC_BASTION_PUBLISHABLE_KEY=pk_live_...
BASTION_SECRET_KEY=sk_live_...
NEXT_PUBLIC_BASTION_API_URL=https://api.bastionauth.dev

2. Wrap Your App

// app/layout.tsx
import { BastionProvider } from '@bastionauth/nextjs';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <BastionProvider>
          {children}
        </BastionProvider>
      </body>
    </html>
  );
}

3. Protect Routes with Middleware

// middleware.ts
import { authMiddleware } from '@bastionauth/nextjs';

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

export const config = {
  matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};

4. Use in Server Components

// app/dashboard/page.tsx
import { auth, currentUser } from '@bastionauth/nextjs/server';

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

  return (
    <div>
      <h1>Welcome, {user?.firstName}!</h1>
      <p>User ID: {userId}</p>
    </div>
  );
}

Features

Edge Middleware

Protect your routes at the edge before they even render.

import { authMiddleware } from '@bastionauth/nextjs';

export default authMiddleware({
  // Public routes that don't require authentication
  publicRoutes: ['/', '/about', '/pricing'],
  
  // Routes that should ignore authentication
  ignoredRoutes: ['/api/webhook'],
  
  // Custom sign-in URL
  signInUrl: '/sign-in',
  
  // After sign-in redirect
  afterSignIn: '/dashboard',
});

Server-Side Authentication

Access authentication state in Server Components and API routes.

import { auth, currentUser } from '@bastionauth/nextjs/server';

// Get user ID and session ID
const { userId, sessionId } = await auth();

// Get full user object
const user = await currentUser();

// Get organization
const { organization, membership } = await auth();

Client Components

All React SDK components and hooks are re-exported for convenience.

import { 
  useAuth, 
  useUser, 
  SignIn, 
  UserButton 
} from '@bastionauth/nextjs';

function ClientComponent() {
  const { isSignedIn, user } = useAuth();
  return <div>Hello, {user?.firstName}</div>;
}

API Route Protection

Protect API routes with authentication checks.

// app/api/protected/route.ts
import { auth } from '@bastionauth/nextjs/server';
import { NextResponse } from 'next/server';

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

  if (!userId) {
    return NextResponse.json(
      { error: 'Unauthorized' },
      { status: 401 }
    );
  }

  return NextResponse.json({ message: 'Protected data', userId });
}

Middleware Configuration

Basic Configuration

import { authMiddleware } from '@bastionauth/nextjs';

export default authMiddleware({
  publicRoutes: ['/'],
  signInUrl: '/sign-in',
});

Advanced Configuration

import { authMiddleware } from '@bastionauth/nextjs';

export default authMiddleware({
  // Public routes (no auth required)
  publicRoutes: ['/', '/about', '/pricing'],
  
  // Ignored routes (skip middleware entirely)
  ignoredRoutes: ['/api/webhook', '/api/health'],
  
  // Sign-in URL
  signInUrl: '/sign-in',
  
  // Redirect after sign-in
  afterSignIn: '/dashboard',
  
  // Redirect after sign-up
  afterSignUp: '/onboarding',
  
  // Custom unauthorized handler
  beforeAuth: (auth, req) => {
    // Custom logic before authentication
    console.log('Authenticating:', req.url);
  },
  
  // Custom handler after authentication
  afterAuth: (auth, req) => {
    // Custom logic after authentication
    if (auth.userId && req.nextUrl.pathname === '/') {
      return NextResponse.redirect(new URL('/dashboard', req.url));
    }
  },
});

Pattern Matching

export const config = {
  matcher: [
    // Match all paths except static files
    '/((?!.*\\..*|_next).*)',
    
    // Match root
    '/',
    
    // Match API and tRPC routes
    '/(api|trpc)(.*)',
  ],
};

Server Helpers

auth()

Get authentication state in Server Components and API routes.

import { auth } from '@bastionauth/nextjs/server';

const { 
  userId,          // string | null - current user ID
  sessionId,       // string | null - current session ID
  orgId,           // string | null - active organization ID
  orgRole,         // string | null - user's role in org
} = await auth();

currentUser()

Get the full user object.

import { currentUser } from '@bastionauth/nextjs/server';

const user = await currentUser();

if (user) {
  console.log(user.email);
  console.log(user.firstName);
  console.log(user.lastName);
}

currentOrganization()

Get the active organization.

import { currentOrganization } from '@bastionauth/nextjs/server';

const { organization, membership } = await currentOrganization();

if (organization) {
  console.log(organization.name);
  console.log(membership.role);
}

Examples

Protected Page

// app/dashboard/page.tsx
import { auth } from '@bastionauth/nextjs/server';
import { redirect } from 'next/navigation';

export default async function DashboardPage() {
  const { userId } = await auth();

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

  return <div>Protected Dashboard</div>;
}

User Profile Page

// app/profile/page.tsx
import { currentUser } from '@bastionauth/nextjs/server';

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

  return (
    <div>
      <h1>{user?.firstName} {user?.lastName}</h1>
      <p>Email: {user?.email}</p>
      <p>Member since: {user?.createdAt.toLocaleDateString()}</p>
    </div>
  );
}

Organization Dashboard

// app/org/[orgId]/page.tsx
import { auth } from '@bastionauth/nextjs/server';

export default async function OrganizationPage({ params }) {
  const { userId, orgId, orgRole } = await auth();

  return (
    <div>
      <h1>Organization Dashboard</h1>
      <p>Your role: {orgRole}</p>
    </div>
  );
}

API Route with Auth

// app/api/user/route.ts
import { auth, currentUser } from '@bastionauth/nextjs/server';
import { NextResponse } from 'next/server';

export async function GET() {
  try {
    const { userId } = await auth();

    if (!userId) {
      return NextResponse.json(
        { error: 'Unauthorized' },
        { status: 401 }
      );
    }

    const user = await currentUser();

    return NextResponse.json({
      user: {
        id: user.id,
        email: user.email,
        name: `${user.firstName} ${user.lastName}`,
      },
    });
  } catch (error) {
    return NextResponse.json(
      { error: 'Internal Server Error' },
      { status: 500 }
    );
  }
}

Sign-In Page

// app/sign-in/page.tsx
import { SignIn } from '@bastionauth/nextjs';

export default function SignInPage() {
  return (
    <div className="flex min-h-screen items-center justify-center">
      <SignIn afterSignIn="/dashboard" />
    </div>
  );
}

Client Component with Hooks

// components/user-menu.tsx
'use client';

import { useAuth, useUser } from '@bastionauth/nextjs';

export function UserMenu() {
  const { isSignedIn, signOut } = useAuth();
  const { user } = useUser();

  if (!isSignedIn) {
    return <a href="/sign-in">Sign in</a>;
  }

  return (
    <div>
      <p>Hello, {user?.firstName}!</p>
      <button onClick={() => signOut()}>
        Sign out
      </button>
    </div>
  );
}

App Router vs Pages Router

This package is designed for Next.js 13+ App Router. For Pages Router support, use the React SDK with custom middleware.

App Router (✅ Recommended)

// app/page.tsx - Server Component
import { auth } from '@bastionauth/nextjs/server';

export default async function Page() {
  const { userId } = await auth();
  return <div>{userId}</div>;
}

Pages Router (Use React SDK)

// pages/index.tsx
import { BastionProvider, useAuth } from '@bastionauth/react';

export default function Page() {
  const { userId } = useAuth();
  return <div>{userId}</div>;
}

TypeScript Support

Fully typed with TypeScript. All functions and components have complete type definitions.

import type { User, Session } from '@bastionauth/nextjs';

const user: User = await currentUser();

Edge Runtime Compatibility

All middleware and server functions are compatible with the Edge Runtime.

export const runtime = 'edge';

export default authMiddleware({
  // Edge-compatible middleware
});

Related Packages

Documentation

💰 Pricing

BastionAuth offers self-hosted authentication with transparent pricing:

  • Free Tier: Up to 1,000 monthly active users
  • Pro: $29/month for up to 10,000 users
  • Enterprise: Custom pricing for unlimited users + premium support

View full pricing →

Why Self-Hosted?

  • 📊 No per-user costs at scale - Pay for hosting, not for users
  • 🔐 Complete data ownership - Your data stays on your infrastructure
  • 🌍 GDPR, HIPAA, SOC2 compliance ready - Meet any regulatory requirement
  • 🚀 No vendor lock-in - You control your auth infrastructure

Support