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

@perkamo/nextjs

v0.9.0

Published

Next.js helpers for Perkamo server routes and browser SDK integrations.

Readme

@perkamo/nextjs

Next.js helpers for Perkamo server routes and browser SDK integrations.

Use this package with supported Next.js LTS releases. Per the Next.js support policy, this package supports Next.js 16 Active LTS and Next.js 15 Maintenance LTS. It requires Node.js 20.9 or newer.

Full SDK documentation: https://www.perkamo.com/docs/v1/sdk

npm install @perkamo/nextjs @perkamo/browser @perkamo/sdk

App Router token routes

Create short-lived client tokens from trusted server code. Never expose a Perkamo server API key or signing secret to Client Components or browser code.

Create a signing key in the Perkamo console (Settings → Security → Signing keys). It gives you a KID (shown in the creation dialog and then listed in the table) and a one-time secret (shown once, backend-only). The route below reads both from environment variables — the names are your own choice:

// app/api/perkamo/token/route.ts
import { createPerkamoClientTokenRoute } from "@perkamo/nextjs/server";
import { auth } from "@/auth";

export const POST = createPerkamoClientTokenRoute({
  kid: process.env.PERKAMO_SIGNING_KID, // KID
  signingSecret: process.env.PERKAMO_SIGNING_SECRET, // backend-only
  getUserId: async () => (await auth())?.user?.id ?? null,
  scope: ["customer:read", "events:write"],
});

Each option means:

| Option | What it is | | --------------- | -------------------------------------------------------------------------------------------------------------- | | kid | KID of your signing key; goes in the token header. | | signingSecret | The signing key's one-time secret. Sensitive — keep it backend-only. | | getUserId | Resolves the authenticated user id from the request; return null to refuse with 401. | | scope | Client permissions: customer:read, events:write, stream:read. Default: customer:read + events:write. | | events | Optional allow-list of event names the token may emit. | | ttlSeconds | Token lifetime in seconds. Default 600; Perkamo clamps to the key's maximum. |

For customer streams, expose a separate endpoint so regular bearer tokens are not placed in EventSource URLs:

// app/api/perkamo/stream-token/route.ts
import { createPerkamoClientTokenRoute } from "@perkamo/nextjs/server";
import { auth } from "@/auth";

export const POST = createPerkamoClientTokenRoute({
  kid: process.env.PERKAMO_SIGNING_KID,
  signingSecret: process.env.PERKAMO_SIGNING_SECRET,
  getUserId: async () => (await auth())?.user?.id ?? null,
  scope: ["stream:read"],
});

kid and signingSecret also accept an async function returning the value, so you can load them from a secret manager instead of environment variables.

Client Components

Use @perkamo/nextjs/client only from Client Components.

"use client";

import { PerkamoProvider, usePerkamoCustomerJson } from "@perkamo/nextjs/client";

export function LoyaltyPanel() {
  return (
    <PerkamoProvider>
      <Points />
    </PerkamoProvider>
  );
}

function Points() {
  const { customer, loading, error, refresh } = usePerkamoCustomerJson();

  if (loading) return <p>Loading...</p>;
  if (error) return <button onClick={refresh}>Retry</button>;

  return <p>{customer?.wallets.points ?? 0} points</p>;
}

PerkamoProvider defaults to these token endpoints:

  • POST /api/perkamo/token
  • POST /api/perkamo/stream-token

Override them when your Next.js app uses different route names.

Server Components and actions

Use the root export or /server only from trusted server code:

import { createPerkamoNextServerClient } from "@perkamo/nextjs/server";

const perkamo = createPerkamoNextServerClient({
  apiKey: () => process.env.PERKAMO_SECRET_KEY,
});

export async function trackPurchase(userId: string, orderId: string) {
  "use server";

  await perkamo.emit(
    userId,
    "purchase.completed",
    { order_id: orderId },
    { txId: orderId },
  );
}

Security defaults

  • @perkamo/nextjs/server requires a kid and signing secret from trusted server code.
  • @perkamo/nextjs/client never accepts server API keys; it fetches short-lived client tokens from your own Next.js route handlers.
  • Token route helpers return 401 when getUserId() returns null, undefined or an empty string.
  • Server helpers use Web Request and Response, matching Next.js App Router route handlers and modern runtimes.
  • Helpers default to the hosted Perkamo API. Set baseUrl only for a custom, staging or private endpoint.
  • Perkamo API failures use PerkamoApiError from @perkamo/sdk, including requestId, retryAfter and rateLimit metadata when returned by the API or gateway.