@rankbuddy/sdk
v0.3.4
Published
Headless SDK for RankBuddy SEO blog data, metadata, and React HTML render (Next.js App Router).
Maintainers
Readme
RankBuddy SDK
Headless SDK for RankBuddy SEO blog data, metadata helpers, and safe React HTML rendering.
Installation
npm install @rankbuddy/sdkThe 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: optionalAbortSignalapplied to SDK requests.timeoutMs: request timeout, default10000.siteUrlandblogPath: used to build canonical URLs when an article does not provideseo.canonicalUrl.allowBrowser: explicit opt-in for browser usage. Do not use with secret keys.apiUrl: must be HTTPS, excepthttp://localhost/http://127.0.0.1for 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()—/blogindex (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 buildExample
A minimal Node.js example is available in examples/server-client.mjs.
RANKBUDDY_API_KEY=rb_... node examples/server-client.mjsRelease Checklist
Before publishing, run the full local release check:
npm run release:dry-runThis 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