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

@logicdine/medusa-plugin-invoice

v0.1.0

Published

Invoice generator plugin for Medusa v2 with multi-template support (PDF + HTML), POS receipts, and admin management

Readme

@logicdine/medusa-plugin-invoice

Invoice generator plugin for Medusa v2 with multi-template support, PDF & HTML engines, POS receipt sizes, and full admin management.

Features

  • Multiple Invoice Templates - Classic Invoice, Kitchen Order, Packing Slip, POS Receipt, or create your own
  • Two Template Engines - Native PDF (pdfmake) with section toggles, or HTML (Handlebars) for full customization
  • POS Receipt Support - 80mm and 58mm thermal receipt paper sizes with dynamic height estimation
  • Template Preview - Preview templates with sample data (75 items) before saving
  • Style Editor - Customize font sizes, colors, bold/italic per style category from the admin UI
  • Section Visibility - Toggle company header, addresses, item prices, totals, notes per template
  • Title Control - Show header on first page only or repeat on every page
  • Auto Invoice on Order - Generates invoice automatically when an order is placed
  • Email Notification - Sends invoice PDF as email attachment on order placement
  • Stale Invoice Tracking - Marks invoices as stale when orders are updated (edits, returns, exchanges)
  • Admin Widget - Invoice list with template selector on order detail page
  • Store API - Customers can download their invoices

Prerequisites

  • Medusa v2 application (v2.13+)
  • PostgreSQL database
  • Node.js >= 20

Installation

npm install @logicdine/medusa-plugin-invoice
# or
pnpm add @logicdine/medusa-plugin-invoice

Configuration

Add the plugin to your medusa-config.ts:

import { defineConfig } from '@medusajs/framework/utils'

export default defineConfig({
  // ...
  plugins: [
    {
      resolve: "@logicdine/medusa-plugin-invoice",
    },
  ],
})

Run migrations:

npx medusa db:migrate

This creates the required tables and seeds 5 built-in templates.

Built-in Templates

| Template | Type | Page Size | Description | |----------|------|-----------|-------------| | Classic Invoice | PDF | A4 | Full invoice with all sections | | Kitchen Order | PDF | A5 | Items + quantities only, no prices | | Packing Slip | PDF | A4 | Items + shipping address, no prices | | POS Receipt | PDF | 80mm | Compact thermal receipt layout | | HTML Invoice (Example) | HTML | A4 | Handlebars HTML template example |

Admin Pages

Invoice Settings (/app/settings/invoice-config)

Configure company information used across all templates:

  • Company name, address, phone, email
  • Company logo URL
  • Notes/footer text
  • Default template selection

Invoice Templates (/app/settings/invoice-templates)

Manage templates:

  • View all templates with type, page size, and default indicator
  • Create new templates (PDF or HTML type)
  • Edit templates with live PDF preview panel
  • Toggle section visibility (11 sections)
  • Customize styles (font size, color, bold, italic) for PDF templates
  • Delete custom templates (built-in templates are protected)

Order Invoice Widget

On each order detail page (order.details.side.before):

  • Template selector dropdown
  • Generate button
  • Invoice list with template name, status, date, and download link

API Endpoints

Admin

| Method | Endpoint | Description | |--------|----------|-------------| | GET | /admin/invoice-config | Get invoice configuration | | POST | /admin/invoice-config | Update invoice configuration | | GET | /admin/orders/:id/invoices | List invoices for an order | | POST | /admin/orders/:id/invoices | Generate invoice (optional template_id in body) | | GET | /admin/invoices/:id/download | Download invoice PDF | | GET | /admin/invoice-templates | List all templates | | POST | /admin/invoice-templates | Create a template | | GET | /admin/invoice-templates/:id | Get a template | | PUT | /admin/invoice-templates/:id | Update a template | | DELETE | /admin/invoice-templates/:id | Delete a template (blocks built-ins) | | POST | /admin/invoice-templates/:id/preview | Preview a saved template with sample data | | POST | /admin/invoice-templates/preview | Preview unsaved template config |

Store

| Method | Endpoint | Description | |--------|----------|-------------| | GET | /store/orders/:id/invoices | Download invoice PDF (customer) |

Creating Custom Templates

PDF Template

Create a template with type: "pdf" and configure sections:

{
  "name": "My Custom Invoice",
  "document_title": "TAX INVOICE",
  "type": "pdf",
  "page_size": "A4",
  "sections": {
    "company_header": true,
    "company_details": true,
    "invoice_metadata": true,
    "billing_address": true,
    "shipping_address": true,
    "items_table": true,
    "item_prices": true,
    "totals": true,
    "notes": true,
    "thank_you": true,
    "title_every_page": false
  },
  "styles": {
    "companyName": { "fontSize": 20, "color": "#1a365d", "bold": true },
    "invoiceTitle": { "fontSize": 28, "color": "#2c3e50" }
  }
}

HTML Template

Create a template with type: "html" and provide Handlebars HTML:

<div style="font-family: Helvetica, sans-serif;">
  <h1>{{config.company_name}}</h1>
  <h2>{{documentTitle}}</h2>
  <p>Invoice: {{invoiceId}} | Date: {{invoiceDate}}</p>
  <p>Order: #{{order.display_id}}</p>

  <table>
    <tr>
      <th>Item</th><th>Qty</th><th>Price</th><th>Total</th>
    </tr>
    {{#each items}}
    <tr>
      <td>{{this.title}}</td>
      <td>{{this.quantity}}</td>
      <td>{{this.unit_price}} {{../currency}}</td>
      <td>{{multiply this.unit_price this.quantity}} {{../currency}}</td>
    </tr>
    {{/each}}
  </table>

  <p><strong>Total: {{order.total}} {{currency}}</strong></p>
</div>

Available Handlebars variables:

  • order - Full order object (display_id, created_at, total, subtotal, tax_total, etc.)
  • config - Invoice config (company_name, company_address, company_phone, etc.)
  • items - Order line items array (title, quantity, unit_price, variant)
  • invoiceId - Invoice display ID
  • invoiceDate - Formatted invoice date
  • orderDate - Formatted order date
  • documentTitle - Template document title
  • billingAddress - Billing address object
  • shippingAddress - Shipping address object
  • currency - Currency code (uppercase)

Available Handlebars helpers:

  • {{multiply a b}} - Multiply two numbers
  • {{uppercase str}} - Convert to uppercase
  • {{formatDate date}} - Format a date string
  • {{padStart val len char}} - Pad a value

Page Sizes

| Value | Dimensions | Use Case | |-------|-----------|----------| | A4 | 210 x 297mm | Standard invoices | | A5 | 148 x 210mm | Kitchen orders, smaller documents | | LETTER | 8.5 x 11in | US letter size | | RECEIPT-80MM | 80mm x auto | Standard thermal receipt (most POS) | | RECEIPT-58MM | 58mm x auto | Narrow thermal receipt |

Receipt sizes use dynamic height estimation based on content — the PDF is always a single page.

Section Visibility

| Section | Description | |---------|-------------| | company_header | Logo + company name + document title | | company_details | Address, phone, email | | invoice_metadata | Invoice ID, date, order ID, order date | | billing_address | Bill-to address block | | shipping_address | Ship-to address block | | items_table | Order line items table | | item_prices | Price and total columns in items table | | totals | Subtotal, tax, shipping, total | | notes | Footer notes from config | | thank_you | "Thank you" message | | title_every_page | Repeat header on every page (vs first page only) |

Events & Subscribers

The plugin listens to these events:

| Event | Action | |-------|--------| | order.placed | Generate invoice + send email with PDF attachment | | order.updated | Mark existing invoices as stale | | order-edit.confirmed | Mark existing invoices as stale | | order.exchange_created | Mark existing invoices as stale | | order.claim_created | Mark existing invoices as stale | | order.return_received | Mark existing invoices as stale |

Workflows

Exported workflows you can use in custom code:

import {
  generateInvoicePdfWorkflow,
  markInvoiceStaleWorkflow,
  updateInvoiceConfigWorkflow,
  createInvoiceTemplateWorkflow,
  updateInvoiceTemplateWorkflow,
  deleteInvoiceTemplateWorkflow,
} from "@logicdine/medusa-plugin-invoice/workflows"

generateInvoicePdfWorkflow

const { result: pdfBuffer } = await generateInvoicePdfWorkflow(container).run({
  input: {
    order_id: "order_123",
    template_id: "inv_tmpl_kitchen", // optional, uses default if omitted
  },
})

Email Notifications

The plugin sends invoice PDFs as email attachments via Medusa's Notification Module. You need a configured notification provider (e.g. SendGrid, Resend) with an order-placed email template.

License

MIT