@jasy/pdf · declarative pdf engine · pure typescript
Create PDFs easier than ever.
A declarative, component-based PDF engine in pure TypeScript. Write components, get paper. ZUGFeRD & XRechnung compliant, with no headless browser and no Java underneath.
Invoice #2026-014
Acme GmbH · Berlin
- no chromium
- no jvm
- AFM + TrueType
- real pagination
- EN-16931
- MIT
one engine · two runtimes · same code
Runs on your server. And in the browser.
Pure TypeScript, no Node-only crutches. The same component tree produces the same byte-exact PDF whether it runs on a server or entirely in the browser - your call, not the library's.
on your server
Node, Nitro, Lambda, Workers
Generate invoices and reports in your API or backend - dependency-light, no Chromium to boot, no JVM to feed.
in the browser
100% client-side
Render the whole PDF in the user's browser - no server round-trip, works offline, and nothing ever leaves the device.
const bytes = await renderToBytes(doc) // same call, server or browser@jasy/vue · PDFs as Vue components
new · on npmYour PDF is a Vue component .
Author a document the way you build an app - components, props, slots and your reactive data - then render it to a real PDF, right in the browser. Real layout and pagination underneath, fully typed props, and a familiar feel if you have reached for @react-pdf/renderer on the React side.
pnpm add @jasy/vue@alpha vue<Document>
<Page :gap="12">
<Text :size="30" bold>{{ invoice.title }}</Text>
<Row
v-for="line in invoice.lines"
:key="line.id"
:justify="'between'"
>
<Text>{{ line.name }}</Text>
<Text bold>{{ line.total }} €</Text>
</Row>
</Page>
</Document>Components & props
Author a document the way you build an app - reusable components, props and slots.
v-for, v-if, computed
Your reactive data drives the page; loops, conditions and computed values just work.
Renders in the browser
The isomorphic engine turns the component tree into a PDF client-side - no server required.
@jasy/nuxt · the Nuxt module
new · on npmDrop it into Nuxt .
One install, zero config. Author PDFs as components and render them right in the browser, or stream them from a server route - your choice, the same components and helpers on both sides.
npx nuxi module add @jasy/nuxt<script setup>
const { open, download } = usePdf(Invoice)
</script>
<template>
<button @click="open">View PDF</button>
</template>// server/api/invoice/[id].get.ts
export default definePdfHandler((e) =>
Document([
Page([
Text(`Invoice #${getRouterParam(e, "id")}`),
]),
]),
)Zero config
Add it to modules. Components and the render helpers are auto-imported - no wiring, no imports.
Client or server
Render in the browser with usePdf, or stream from a Nitro route with definePdfHandler. Same vocabulary.
Nitro caching, lean bundle
Cache a route per path + query in one option. jimp stays server-side - the browser bundle stays small.
roadmap · MIT · built in the open
We're just getting started.
Built in the open, MIT-licensed. Here's where jasy is headed - the plan, in order, no dates promised.
Richer layout & styling
Gradients, SVG, aspect-ratio, min and max sizes, and the full flexbox model.
Documents that break right
Orphans and widows, and true multi-column, so a long report never breaks in the wrong place. (Page breaks and keep-together already shipped.)
More fonts
WOFF fonts and loading a font straight from a URL.
Forms
Fillable AcroForm fields: text, checkboxes, radios and dropdowns.
Read & edit existing PDFs
Open any PDF (even password-protected), edit it, and merge, split or extract pages.
Deeper e-invoicing & signatures
More Factur-X / ZUGFeRD profiles, Peppol, further country formats, and digital signatures.