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

@webbyx/next-js

v0.1.0

Published

Blazing fast development with NextJs helpers

Readme

@webbyx/next-js

Blazing-fast helpers for Next.js apps — opinionated wrappers around Apollo Client, authentication flows, and route progress UI. Works with both the Pages Router (HOC pattern) and the App Router (provider + server-helper pattern).


Table of contents


Installation

npm install @webbyx/next-js
# or
yarn add @webbyx/next-js

The package ships with @apollo/client, graphql, graphql-ws, @apollo/client-integration-nextjs, rxjs, next, react, react-dom, nookies, and styled-components as direct dependencies — no extra installs are required to use any of the features.

Subpath exports. The library exposes three entrypoints:

| Import path | Use for | | ---------------------------- | ------------------------------------------------------------------------------------------------- | | @webbyx/next-js | Pages Router (HOCs, factories, helpers) and shared types/hooks | | @webbyx/next-js/app | App Router client-safe APIs (providers, hooks, components) | | @webbyx/next-js/app/server | App Router server-only APIs (getAuthSession, createServerApolloClient, server cookie helpers) |


Quick start

Pages Router

// pages/_app.tsx
import type { AppProps } from "next/app";
import {
  withApolloClient,
  withAuthIdentity,
  withRouteIndicator
} from "@webbyx/next-js";
import { apolloOptions } from "../config/apollo";
import { authOptions } from "../config/auth";

const MyApp = ({ Component, pageProps }: AppProps) => (
  <Component {...pageProps} />
);

export default withRouteIndicator()(
  withApolloClient({ ssr: true, options: apolloOptions })(
    withAuthIdentity({ ssr: true, apollo: true, options: authOptions })(MyApp)
  )
);

App Router

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

import {
  ApolloAppProvider,
  AuthIdentityProvider,
  RouteIndicator
} from "@webbyx/next-js/app";
import { apolloOptions } from "../config/apollo";
import { authConfig } from "../config/auth";

export const Providers = ({
  children,
  initialAuthUser,
  initialConfig
}: {
  children: React.ReactNode;
  initialAuthUser: User | null;
  initialConfig: Record<string, unknown>;
}) => (
  <ApolloAppProvider options={apolloOptions}>
    <AuthIdentityProvider
      config={authConfig}
      initialAuthUser={initialAuthUser}
      initialConfig={initialConfig}>
      <RouteIndicator />
      {children}
    </AuthIdentityProvider>
  </ApolloAppProvider>
);
// app/layout.tsx
import { getAuthSession } from "@webbyx/next-js/app/server";
import { authConfig } from "../config/auth";
import { Providers } from "./providers";
import { headers } from "next/headers";

export default async function RootLayout({
  children
}: {
  children: React.ReactNode;
}) {
  const pathname = (await headers()).get("x-pathname") ?? "/";
  const { authUser, config } = await getAuthSession(
    { pathname },
    authConfig.options,
    /* redirect */ false
  );

  return (
    <html lang="en">
      <body>
        <Providers initialAuthUser={authUser} initialConfig={config}>
          {children}
        </Providers>
      </body>
    </html>
  );
}

Pages Router usage

All Pages-Router APIs are imported from the package root:

import {
  withApolloClient,
  withAuthIdentity,
  withAuthServerSideProps,
  withRouteIndicator,
  useAuthIdentity,
  AuthIdentityContext,
  createApolloClient,
  createApolloContext,
  createAuthConfigProps,
  getCookie,
  setCookie,
  destroyCookie,
  setAuthToken,
  clearAuthToken,
  retrieveAuthTokenFromContext,
  redirect
} from "@webbyx/next-js";

withApolloClient

HOC that mounts an Apollo Client on the page tree and (optionally) hydrates the cache at SSR time.

// pages/_app.tsx
import { withApolloClient } from "@webbyx/next-js";

const MyApp = (props) => <props.Component {...props.pageProps} />;

export default withApolloClient({
  ssr: true,
  options: {
    graphqlRequest: { uri: "https://api.example.com/graphql" },
    websocketRequest: { url: "wss://api.example.com/graphql" },
    getAuthToken: async (ctx) => retrieveAuthTokenFromContext(ctx)
  }
})(MyApp);

| Prop | Type | Description | | --------- | --------------------------------------------- | ---------------------------------------------------------- | | ssr | boolean | Run getInitialProps and extract Apollo cache during SSR. | | options | ApolloClientOptions | Apollo configuration (links, cache, websocket, auth). |

withAuthIdentity

HOC that attaches an authenticated session, manages cross-tab signout, and computes redirection rules from AuthOptions.paths.

// pages/_app.tsx
import { withApolloClient, withAuthIdentity } from "@webbyx/next-js";

const MyApp = (props) => <props.Component {...props.pageProps} />;

export default withApolloClient({ ssr: true, options: apolloOptions })(
  withAuthIdentity({
    ssr: true,
    apollo: true,
    options: {
      checkAuthProfile: async () => fetchMe(),
      refreshAccessToken: async () => refreshToken(),
      paths: {
        signInPath: "/signin",
        afterAuthPath: "/app",
        beforeAuthPath: "/",
        allowedBeforeAuthPaths: ["/", "/signin", "/signup"],
        restrictAfterAuthPaths: ["/signin", "/signup"]
      }
    }
  })(MyApp)
);

| Prop | Type | Description | | --------- | ----------------------------- | -------------------------------------------------------------------------------- | | ssr | boolean | Resolve the auth user during getInitialProps. | | apollo | boolean | When true, requires withApolloClient and resets the Apollo cache on signout. | | options | AuthOptions | Auth resolver, paths, and redirection rules. |

withAuthServerSideProps

A getServerSideProps factory you can drop into individual pages when you want per-page SSR auth resolution (instead of app-wide withAuthIdentity({ ssr: true })).

// pages/dashboard.tsx
import { withAuthServerSideProps } from "@webbyx/next-js";

export const getServerSideProps = withAuthServerSideProps(
  { ...authOptions, redirection: true },
  ({ authUser }) =>
    async () => ({
      props: { dashboardData: await fetchDashboard(authUser) }
    })
);

withRouteIndicator

A top-of-page progress bar driven by Next.js Router.events.

// pages/_app.tsx
import { withRouteIndicator } from "@webbyx/next-js";

const MyApp = (props) => <props.Component {...props.pageProps} />;
export default withRouteIndicator({ color: "#f85656", height: 4 })(MyApp);

| Option | Type | Default | Description | | -------- | -------- | --------- | --------------------- | | color | string | #f85656 | Bar color. | | height | number | 4 | Bar height in pixels. |


App Router usage

App-Router APIs are split between two entrypoints. Client-safe APIs come from @webbyx/next-js/app; server-only APIs come from @webbyx/next-js/app/server. Importing a server-only export into a client component will fail at runtime — keep the boundary clean.

// Client-safe (use in client components, layouts, etc.)
import {
  ApolloAppProvider,
  AuthIdentityProvider,
  RouteIndicator,
  buildApolloLink
} from "@webbyx/next-js/app";

// Server-only (use in server components / route handlers / server actions)
import {
  createServerApolloClient,
  getAuthSession,
  getServerCookie,
  setServerCookie,
  deleteServerCookie,
  getServerAuthToken
} from "@webbyx/next-js/app/server";

<ApolloAppProvider>

Streaming-aware Apollo provider built on @apollo/client-integration-nextjs. Wrap your app's client tree once.

// app/providers.tsx
"use client";
import { ApolloAppProvider } from "@webbyx/next-js/app";

export const Providers = ({ children }: { children: React.ReactNode }) => (
  <ApolloAppProvider
    options={{
      graphqlRequest: { uri: "https://api.example.com/graphql" },
      websocketRequest: { url: "wss://api.example.com/graphql" }
    }}>
    {children}
  </ApolloAppProvider>
);

| Prop | Type | Description | | --------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | options | ApolloClientOptions | Same shape as the Pages Router. The provider uses the streaming-aware ApolloClient from @apollo/client-integration-nextjs so server-rendered queries hydrate correctly. |

createServerApolloClient

Per-request Apollo Client for use inside React Server Components, route handlers, and server actions.

// lib/apollo-server.ts
import {
  createServerApolloClient,
  getServerAuthToken
} from "@webbyx/next-js/app/server";

export const { getClient, query, PreloadQuery } = createServerApolloClient({
  graphqlRequest: { uri: "https://api.example.com/graphql" },
  getAuthToken: () => getServerAuthToken()
});
// app/dashboard/page.tsx
import { query } from "@/lib/apollo-server";
import { GET_DASHBOARD } from "@/queries";

export default async function DashboardPage() {
  const { data } = await query({ query: GET_DASHBOARD });
  return <Dashboard data={data} />;
}

Returned API: { getClient, query, PreloadQuery } from @apollo/client-integration-nextjs.

<AuthIdentityProvider>

Drop-in replacement for withAuthIdentity that subscribes to usePathname / useSearchParams from next/navigation. Hydrate it from getAuthSession.

"use client";
import { AuthIdentityProvider } from "@webbyx/next-js/app";

export const AuthBoundary = ({
  children,
  initialAuthUser,
  initialConfig
}: Props) => (
  <AuthIdentityProvider
    config={{
      apollo: true,
      options: {
        checkAuthProfile: async () => fetchMe(),
        refreshAccessToken: async () => refreshToken(),
        paths: {
          /* same shape as Pages Router */
        }
      }
    }}
    initialAuthUser={initialAuthUser}
    initialConfig={initialConfig}>
    {children}
  </AuthIdentityProvider>
);

| Prop | Type | Description | | ----------------- | --------------------------- | --------------------------------------------------------- | | config | AuthConfig | { apollo, options } — same as Pages Router minus ssr. | | initialAuthUser | T \| null | Hydrated from getAuthSession on the server. | | initialConfig | Record<string, unknown> | Hydrated derived config (e.g. shouldHideLayout). |

When config.apollo is true, the provider must be a child of <ApolloAppProvider> so it can clear the cache on sign-out.

getAuthSession

Server-side auth resolver. Reads the access cookie, calls checkAuthProfile, computes createAuthConfigProps, and (optionally) issues a next/navigation redirect for protected routes.

// app/(authenticated)/layout.tsx
import { getAuthSession } from "@webbyx/next-js/app/server";
import { headers } from "next/headers";
import { authConfig } from "@/config/auth";

export default async function ProtectedLayout({
  children
}: {
  children: React.ReactNode;
}) {
  const pathname = (await headers()).get("x-pathname") ?? "/";
  const { authUser, config } = await getAuthSession(
    { pathname },
    authConfig.options,
    /* redirect */ true
  );
  return (
    <Authed user={authUser} config={config}>
      {children}
    </Authed>
  );
}

| Argument | Type | Description | | ---------- | --------------------------------------- | -------------------------------------------------------------------------------------------- | | context | { pathname: string; asPath?: string } | Current request path. Pull from middleware-set headers or params. | | options | AuthOptions | Same as Pages Router. | | redirect | boolean (default true) | When true, the helper calls next/navigation's redirect() for any computed redirection. |

Returns: { authUser, config, redirection }.

<RouteIndicator> (App Router)

Top-loading-bar that pulses on every navigation by watching usePathname + useSearchParams. Mount once near the root.

// app/layout.tsx
import { RouteIndicator } from "@webbyx/next-js/app";

export default function RootLayout({
  children
}: {
  children: React.ReactNode;
}) {
  return (
    <html>
      <body>
        <RouteIndicator color="#f85656" height={4} />
        {children}
      </body>
    </html>
  );
}

Same color / height options as the Pages Router HOC.


Shared APIs

useAuthIdentity

Consume the auth context from anywhere inside <AuthIdentityProvider> or withAuthIdentity.

import { useAuthIdentity } from "@webbyx/next-js"; // also re-exported from /app via the auth context

const Header = () => {
  const { authUser, signOut } = useAuthIdentity<User>();
  return authUser ? (
    <button onClick={signOut}>Sign out</button>
  ) : (
    <SignInLink />
  );
};

Returned shape (AuthIdentityProps<T>):

| Field | Type | Description | | --------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------- | | authUser | T \| null | Current user. | | config | Record<string, any> | Computed redirection / layout config. | | signIn(token) | (token: string) => void | Persist token and navigate to paths.afterAuthPath. | | signOut() | () => Promise<void> | Reset Apollo cache (if enabled), clear token, broadcast sign-out across tabs, navigate to paths.beforeAuthPath. | | refetch() | () => Promise<T \| null> | Re-run checkAuthProfile. | | setAuthUser(user?) | (user?: T) => void | Optimistically set the user. | | setAuthToken(token) | (token: string) => void | Persist a token without navigation. | | refreshToken() | () => Promise<void> | Calls options.refreshAccessToken. | | clearAuthToken() | () => void | Drop the cookie locally. |

Factories

Useful when you need raw access (e.g. building a custom test harness or wiring Apollo into a custom server framework).

| Export | Where it lives | Purpose | | ---------------------------------------------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | createApolloClient(initialState, options, context) | @webbyx/next-js | Pages-Router Apollo factory used internally by withApolloClient. | | initApolloClient(initialState, options, context) | @webbyx/next-js | Singleton-on-client / fresh-on-server wrapper. | | createApolloContext(options, ctx) | @webbyx/next-js | Installs an Apollo client onto a NextPageContext for use inside getStaticProps / getServerSideProps. | | createAuthConfigProps(ctx, authUser, options, redirect?) | @webbyx/next-js | Pure path-rules engine — returns { redirection, config }. Reused by both routers. | | buildApolloLink(options, context) | @webbyx/next-js/app | Shared link/cache builder — mirrors the Pages-Router link chain (auth, error, http, optional GraphQL-WS). Useful if you want to assemble a custom Apollo client on top. | | createServerApolloClient(options) | @webbyx/next-js/app | RSC-scoped Apollo client (see above). |

Helpers

import {
  // cookie helpers (Pages Router context-aware)
  getCookie,
  setCookie,
  destroyCookie,
  eraseCookieFromAllPaths,
  // token helpers
  setAuthToken,
  clearAuthToken,
  setAuthTokenToContext,
  retrieveAuthTokenFromContext,
  getTokenFromCookies,
  // navigation (Pages Router only)
  redirect
} from "@webbyx/next-js";

| Helper | Signature | Notes | | ------------------------------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | | getCookie(key, ctx?) | (string, NextContextPayload?) => string \| null | Reads from nookies (server: from ctx.req; client: from document.cookie). | | setCookie(key, value, ctx?, days?, path?) | | days defaults to 30, path to /. | | destroyCookie(key, ctx) | | Also calls eraseCookieFromAllPaths to scrub legacy entries. | | setAuthToken(token, key?, days?) | | Wrapper around setCookie keyed by accessTokenKey (default "token"). | | clearAuthToken(key?) | | Removes the auth cookie everywhere. | | retrieveAuthTokenFromContext(ctx?, key?) | | Auto-detects AppContext vs NextPageContext. | | redirect(ctx, target, method?) | method"replace" (default) | "push" | "reload" | "force-reload" | "external" | On the server it writes a 303; on the client it goes through next/router. |

Server cookies (App Router only)

Not part of the Pages-Router helper set — these use next/headers and are async.

import {
  getServerCookie,
  setServerCookie,
  deleteServerCookie,
  getServerAuthToken
} from "@webbyx/next-js/app/server";

const token = await getServerAuthToken(); // defaults to "token"
await setServerCookie("locale", "en", /* days */ 365);
await deleteServerCookie("legacy_session");

TypeScript types

All public types are exported from the package root and re-exported by /app where relevant.

ApolloClientOptions

type ApolloClientOptions = Omit<
  ApolloClient.Options,
  "uri" | "credentials" | "headers" | "cache" | "ssrMode"
> & {
  graphqlRequest: { uri: string; credentials?: RequestCredentials };
  cache?: ApolloCache;
  cacheConfig?: InMemoryCacheConfig;
  websocketRequest?: WsClientOptions | ((ctx?: any) => WsClientOptions);
  websocketEvents?: WsEventListener;
  getAuthToken?: (ctx?: any) => Promise<string | null>;
  constructApolloLinks?: (
    links: {
      errorLink: ApolloLink;
      authLink: ApolloLink;
      httpLink: ApolloLink;
    },
    ctx: any
  ) => ApolloLink[];
  connectToDevTools?: boolean;
};

WsEventListener

onPing, onPong, onError, onOpened, onClosed, onMessage, onConnected, onConnecting — all optional, all from graphql-ws.

AuthOptions

type AuthOptions<T = any> = {
  paths: AuthPaths;
  logging?: boolean;
  enableAdmin?: boolean;
  enableOnboarding?: boolean;
  enableNotFoundRedirection?: boolean;
  valueKeyAdmin?: string; // default: "isAdmin"
  valueKeyOnboard?: string; // default: "setupIsRequired"
  accessTokenKey?: string; // default: "token"
  accessTokenValidityDays?: number; // default: 30
  syncAuthEventKeyName?: string; // localStorage key for cross-tab signout
  checkAuthProfile: (ctx?: any) => Promise<T | null>;
  refreshAccessToken?: (ctx?: any) => Promise<string>;
  checkRequiredOnboard?: (user: T) => Promise<boolean>;
  onChangePath?: (paths: string[], user?: T) => Promise<string | false>;
  onConstructConfig?: (
    paths: string[],
    user?: T
  ) => Promise<Record<string, any> | false>;
};

AuthPaths

type AuthPaths = {
  notFoundPath?: string;
  signInPath: string;
  afterAuthPath: string;
  beforeAuthPath: string;
  onboardingPath?: string;
  allowedBeforeAuthPaths: string[];
  restrictAfterAuthPaths: string[];
  allowedAdminPaths?: string[];
  noLayoutPaths?: string[];
};

AuthConfig

type AuthConfig = {
  ssr?: boolean; // Pages Router only
  apollo?: boolean;
  options: AuthOptions;
};

RouteIndicatorOptions

type RouteIndicatorOptions = { color?: string; height?: number };

Compatibility matrix

| Peer | Tested with | | ----------------------------------- | ----------- | | next | ^16.0.0 | | react / react-dom | ^19.0.0 | | @apollo/client | ^4.0.0 | | @apollo/client-integration-nextjs | ^0.14.0 | | graphql | ^16.0.0 | | graphql-ws | ^6.0.0 | | styled-components | ^6.0.0 |


FAQ

Can I mix the two routers in one project? Yes. Pages Router code stays under pages/, App Router code under app/. Import HOCs from @webbyx/next-js for the former and providers from @webbyx/next-js/app for the latter — they don't share runtime state, so make sure each tree gets its own provider/HOC.

Why does <AuthIdentityProvider> need an initial user? The hydration is done on the server through getAuthSession. Passing initialAuthUser and initialConfig avoids a client-side flicker while the user resolves.

Why is lib/dom pinned to ES2020 in tsconfig.json? The current ESLint stack (@typescript-eslint/parser 4.x, eslint 7.x) can't parse newer lib values. Modernizing the lint stack is a separate task; the runtime itself supports modern targets.

Subscriptions + App Router? Set options.websocketRequest on <ApolloAppProvider> exactly like the Pages Router. The link is only attached on the browser, so RSC queries are unaffected.


Changelog

v0.0.7 (unreleased)

  • Bumped Next.js to 16.2.4, React to 19.2.5, Apollo Client to 4.1.9.
  • Added App Router support under the ./app subpath: <ApolloAppProvider>, createServerApolloClient, <AuthIdentityProvider>, getAuthSession, <RouteIndicator>, server cookie helpers.
  • Modernized tsconfig.json; cleaned up redundant default exports.

v0.0.6

  • See git log for previous releases.