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

@rankbuddy/sdk

v0.3.4

Published

Headless SDK for RankBuddy SEO blog data, metadata, and React HTML render (Next.js App Router).

Readme

RankBuddy SDK

Headless SDK for RankBuddy SEO blog data, metadata helpers, and safe React HTML rendering.

Installation

npm install @rankbuddy/sdk

The package is ESM-only and requires Node.js 18+ or another runtime with fetch.

Server-Side Client

Keep apiKey on the server. createRankBuddyClient is server-only by default and throws in browser runtimes unless allowBrowser is explicitly enabled for a publishable key or trusted proxy.

import { createRankBuddyClient } from "@rankbuddy/sdk";

const rankBuddy = createRankBuddyClient({
  apiKey: process.env.RANKBUDDY_API_KEY!,
  siteUrl: "https://example.com",
  blogPath: "/blog",
});

const articles = await rankBuddy.articles.list({ limit: 10, page: 1 });
const article = await rankBuddy.articles.getBySlug("hello-world");
const metadata = await rankBuddy.seo.generateMetadata("hello-world");

// Topic hubs (SEO clusters)
const clusters = await rankBuddy.clusters.list();
const cluster = await rankBuddy.clusters.getBySlug("saas-blog-automation");
const topicArticles = await rankBuddy.clusters.listArticles("saas-blog-automation", {
  limit: 10,
  page: 1,
});

Client Options

  • apiKey: required secret API key.
  • apiUrl: optional API base URL. HTTPS is required.
  • fetch: optional custom fetch implementation for tests, proxies, or non-standard runtimes.
  • signal: optional AbortSignal applied to SDK requests.
  • timeoutMs: request timeout, default 10000.
  • siteUrl and blogPath: used to build canonical URLs when an article does not provide seo.canonicalUrl.
  • allowBrowser: explicit opt-in for browser usage. Do not use with secret keys.
  • apiUrl: must be HTTPS, except http://localhost / http://127.0.0.1 for local development.

Errors

SDK failures throw RankBuddyError with a stable code and optional status, responseBody, and cause.

import { RankBuddyError } from "@rankbuddy/sdk";

try {
  await rankBuddy.articles.getBySlug("missing-article");
} catch (error) {
  if (error instanceof RankBuddyError && error.status === 404) {
    // handle not found
  }
}

Next.js App Router (ISR)

Cache article data with a stable tag, then call revalidateTag with the same tag after you publish or update a post (in addition to any revalidatePath you use).

import {
  blogArticleCacheTag,
  createRankBuddyClient,
  getArticleBySlug,
} from "@rankbuddy/sdk";

const rankBuddy = createRankBuddyClient({
  apiKey: process.env.RANKBUDDY_API_KEY!,
});

// Server Component (ISR / static blog post page) — use instead of articles.getBySlug directly
const article = await getArticleBySlug(rankBuddy, slug);

After a successful publish from your app:

import { revalidatePath, revalidateTag } from "next/cache";
import { blogArticleCacheTag } from "@rankbuddy/sdk";

revalidateTag(blogArticleCacheTag(slug));
revalidatePath(`/blog/${slug}`);

Install next in your app. The optional peer is declared on the SDK. getArticleBySlug loads next/cache only when you call it.

Additional tags and loaders for listing pages, topic hubs, and related posts (same revalidateTag pattern):

  • blogListingCacheTag()/blog index (getArticlesList, getClustersList, getClusterSlugs).
  • blogTopicListingCacheTag(clusterSlug)/blog/topic/[clusterSlug] (getClusterBySlug, getClusterArticles).
  • blogRelatedCacheTag(slug) — related block on /blog/[slug] (getRelatedArticles).

After publish, call revalidateTag for the article slug, blogListingCacheTag(), blogRelatedCacheTag(slug), and each affected blogTopicListingCacheTag(clusterSlug) (plus revalidatePath if you use it).

React HTML Rendering

React helpers live in the optional @rankbuddy/sdk/react entry. React is an optional peer dependency for consumers who only use the headless client.

RenderContent sanitizes content.html by default before rendering with dangerouslySetInnerHTML.

import { RenderContent } from "@rankbuddy/sdk/react";
import type { RankBuddyContent } from "@rankbuddy/sdk";

export function Article({ article }: { article: { content: RankBuddyContent } }) {
  return <RenderContent content={article.content} />;
}

If HTML is already sanitized by trusted server code, use the explicit escape hatch:

<RenderContent content={article.content} unsafeSkipSanitization />

For server-side pipelines, the sanitizer is exported directly:

import { sanitizeRankBuddyHtml } from "@rankbuddy/sdk/react";

const safeHtml = sanitizeRankBuddyHtml(rawHtml);

Development

npm ci
npm run typecheck
npm run lint
npm test
npm run build

Example

A minimal Node.js example is available in examples/server-client.mjs.

RANKBUDDY_API_KEY=rb_... node examples/server-client.mjs

Release Checklist

Before publishing, run the full local release check:

npm run release:dry-run

This runs TypeScript checks, ESLint, tests, a production build, npm pack --dry-run, publint, and arethetypeswrong with the ESM-only profile.

Publish the public scoped package after the dry run passes:

npm publish --access public