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

@pictify/sdk

v1.0.0

Published

Official Pictify Node.js SDK for generating images from HTML templates

Downloads

16

Readme

@pictify/sdk

Official Node.js SDK for Pictify — generate images, PDFs, and GIFs from HTML, live URLs, and reusable templates.

Installation

npm install @pictify/sdk
# or
yarn add @pictify/sdk
# or
pnpm add @pictify/sdk

Quick Start

import { Pictify } from '@pictify/sdk';

const pictify = new Pictify({
  apiKey: process.env.PICTIFY_API_KEY!,
});

// Render raw HTML to a PNG
const image = await pictify.renderHtml({
  html: '<div style="font-size:48px;padding:40px">Hello World</div>',
  width: 1200,
  height: 630,
});

console.log('Image URL:', image.url);

// Render a reusable template
const result = await pictify.render({
  templateId: 'your-template-uid',
  variables: { name: 'Ada', company: 'Pictify' },
});

console.log('Image URL:', result.url);

Features

  • Full TypeScript support — complete type definitions included
  • Promise-based API — modern async/await interface
  • Automatic retries — exponential backoff on 5xx and network errors
  • Typed errorsAuthenticationError, RateLimitError, QuotaExceededError, and more
  • Templates, HTML, URLs & GIFs — one client for every render type
  • Async batch rendering — submit large jobs and poll for progress

Constructor

const pictify = new Pictify({
  apiKey: string,      // Required: your Pictify API key
  baseUrl?: string,    // Optional: API base URL (default: https://api.pictify.io)
  timeout?: number,    // Optional: request timeout in ms (default: 30000)
  retries?: number,    // Optional: number of retries on 5xx/network errors (default: 3)
});

API Reference

renderHtml(options)

Render an image (or PDF) directly from HTML. POST /image.

const image = await pictify.renderHtml({
  html: '<div style="padding:40px">Hello</div>',
  css: 'div { color: blue; }', // optional — inlined into a <style> tag
  width: 1200,                 // optional (default: 1280)
  height: 630,                 // optional (default: 720)
  selector: '#card',           // optional — crop to a specific element
  format: 'png',               // optional: 'png' | 'jpg' | 'jpeg' | 'webp' | 'pdf' (default: png)
});

// Result: { url, id, createdAt }
console.log(image.url);

renderUrl(options)

Screenshot a live URL. POST /image with url.

const image = await pictify.renderUrl({
  url: 'https://example.com',
  width: 1280,
  height: 720,
  selector: '.hero', // optional
  format: 'png',     // optional
});

// Result: { url, id, createdAt }
console.log(image.url);

render(options)

Render a single image (or PDF) from a template. POST /templates/:uid/render.

const result = await pictify.render({
  templateId: 'template-uid',
  variables: { title: 'My Post', author: 'Ada' },
  format: 'png',  // optional: 'png' | 'jpg' | 'jpeg' | 'webp' | 'pdf' (default: png)
  quality: 0.9,   // optional render quality, 0.1–1.0 (default: 0.9)
  width: 1200,    // optional
  height: 630,    // optional
});

// The response is a results[] envelope. `result.url` is a convenience
// accessor for results[0]?.url.
console.log(result.url);
console.log(result.results[0]); // { layout, url, width, height, format, name, id, createdAt }

The response shape:

{
  results: RenderResultItem[];   // one entry per rendered layout
  errors: RenderErrorEntry[];    // { layout, error } for any failed layout
  totalLayouts: number;
  totalRendered: number;
  totalErrors: number;
  templateUid: string;
  url: string | undefined;       // convenience getter == results[0]?.url
}

renderLayouts(options)

Render multiple layout variants of a template in one call. POST /templates/:uid/render with layouts.

Templates can have layout variants (e.g. square, story) created via AI Resize in the Pictify editor. Use default for the base layout. Missing or invalid layouts come back in errors[] rather than throwing.

const result = await pictify.renderLayouts({
  templateId: 'template-uid',
  variables: { title: 'Hello World' },
  layouts: ['default', 'square', 'story'], // max 20
});

for (const item of result.results) {
  console.log(`${item.layout}: ${item.url} (${item.width}x${item.height})`);
}
for (const err of result.errors) {
  console.log(`${err.layout} failed: ${err.error}`);
}

renderGif(options)

Render an animated GIF from raw HTML, a live URL, or a template. POST /gif. Provide exactly one source.

const gif = await pictify.renderGif({
  html: '<style>@keyframes p{...}</style><div class="anim">Hi</div>',
  // or: url: 'https://example.com'
  // or: templateId: 'template-uid', variables: { name: 'Ada' }
  width: 400,         // optional (default: 800)
  height: 200,        // optional (default: 600)
  quality: 'medium',  // optional: 'low' | 'medium' | 'high' (default: medium)
});

// Result: { url, uid, width, height, animationLength }
console.log(gif.url);

The source HTML/URL must contain motion (e.g. a CSS animation). Static content produces no frames and returns an error.

renderBatch(options) + getBatchResults(batchId)

Submit an async batch render of a template across many variable sets. POST /templates/:uid/batch-render returns immediately with a batchId; poll getBatchResults to track progress.

const job = await pictify.renderBatch({
  templateId: 'template-uid',
  variableSets: [
    { name: 'Ada', company: 'Pictify' },
    { name: 'Grace', company: 'Pictify' },
  ], // max 100 per batch
  format: 'png',     // optional
  quality: 0.9,      // optional, 0.1–1.0
  concurrency: 5,    // optional, 1–10 (default: 5)
  // layout: 'square' or layouts: ['default', 'square'] — optional
});

// { batchId, status, totalItems }
console.log(job.batchId);

// Poll for progress.
const status = await pictify.getBatchResults(job.batchId);
console.log(status.status);          // 'pending' | 'processing' | 'completed' | 'partial' | 'failed' | 'cancelled'
console.log(status.completedItems, 'of', status.totalItems);
for (const item of status.results) {
  console.log(`item ${item.index}: success=${item.success}`);
}

Rendered URLs are not returned by the poll endpointgetBatchResults reports per-item { index, success, variables } (and error on failures). Final image URLs are delivered via the render.completed webhook. Subscribe to webhooks to collect batch output.

getTemplate(templateId)

Get a single template by its UID. GET /templates/:uid.

const template = await pictify.getTemplate('template-uid');

// { uid, name, html, width, height, engine, outputFormat,
//   variables: string[], variableDefinitions: [...], createdAt, ... }
console.log(template.uid, template.name);

listTemplates(options)

List templates in your account. GET /templates.

const { templates, pagination } = await pictify.listTemplates({
  page: 1,        // optional (default: 1)
  limit: 20,      // optional, max 100 (default: 12)
  sort: 'newest', // optional: 'newest' | 'oldest' | 'name'
});

console.log(pagination.total, 'templates');
for (const t of templates) console.log(t.uid, t.name);

createTemplate(options)

Create a template from HTML. POST /templates. Variables are auto-discovered from {{variableName}} tokens in the HTML body.

const template = await pictify.createTemplate({
  html: '<div>Hi {{firstName}}</div>',
  name: 'Welcome Card',     // optional
  width: 600,               // optional
  height: 200,              // optional
  variableDefinitions: [],  // optional — auto-extracted from the HTML when omitted
  outputFormat: 'image',    // optional: 'image' | 'pdf'
});

console.log(template.uid);

Error Handling

All API errors throw a typed subclass of PictifyError.

import {
  Pictify,
  PictifyError,
  AuthenticationError,
  TemplateNotFoundError,
  RateLimitError,
  QuotaExceededError,
  RenderError,
} from '@pictify/sdk';

try {
  const result = await pictify.render({ templateId: 'template-uid' });
} catch (error) {
  if (error instanceof RateLimitError) {
    console.log('Rate limited — slow down');
  } else if (error instanceof QuotaExceededError) {
    console.log('Quota exceeded — upgrade your plan');
  } else if (error instanceof RenderError) {
    console.error('Render/validation failed:', error.message, error.errors);
  } else if (error instanceof PictifyError) {
    console.error('Pictify error:', error.code, error.message);
  }
}

Error Types

| Error Class | Code | HTTP | Description | |------------|------|------|-------------| | AuthenticationError | INVALID_API_KEY | 401 | Invalid or missing API key | | QuotaExceededError | QUOTA_EXCEEDED | 402 / 429 | Render quota exceeded | | TemplateNotFoundError | TEMPLATE_NOT_FOUND | 404 | Template (or batch job) not found | | RenderError | RENDER_FAILED | 422 (and other 4xx) | Render or input validation failed (error.errors holds field-level details) | | RateLimitError | RATE_LIMIT_EXCEEDED | 429 | Too many requests | | ServerError | SERVER_ERROR | 5xx | Server-side failure | | NetworkError | NETWORK_ERROR | — | Network request failed | | TimeoutError | TIMEOUT | — | Request timed out |

CommonJS Support

const { Pictify } = require('@pictify/sdk');

const pictify = new Pictify({ apiKey: process.env.PICTIFY_API_KEY });

Examples

Express.js OG-image route

import express from 'express';
import { Pictify } from '@pictify/sdk';

const app = express();
const pictify = new Pictify({ apiKey: process.env.PICTIFY_API_KEY! });

app.get('/og-image', async (req, res) => {
  const { title, description } = req.query as Record<string, string>;

  const result = await pictify.render({
    templateId: 'og-template-uid',
    variables: { title, description },
  });

  res.redirect(result.url!);
});

Next.js route handler

// app/api/og/route.ts
import { Pictify } from '@pictify/sdk';
import { NextRequest, NextResponse } from 'next/server';

const pictify = new Pictify({ apiKey: process.env.PICTIFY_API_KEY! });

export async function GET(req: NextRequest) {
  const title = req.nextUrl.searchParams.get('title') ?? '';

  const result = await pictify.render({
    templateId: 'og-template-uid',
    variables: { title },
  });

  return NextResponse.redirect(result.url!);
}

License

MIT — see LICENSE for details.

Links