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

@veztraa/report-renderer

v0.3.4

Published

Render JSON report templates to PDF in Node.js or the browser — zero Chromium, zero Python. Supports 12 element types including signature blocks, repeating container bands, and multilingual text (Chinese, Japanese, Korean, Arabic, Hebrew, Hindi, Thai) via

Readme

@veztraa/report-renderer

Documentation & Live Demo →

PDF rendering engine for ReportForge. Converts a template JSON + data object into a PDF buffer — pure Node.js, zero Chromium, zero Python.

Works in Node.js and the browser from a single install. Supports 12 element types including signature blocks and repeating container bands. Fonts (12 Latin families, 4 handwriting fonts, 8 multilingual Noto fonts) are registered automatically — no manual setup needed.

Installation

npm install @veztraa/report-renderer

Usage

Node.js (Express, Next.js API route, CLI, etc.)

import { render } from "@veztraa/report-renderer";

const pdf = await render(template, data);

// Save to file
import fs from "fs";
fs.writeFileSync("report.pdf", pdf);

Next.js API route

import { NextRequest, NextResponse } from "next/server";
import { render } from "@veztraa/report-renderer";

export async function POST(req: NextRequest) {
  const { template, data } = await req.json();

  if (!template || !data) {
    return NextResponse.json(
      { success: false, message: "Both 'template' and 'data' are required." },
      { status: 400 }
    );
  }

  const pdfBuffer = await render(template, data);

  return new NextResponse(pdfBuffer as any, {
    status: 200,
    headers: {
      "Content-Type": "application/pdf",
      "Content-Disposition": 'attachment; filename="report.pdf"',
    },
  });
}

Express

import express from "express";
import { render } from "@veztraa/report-renderer";

const app = express();
app.use(express.json());

app.post("/api/pdf", async (req, res) => {
  const { template, data } = req.body;
  const pdf = await render(template, data);
  res.setHeader("Content-Type", "application/pdf");
  res.setHeader("Content-Disposition", "attachment; filename=report.pdf");
  res.send(pdf);
});

Browser (React + Vite / Next.js client)

import { ReportDocument, usePDF } from "@veztraa/report-renderer";

function DownloadButton({ template, data }) {
  const doc = <ReportDocument template={template} data={data} />;
  const [{ url, loading }] = usePDF({ document: doc });

  if (loading) return <span>Rendering…</span>;
  return <a href={url} download="report.pdf">Download PDF</a>;
}

Bundlers (Vite, webpack) automatically pick the browser build via the browser export condition. Latin and handwriting fonts are embedded as base64 data URIs — no network requests, works offline. Noto multilingual fonts load from CDN on first use.

Pagination

The engine flows content-driven elements across pages automatically — no manual page math:

  • Tables break between rows and repeat the header on each continuation page.
  • Rich text breaks between lines; headings, images, and embedded tables are never split mid-element.
  • Repeating containers (type: "container" with a dataSource) flow item by item: an item that fits on a page is kept together, while an item taller than a page flows across pages.

Large reports & the browser main thread

render() / usePDF() lay the document out synchronously, so a very large report (hundreds of pages) will block the thread it runs on. In Node/CLI that's fine. In the browser, render inside a Web Worker to keep the UI responsive:

// worker-globals.ts — imported first so it runs BEFORE react-pdf loads.
const g = globalThis as any;
if (typeof g.window === "undefined") g.window = g;
export {};
// pdf.worker.ts
import "./worker-globals"; // MUST be the first import
import React from "react";
import { pdf, ReportDocument } from "@veztraa/report-renderer";

self.onmessage = async (e) => {
  const { template, data } = e.data;
  const blob = await pdf(React.createElement(ReportDocument, { template, data })).toBlob();
  self.postMessage({ blob });
};

@veztraa/report-designer already renders its live preview in a worker — you only need this if you call the renderer directly in the browser.

API

// Render to Buffer (Node.js) or Uint8Array (browser)
render(template: Template, data?: Record<string, unknown>): Promise<Buffer>

// Render to readable stream (Node.js only)
renderStream(template: Template, data?: Record<string, unknown>): Promise<NodeJS.ReadableStream>

// React component — use with usePDF in the browser
ReportDocument: React.FC<{ template: Template; data: Record<string, unknown> }>

// Re-exported from the underlying PDF engine for browser usage
usePDF, pdf, BlobProvider

Bundled Fonts

Latin & built-in (bundled — no network request)

| Family | Weights | |---|---| | Helvetica, Times Roman, Courier | Built-in (no download) | | Roboto | 400, 700, italic | | Open Sans | 400, 700, italic | | Lato | 400, 700, italic | | Montserrat | 400, 700, italic | | Inter | 400, 700 | | Poppins | 400, 700, italic | | Nunito | 400, 700, italic | | Raleway | 400, 700, italic | | Ubuntu | 400, 700, italic | | Playfair Display | 400, 700, italic | | Merriweather | 400, 700, italic | | Source Code Pro | 400, 700 |

Handwriting (bundled — for signature elements)

| Family | Use case | |---|---| | Great Vibes | Elegant cursive — formal signatures | | Dancing Script | Casual handwriting | | Pacifico | Rounded, friendly script | | Sacramento | Thin calligraphic script |

Use any handwriting family as style.fontFamily in a text element, or as scriptFont in a signature element.

Multilingual Noto fonts (CDN-loaded on first use)

@react-pdf has no automatic glyph fallback — you must pick a font family whose file contains your content's script glyphs. The Noto families below each cover one script:

| Family | Script | |---|---| | Noto Sans | Latin, Cyrillic, Greek | | Noto Sans SC | Chinese Simplified (also covers Latin) | | Noto Sans JP | Japanese (also covers Latin) | | Noto Sans KR | Korean (also covers Latin) | | Noto Sans Arabic | Arabic | | Noto Sans Hebrew | Hebrew | | Noto Sans Devanagari | Hindi / Devanagari | | Noto Sans Thai | Thai |

CJK fonts (SC, JP, KR) also include automatic per-character line-breaking so text wraps correctly even without spaces.

Template Format

See @veztraa/report-core for the full template schema and expression syntax.

Keywords

pdf pdf-generator pdf-renderer report nodejs-pdf react-pdf pdf-export no-chromium no-puppeteer server-side-pdf nextjs-pdf express-pdf signature multilingual reportforge

License

MIT © Veztraa Solutions