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

winbill

v2.1.1

Published

Effortlessly generate professional, beautiful PDF invoices and receipts for your Node.js applications.

Readme

winbill

Effortlessly generate professional, beautiful PDF invoices and receipts for your Node.js applications.

winbill allows you to dynamically generate beautiful, customizable PDFs with zero design headaches. Perfect for e-commerce backends, SaaS billing, and freelancer tooling!

Previews

Installation

npm install winbill

Features

  • Advanced Output: Generate directly to a disk file or directly to a memory Buffer for modern web streaming (Express, NestJS, Next.js).
  • Tax & Discount Engine: Supports stacked global taxes and discounts, categorized product/service groupings, and line-item exemptions.
  • Interactive Elements & Payments: Automatically renders clickable payment links, embeds QR codes, and dynamically draws complete "How to Pay" Bank Details blocks!
  • Document Watermarks: Fully customizable stamp tool for marking documents as "PAID", "DRAFT", "VOID", etc.
  • Strictly Typed & Validated: Full TypeScript support with robust zod validation. Invalid payloads throw immediately!
  • Internationalization & i18n: Native Intl.NumberFormat support for all ISO currency codes, plus a full translations dictionary to localize static PDF labels.
  • Theming & Custom Fonts: Inject your own custom .ttf font paths and define strict brand colors.
  • Multiple Layouts: Comes out-of-the-box with DEFAULT, MODERN, MINIMAL, and THERMAL (80mm POS) templates.
  • Extensible Architecture: Need a bespoke design? Implement ILayoutStrategy and inject your own completely custom layout!

Quick Start

import { Winbill, BillingData, GeneratorOptions } from "winbill";
import * as path from "path";

async function run() {
  const winbill = new Winbill();

  // Generate a random bill number
  const invoiceNumber = winbill.generateBillNumber("INV-");

  const data: BillingData = {
    companyName: "Acme Corp",
    companyAddress: ["123 Business Rd.", "Tech City, CA 90210"],
    clientName: "Globex Corporation",
    clientAddress: "456 Enterprise Way\nSpringfield, IL 62704",
    invoiceNumber: invoiceNumber,
    date: new Date(),
    dueDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), 
    currency: "USD",
    locale: "en-US",
    
    // Global Taxes
    taxes: [{ name: "State Tax", rate: 0.08 }],
    
    // Item Groupings
    categories: [
      {
        name: "Web Services",
        items: [
          { description: "Development", quantity: 40, unitPrice: 150.0 },
          { description: "Hosting (Tax Exempt)", quantity: 1, unitPrice: 50.0, isTaxExempt: true }
        ],
        // Category-specific taxes
        taxes: [{ name: "Digital Services Tax", rate: 0.05 }]
      }
    ],

    // Interactive & Payment Info
    paymentDetails: {
      paymentUrl: "https://stripe.com/pay/xyz", // Generates clickable link!
      qrCodeUrl: "https://stripe.com/pay/xyz",  // Automatically renders QR code!
      bankDetails: {
        bankName: "Global Tech Bank",
        accountNumber: "1234567890",
        routingNumber: "098765432"
      }
    },
    
    // Status Stamp
    watermark: { text: "DRAFT", color: "#e0e0e0", opacity: 0.3 },
    termsAndConditions: "1. All sales are final.\n2. Payment is due within 30 days." // Spawns an appendix page!
  };

  const options: GeneratorOptions = {
    filePath: path.join(__dirname, "invoice.pdf"),
    layout: 'DEFAULT',
    theme: { 
      primaryColor: "#005b96",
      translations: { invoice: "FACTURE" } // i18n example
    }
  };

  // Generate a PDF File
  await winbill.generateBill(data, options);

  // Or generate a memory Buffer to stream directly to web clients!
  // const pdfBuffer = await winbill.generateBuffer(data, options);
}

run();

API Reference

Winbill Class Methods

  • generateBill(data: BillingData, options: GeneratorOptions): Promise<void> Generates and saves the PDF file to disk (requires options.filePath).
  • generateBuffer(data: BillingData, options: GeneratorOptions): Promise<Buffer> Generates the PDF in memory and returns a Buffer (perfect for web servers).
  • generateBillNumber(prefix?: string): string Helper method to generate a randomized, alphanumeric bill number.

Interfaces

BillingData

interface BillingData {
  companyName: string;
  companyAddress?: string | string[]; 
  clientName: string;
  clientAddress?: string | string[];
  
  invoiceNumber: string;
  purchaseOrderNumber?: string;
  date: Date;
  dueDate?: Date;
  
  currency: string;
  locale?: string;
  
  // Categorized Items
  categories?: BillingCategory[];
  // Legacy / Flat Items
  items?: BillingItem[];
  
  // Global Modifiers
  taxes?: Tax[];
  discounts?: BillingDiscount[];
  
  logoPath?: string;
  notes?: string;
  termsAndConditions?: string;
  
  // Interactive Elements (Not allowed on Receipts)
  paymentDetails?: {
    paymentUrl?: string; 
    qrCodeUrl?: string;
    bankDetails?: {
      accountName?: string;
      accountNumber?: string;
      bankName?: string;
      iban?: string;
      swift?: string;
      routingNumber?: string;
    }
  };
  
  watermark?: {
    text: string;
    color?: string;
    opacity?: number;
    fontSize?: "xsmall" | "small" | "medium" | "large" | "xlarge";
  };
  
  // Convert document into a Receipt
  receipt?: ReceiptSettings;   
}

GeneratorOptions

interface GeneratorOptions {
  filePath?: string; // Required for generateBill()
  layout?: 'DEFAULT' | 'MODERN' | 'MINIMAL' | 'THERMAL';
  theme?: {
    primaryColor?: string;
    customFontPath?: { regular: string, bold: string }; // Use absolute paths to .ttf
    translations?: {
      invoice?: string;
      receipt?: string;
      invoiceNumber?: string;
      poNumber?: string;
      date?: string;
      dueDate?: string;
      from?: string;
      billTo?: string;
      description?: string;
      qty?: string;
      unitPrice?: string;
      total?: string;
      subtotal?: string;
    };
  };
}

License

Licensed under GPL-3.0.