Official SDK
@renderfy/sdk
The official TypeScript SDK for Renderfy. Zero dependencies, fully typed, compatible with Node.js 18+, Next.js Edge Runtime, Cloudflare Workers, and Bun.
Installation
npm install @renderfy/sdk # or pnpm add @renderfy/sdk # or yarn add @renderfy/sdk # or bun add @renderfy/sdk
Get your API key at renderfy.io/dashboard. New accounts include 100 free credits.
Quick start
Save a rendered Tailwind card to disk in Node.js:
import { Renderfy } from "@renderfy/sdk";
import { writeFileSync } from "node:fs";
const renderfy = new Renderfy({ apiKey: process.env.RENDERFY_API_KEY! });
const { data } = await renderfy.tailwind(
`<div class="flex items-center justify-center h-full bg-gradient-to-br from-violet-600 to-indigo-600 p-12">
<div class="text-center text-white">
<h1 class="text-6xl font-bold mb-4">Hello, Renderfy</h1>
<p class="text-2xl opacity-80">Rendered in milliseconds.</p>
</div>
</div>`,
{ format: "png", dimensions: "1200x630" }
);
writeFileSync("output.png", Buffer.from(data));
console.log("Saved output.png");Client setup
import { Renderfy } from "@renderfy/sdk";
const renderfy = new Renderfy({
apiKey: "rfy_live_...", // required
baseUrl: "https://renderfy.io", // optional — override for proxies
timeout: 30_000, // optional — ms, default 30s
});Methods
All methods return Promise<RenderResult> — an object with data (ArrayBuffer), contentType, creditsCharged, and creditsRemaining.
renderfy.tailwind(content, options?)Render Tailwind CSS + HTML markup to PNG, JPEG, WebP, or PDF.
const { data } = await renderfy.tailwind(
`<div class="flex h-full items-center justify-center bg-zinc-900">
<h1 class="text-white text-5xl font-bold">Hello</h1>
</div>`,
{ format: "png", dimensions: "1200x630" }
);renderfy.html(content, options?)Render a raw HTML string — use inline styles or <style> blocks.
const { data } = await renderfy.html(
`<html><body style="background:#000;color:#fff;padding:2rem">
<h1 style="font-size:3rem">Invoice #1042</h1>
</body></html>`,
{ format: "pdf" }
);renderfy.markdown(content, options?)Render GitHub-Flavoured Markdown to a styled image or PDF.
const { data } = await renderfy.markdown(
"# Q4 Report\n\nRevenue grew **42%** this quarter.",
{ format: "pdf", dimensions: "595x842" }
);renderfy.chart(payload, options?)Render a bar, line, or pie chart from a data payload.
const { data } = await renderfy.chart(
{
type: "bar",
title: "Monthly Active Users",
labels: ["Jan", "Feb", "Mar"],
datasets: [{ label: "MAU", data: [12000, 18500, 22000], color: "#00e676" }],
},
{ format: "png", dimensions: "1200x630" }
);renderfy.diagram(payload, options?)Render any Mermaid diagram. flowchart TD is auto-prefixed when absent.
const { data } = await renderfy.diagram(
{ definition: "A[Client] --> B(API) --> C[(DB)]" },
{ format: "png", dimensions: "1200x800" }
);renderfy.code(payload, options?)Render syntax-highlighted source code as a macOS-style window card.
const { data } = await renderfy.code(
{ code: "const greet = (name: string) => `Hello, ${name}!`;", lang: "typescript" },
{ format: "png" }
);renderfy.math(latex, options?)Render a LaTeX expression. PNG output has a transparent background.
const { data } = await renderfy.math(
String.raw`E = mc^{2}`,
{ format: "png" }
);RenderOptions
Passed as the last argument to every helper method.
format"png" | "jpeg" | "webp" | "pdf"Output format. PNG, JPEG, and WebP cost 1 credit. PDF costs 3. WebP is 30–50% smaller than PNG with alpha support. Defaults to "png".
dimensionsstringCanvas size as "WIDTHxHEIGHT" in pixels. Common presets: "1200x630" (OG), "1080x1080" (square), "595x842" (A4). Defaults to "1200x630".
scalenumberDevice pixel ratio for HiDPI output. Default 2 (Retina). No effect on PDF.
qualitynumberJPEG quality 1–100. Default 90. Only applies when format is jpeg.
Error handling
The SDK throws typed errors so you can handle each failure mode precisely.
import {
Renderfy,
RenderfyAuthError,
RenderfyInsufficientCreditsError,
RenderfyValidationError,
RenderfyAPIError,
RenderfyError,
} from "@renderfy/sdk";
try {
const { data, creditsRemaining } = await renderfy.tailwind(content);
} catch (err) {
if (err instanceof RenderfyAuthError) {
// 401 — invalid or missing API key
} else if (err instanceof RenderfyInsufficientCreditsError) {
// 402 — out of credits
} else if (err instanceof RenderfyValidationError) {
// 400/422 — bad request payload
} else if (err instanceof RenderfyAPIError) {
console.error(err.status, err.apiMessage);
} else if (err instanceof RenderfyError) {
// timeout, network failure, etc.
}
}Next.js Route Handler
Stream a dynamic OG image on-demand from an App Router route.
// app/api/og/route.ts
import { NextRequest } from "next/server";
import { Renderfy } from "@renderfy/sdk";
const renderfy = new Renderfy({ apiKey: process.env.RENDERFY_API_KEY! });
export async function GET(req: NextRequest) {
const title = req.nextUrl.searchParams.get("title") ?? "Untitled";
const { data, contentType } = await renderfy.tailwind(
`<div class="flex items-center justify-center h-full bg-gradient-to-br
from-zinc-900 to-zinc-800 p-16">
<h1 class="text-white font-bold text-5xl text-center">${title}</h1>
</div>`,
{ format: "png", dimensions: "1200x630" }
);
return new Response(data, {
headers: {
"Content-Type": contentType,
"Cache-Control": "public, max-age=86400, immutable",
},
});
}Usage: GET /api/og?title=Hello+World → returns a 1200×630 PNG.
Cloudflare Workers
import { Renderfy } from "@renderfy/sdk";
export default {
async fetch(request: Request, env: { RENDERFY_API_KEY: string }) {
const renderfy = new Renderfy({ apiKey: env.RENDERFY_API_KEY });
const { data, contentType } = await renderfy.markdown(
"# Edge Report\n\nGenerated at the edge in **milliseconds**.",
{ format: "pdf" }
);
return new Response(data, {
headers: {
"Content-Type": contentType,
"Content-Disposition": 'attachment; filename="report.pdf"',
},
});
},
};