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

@syedalihamzazaidi/renderkit

v0.2.0

Published

Render JSON design scenes (Fabric.js or Polotno-style) to PNG/JPEG/PDF buffers.

Readme

RenderKit

Render JSON design scenes — Fabric.js canvas JSON or Polotno-style pages — to PNG/JPEG images in Node.js, using node-canvas and fabric.js.

npm install @syedalihamzazaidi/renderkit
import { renderDesign } from '@syedalihamzazaidi/renderkit';
import { writeFile } from 'fs/promises';

const { png, jpeg } = await renderDesign({
  pages: [{
    width: 400,
    height: 300,
    background: '#ffffff',
    children: [
      {
        type: 'text',
        x: 20, y: 20,
        width: 360, height: 60,
        text: 'Hello RenderKit',
        fontFamily: 'Roboto',
        fontSize: 32,
        fontWeight: '700',
        fill: '#111111',
        align: 'center',
      },
      {
        type: 'figure',
        subType: 'rect',
        x: 50, y: 100,
        width: 300, height: 150,
        fill: '#4f46e5',
        cornerRadius: 12,
      },
    ],
  }],
});

await writeFile('output.png', png);

png and jpeg are Buffers — do whatever you want with them: save to disk, upload to storage, stream in an HTTP response, etc.

Also included in this repo: a ready-to-run NestJS HTTP server that wraps the same rendering engine, for teams who'd rather call a REST endpoint than embed the library. See Run as a server below.

Requirements

  • Node.js >= 18
  • canvas's native build dependencies for your OS (Cairo, Pango, etc.) — see the node-canvas installation guide
  • Outbound internet access at render time if you use Google Fonts (see Fonts)

API

renderDesign(design, options?)

function renderDesign(design: unknown, options?: RenderOptions): Promise<RenderResult>;

interface RenderOptions {
  /** Also write output.png / output.jpg to this directory. */
  outDir?: string;
  /** JPEG quality, 0-1. Defaults to 0.9. */
  jpegQuality?: number;
}

interface RenderResult {
  png: Buffer;
  jpeg: Buffer;
  /** Present only when `outDir` was provided. */
  files?: { png: string; jpeg: string };
}

Throws RenderError (also exported) when the design JSON is invalid or rendering fails.

import { renderDesign, RenderError } from '@syedalihamzazaidi/renderkit';

try {
  const result = await renderDesign(design, { outDir: './output' });
  console.log(result.files); // { png: './output/output.png', jpeg: './output/output.jpg' }
} catch (err) {
  if (err instanceof RenderError) {
    console.error('Invalid design:', err.message);
  }
}

Design JSON schema

A design is either a full document ({ "pages": [...] }, first page used) or a single page object directly. Each page needs:

  • width, height — required numbers
  • background — optional CSS color string
  • One of:
    • json — a raw Fabric.js canvas JSON object (passed straight to canvas.loadFromJSON), or
    • children — an array of Polotno-style elements (converted to Fabric internally)

Polotno children element types

Common fields on every element: type, x, y, rotation, opacity, visible (elements with visible: false are skipped).

type: "text"

| Field | Notes | |---|---| | text | string content | | width, height | box size | | fontSize | number | | fontFamily | any Google Fonts family name (fetched live, see below) | | fontWeight | number or string, default "400" | | fontStyle | "italic" or other | | align | text alignment | | fill | text color | | textDecoration | "underline" or "line-through" | | lineHeight, letterSpacing | numbers |

type: "image" / "svg"

| Field | Notes | |---|---| | src | required — URL, data URI, or resolvable path | | width, height | used to compute scaleX/scaleY against natural image size | | flipX, flipY | booleans |

type: "figure"

| Field | Notes | |---|---| | subType | "circle" or "rect" (default "rect") | | width, height | shape size | | fill | fill color | | stroke, strokeWidth | stroke (ignored if stroke is "transparent") | | cornerRadius | rect only |

Any other type is silently dropped.

Fonts

Text elements load fonts on demand from Google Fonts (https://fonts.googleapis.com/css2?family=...), download the .ttf, register it with node-canvas, and cache it on disk under .font-cache/ in the current working directory. This means:

  • Your process needs outbound network access at render time for any font not already cached.
  • Only fonts published on Google Fonts are supported; unsupported families/weights/styles fail silently and fall back to the canvas default — no error is raised.
  • Fabric-JSON-only payloads (page.json) never trigger font loading.

Current limitations

  • Only PNG and JPEG output are implemented — no PDF or SVG export yet.
  • Font loading and outDir writes touch the filesystem/network — for a pure in-memory environment, stick to page.json (Fabric JSON) input and ignore files/outDir.

Run as a server

This repo also ships the NestJS app that exposes renderDesign over HTTP, if you'd rather run a service than embed the library.

git clone https://github.com/codewithalihamza/renderkit.git
cd renderkit
npm install
npm run start:dev

Environment variables

| Variable | Default | Description | |------------|---------------|-------------------------------| | PORT | 5000 | HTTP port the server binds to | | NODE_ENV | development | Environment name |

Endpoints

GET /health

curl http://localhost:5000/health

POST /render — body is a design JSON object (see schema above).

curl -X POST http://localhost:5000/render \
  -H "Content-Type: application/json" \
  -d '{"pages":[{"width":400,"height":300,"background":"#ffffff","children":[{"type":"figure","subType":"rect","x":50,"y":100,"width":300,"height":150,"fill":"#4f46e5","cornerRadius":12}]}]}'
{
  "success": true,
  "data": { "success": true, "png": "output/output.png", "jpeg": "output/output.jpg" },
  "timestamp": "..."
}

The png/jpeg fields are paths relative to the server's working directory — the endpoint does not stream image bytes back. Files are written to <project root>/output/output.png and output.jpg; without a shared volume, they won't be reachable across multiple server instances.

GET /render renders a fixed design file at <project root>/raffle-ticket-design.json, which is not included in this repo — add your own JSON at that path first, or this route returns 404.

Build scripts

npm run build        # nest build (also compiles the library entry point)
npm run start:prod   # node dist/main

Author

Ali Hamza — LinkedIn

License

MIT