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

@typeb-digital/nucleus-nextjs

v0.0.1

Published

Next.js (App Router) auth SDK for the Nucleus data platform — BFF pattern, encrypted httpOnly cookie sessions, great DX

Readme

@typeb-digital/nucleus-nextjs

Next.js App Router auth for the Nucleus platform — with the DX Next.js auth usually lacks.

Drop in middleware, wrap a provider, link to /auth/login, read getSession() in a Server Component. Done. No callback wiring, no token plumbing, no giant config object.

It uses a backend-for-frontend (BFF) model: the server owns the PKCE exchange and token refresh, tokens live in an encrypted, httpOnly cookie, and client code gets a thin useUser() hook. The browser never holds the refresh token — honoring Nucleus's "token never in the browser" rule.

Auth only. Like @typeb-digital/nucleus-client, this package never holds the app token and never calls data endpoints. For data, use @typeb-digital/nucleus-sdk from your Server Components / Route Handlers.


Installation

npm install @typeb-digital/nucleus-nextjs
# peer deps: next >= 14.2, react >= 19

Environment

NUCLEUS_APP_ID=app_xxxxxxxxxxxx          # public app id from the Nucleus dashboard
APP_BASE_URL=http://localhost:3000       # this app's URL — builds the redirect URI
NUCLEUS_SESSION_SECRET=<32-byte hex>     # cookie encryption — `openssl rand -hex 32`
# NUCLEUS_BASE_URL=https://nucleus.typeb-lab.online   # optional, this is the default

Register <APP_BASE_URL>/auth/callback as a redirect URI on your app in the Nucleus dashboard.


Quick start (4 steps)

1. Create the clientlib/nucleus.ts:

import { createNucleusClient } from '@typeb-digital/nucleus-nextjs';

export const nucleus = createNucleusClient({
  protectedRoutes: ['/dashboard'], // optional: middleware guards these
});

2. Mount the middlewaremiddleware.ts:

import { nucleus } from '@/lib/nucleus';

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

3. Wrap your layoutapp/layout.tsx:

import { NucleusProvider } from '@typeb-digital/nucleus-nextjs/client';
import { nucleus } from '@/lib/nucleus';

export default async function RootLayout({ children }) {
  const session = await nucleus.getSession();
  return (
    <html>
      <body>
        <NucleusProvider initialUser={session?.user ?? null}>{children}</NucleusProvider>
      </body>
    </html>
  );
}

4. Use it. Login/logout are plain links — no JS:

<a href="/auth/login">Sign in</a>
<a href="/auth/logout">Sign out</a>
// client component
'use client';
import { useUser } from '@typeb-digital/nucleus-nextjs/client';
const { user, isLoading } = useUser();
// Server Component / Route Handler / Server Action
const session = await nucleus.getSession(); // { user, accessToken, expiresAt } | null
const token = await nucleus.getAccessToken(); // valid access token for your backend calls

Prefer middleware mounting. If you'd rather not use middleware, mount the catch-all route handler instead — app/api/auth/[...nucleus]/route.ts: export const GET = nucleus.handler; (then point the routes at /api/auth/*). Both are supported.


Mounted routes

| Route | Purpose | | ------------------------ | --------------------------------------------------------------- | | GET /auth/login | Start PKCE; supports ?returnTo= and ?login_hint= | | GET /auth/callback | Finish PKCE, set the session cookie | | GET /auth/logout | Revoke the refresh-token family, clear the session | | GET /auth/profile | Current user JSON (used by useUser()) | | GET /auth/access-token | Fresh access token JSON (used by the client getAccessToken()) |

API

Server (@typeb-digital/nucleus-nextjs): createNucleusClient(options?){ middleware, handler, getSession(), getAccessToken(), config }.

Client (@typeb-digital/nucleus-nextjs/client): <NucleusProvider>, useUser(), useAccessToken(), getAccessToken(url?).

createNucleusClient options

All optional except where the env var is required. appId, baseUrl, appBaseUrl, sessionSecret, useRefreshTokens (default true), refreshLeewaySeconds (default 60), routes, cookie, protectedRoutes, postLogoutRedirect.


Refresh & the RSC cookie constraint (important)

React Server Components can read cookies but not write them. A token rotated during an RSC render therefore can't be persisted — and because Nucleus refresh tokens are single-use (a reused one revokes the whole family), silently dropping a rotation is dangerous.

This package solves it the right way: refresh happens in the middleware, which writes the rotated cookie back onto both the request and the response. By the time your RSC renders, the token is already fresh, so getSession()/getAccessToken() are pure reads.

So: use the middleware (the default). If getAccessToken() ever needs to refresh in a context that can't write cookies (e.g. you skipped middleware), it throws a clear error telling you to add it — rather than corrupting the session.

Security notes

  • Session lives in an httpOnly, Secure (when APP_BASE_URL is https), SameSite=Lax, JWE-encrypted cookie. The refresh token never reaches the browser.
  • NUCLEUS_SESSION_SECRET must be strong (openssl rand -hex 32) and kept secret.
  • Refresh is deduplicated per refresh token within a server instance. Under heavy concurrent refresh on a stateless cookie there's a small race window with rotation; concentrating refresh in middleware avoids it in practice. A pluggable server-side session store may be added for high-concurrency deployments.

License

Proprietary — © Type B Digital.