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

@logickernel/bridge

v0.15.7

Published

Framework-agnostic micro-frontend authentication library for AuthJS/NextAuth JWT tokens

Readme

@logickernel/bridge

Framework-agnostic micro-frontend authentication library for AuthJS/NextAuth JWT tokens with built-in Next.js components.

Installation

npm install @logickernel/bridge

Quick Start (Next.js)

1. Environment Variables

Add these to the .env file of your application:

AUTH_SECRET=your-nextauth-secret  # Required: Same secret used by your kernel/auth server
AUTH_URL=http://localhost:3000    # Required: Base URL of your kernel/auth server
BASE_URL=http://localhost:7001    # Optional: Your facade URL for user-facing redirects

2. Configure Next.js

In your next.config.ts, add the bridge package to transpilePackages:

import type { NextConfig } from "next"

const nextConfig: NextConfig = {
  transpilePackages: ["@logickernel/bridge"],
  // ... other config
}

export default nextConfig

Use webpack instead of Turbopack (the default) in your package.json scripts:

{
  "scripts": {
    "dev": "next dev --webpack",
    "build": "next build --webpack"
  }
}

3. Configure Tailwind CSS

Add the @source directive to your src/app/globals.css to ensure Tailwind scans classes from this package:

@import "tailwindcss";
/* ... other imports ... */

@source "../../node_modules/@logickernel/bridge/dist/**/*.{js,cjs}";

Note: If using a local file:../bridge dependency, use @source "../../../bridge/dist/**/*.{js,cjs}"; instead. Restart your dev server after adding this directive.

4. Use the Layout Component

Create a wrapper component to establish the client/server boundary:

"use client"

/**
 * Client boundary wrapper for AppLayout.
 * 
 * This wrapper is required because "use client" directives are not preserved
 * in bundled library code. Next.js needs this directive in your source code
 * to properly handle the client/server boundary.
 */
import { AppLayout } from "@logickernel/bridge/next/components"

export function AppLayoutWrapper({
  children,
  organizationId,
  apiBaseUrl,
}: {
  children: React.ReactNode
  organizationId?: string
  apiBaseUrl?: string
}) {
  return (
    <AppLayout
      organizationId={organizationId}
      apiBaseUrl={apiBaseUrl}
    >
      {children}
    </AppLayout>
  )
}

Use in your layout:

import { redirect } from "next/navigation"
import { auth } from "@/lib/next-auth" // or your auth setup
import { AppLayoutWrapper } from "@/components/app-layout-wrapper"

export default async function Layout({
  children,
}: {
  children: React.ReactNode
}) {
  const session = await auth()

  if (!session?.user) {
    redirect("/core/auth/signin?callbackUrl=/core/app")
  }

  return (
    <AppLayoutWrapper>
      {children}
    </AppLayoutWrapper>
  )
}

The layout automatically fetches user information from the navigation API endpoint.

5. Navigation API Endpoint

The layout automatically loads navigation items from /core/api/navigation/[organization_id].

Required Endpoint: GET /core/api/navigation/[organization_id]

Response Payload:

{
  items: NavigationItem[]
  organizationId: string
  organizations: NavigationOrganization[]
  user: {
    id: string
    name: string | null
    email: string
    image: string | null
  }
}

interface NavigationItem {
  title: string
  url?: string        // If missing, item is treated as a section label
  icon?: string       // Lucide icon name (e.g., "LayoutDashboard", "Users")
  isActive?: boolean  // Whether the item should be highlighted
  items?: {           // Sub-items for collapsible navigation
    title: string
    url: string
  }[]
}

interface NavigationOrganization {
  id: string
  name: string
  logo?: string       // Lucide icon name for the organization logo
  plan?: string       // Optional plan/badge text
}

The endpoint should be protected and only return data the authenticated user has access to. The {organizationId} placeholder in item URLs is automatically replaced with the current organization ID.

Features

  • Built-in sidebar navigation with collapsible sections
  • Organization switcher
  • User menu with profile and sign-out
  • Responsive design (mobile and desktop)
  • Automatic navigation loading from API
  • Consistent UI across microfrontends

Next.js Utilities

Server Components / Pages

import { getSession } from "@logickernel/bridge/next"
import { redirect } from "next/navigation"

export default async function DashboardPage() {
  const session = await getSession()
  
  if (!session) {
    redirect("/core/auth/signin")
  }

  return <div>Welcome, {session.user.email}!</div>
}

Role-Based Page Protection

import { checkPageAuth } from "@logickernel/bridge/next"
import { redirect, notFound } from "next/navigation"

export default async function AdminPage({
  params,
}: {
  params: Promise<{ organization_id: string }>
}) {
  const { organization_id } = await params

  const auth = await checkPageAuth({
    requiredRoles: ["organization.owner", "organization.editor"],
    organizationId: organization_id,
  })

  if (!auth.authenticated) {
    redirect(auth.redirectUrl)
  }

  if (!auth.hasRequiredRole) {
    notFound()
  }

  return <div>Admin Panel for {auth.session.user.email}</div>
}

API Routes

import { withAuth } from "@logickernel/bridge/next"
import { NextResponse } from "next/server"

// Any authenticated user
export const GET = withAuth(async (request, { session }) => {
  return NextResponse.json({
    userId: session.user.id,
    email: session.user.email,
  })
})

// With role requirements
export const DELETE = withAuth(
  async (request, { session }) => {
    // Only owners can delete
    return NextResponse.json({ deleted: true })
  },
  {
    requiredRoles: ["organization.owner"],
    organizationId: "org_id", // Extract from route params
  }
)

Middleware / Proxy

// middleware.ts or proxy.ts
import { createProxyHandler, type ProxyOptions } from "@logickernel/bridge/next"

const config: ProxyOptions = {
  basePath: "/app",
  routes: {
    "/dashboard": [],  // Any authenticated user (relative to basePath)
    "/settings": [],
    "/[organization_id]/admin": ["organization.owner"],  // Dynamic route with role requirement
  },
}

export const proxy = createProxyHandler(config)

// Static config for Next.js middleware
export const config = {
  matcher: ["/((?!_next/static|_next/image|favicon.ico|public).*)"],
}

Import Paths

// Core utilities (framework-agnostic)
import { decodeSessionToken, fetchUserRoles } from "@logickernel/bridge"

// Next.js utilities (server components, API routes, middleware)
import { getSession, withAuth, checkPageAuth } from "@logickernel/bridge/next"

// Layout components (client components)
import { AppLayout, type User } from "@logickernel/bridge/next/components"

API Reference

Core Exports (@logickernel/bridge)

| Export | Description | |--------|-------------| | decodeSessionToken(token, secret, isSecure) | Decode and validate a JWT session token | | extractSessionCookie(cookies) | Extract session cookie from a cookies object | | fetchUserRoles(options) | Fetch user roles from the kernel API | | hasAnyRole(userRoles, requiredRoles) | Check if user has at least one required role | | hasAllRoles(userRoles, requiredRoles) | Check if user has all required roles | | hasRole(userRoles, role) | Check if user has a specific role |

Next.js Exports (@logickernel/bridge/next)

| Export | Description | |--------|-------------| | getSession() | Get the current session from cookies | | getSessionToken() | Get the raw session token value | | getUserRoles(orgId) | Get user roles in an organization | | withAuth(handler, options?) | Wrap an API route with authentication | | checkPageAuth(options?) | Check authentication for a page | | requireAuth() | Require authentication (throws if not authenticated) | | hasRequiredRole(orgId, roles) | Check if user has required roles | | createProxyHandler(options) | Create a middleware/proxy handler |

Layout Components (@logickernel/bridge/next/components)

| Export | Description | |--------|-------------| | AppLayout | Main layout component with sidebar navigation (wrap in a local component with "use client" for server components) | | useNavigation | Hook to fetch navigation items from API | | getIconComponent | Utility to get icon component from icon name |

AppLayout Props:

interface AppLayoutProps {
  user?: User                    // Optional: Auto-fetched if not provided
  organizationId?: string        // Optional: Current organization ID
  apiBaseUrl?: string            // Optional: Defaults to "/core/api"
  children: React.ReactNode
}

TypeScript Types

// Core types
import type {
  Session,
  SessionUser,
  DecodeResult,
} from "@logickernel/bridge"

// Next.js types
import type {
  ProxyOptions,
  AuthContext,
  AuthenticatedHandler,
  PageAuthOptions,
  PageAuthResult,
} from "@logickernel/bridge/next"

// Component types
import type {
  User,
  NavigationItem,
  NavigationOrganization,
} from "@logickernel/bridge/next/components"

Architecture

bridge/
├── src/
│   ├── index.ts              # Core exports (framework-agnostic)
│   ├── jwt.ts                # JWT decoding utilities
│   ├── roles.ts              # Role checking utilities
│   └── next/
│       ├── index.ts          # Next.js adapter exports
│       ├── session.ts        # Session utilities
│       ├── api.ts            # API route utilities
│       ├── page.ts           # Page utilities
│       ├── proxy.ts          # Middleware/proxy utilities
│       └── components/
│           ├── app-layout.tsx     # Main layout component
│           ├── app-sidebar.tsx    # Sidebar component
│           ├── nav-main.tsx       # Navigation component
│           ├── nav-user.tsx       # User menu component
│           ├── team-switcher.tsx  # Organization switcher
│           ├── use-navigation.ts  # Navigation hook
│           └── ui/                # Internal UI components (shadcn)

Development

# Install dependencies
npm install

# Build the library
npm run build

# Watch mode for development
npm run dev

# Type checking
npm run typecheck

# Clean build artifacts
npm run clean

License

MIT