pdf-certificate-kit
v0.1.0
Published
Lightweight, framework-agnostic certificate PDF generator built on pdf-lib. Template + data + signatures -> small vector PDF, in the browser or Node.
Maintainers
Readme
pdf-certificate-kit
Lightweight, framework-agnostic certificate PDF generator built on pdf-lib.
You give it an admin-editable template (logo + text with {{variables}} + theme), a flat data bag,
and a list of signatures; it returns a small, vector PDF — in the browser or in Node.
Built and consumed exactly like the in-repo czero package: TypeScript + Rollup → dist/index.{js,cjs,d.ts}.
Install
pdf-lib is a peer dependency (consumed from the host app to avoid duplication).
// the host app's package.json
{
"dependencies": {
"pdf-certificate-kit": "file:../pdf-certificate-kit", // or a published version range once released
"pdf-lib": "^1.17.1"
}
}Then build the package: npm install && npm run build inside pdf-certificate-kit/.
Usage
import { renderCertificate, downloadBytes } from "pdf-certificate-kit";
const pdfBytes = await renderCertificate({
template: {
logo: { data: logoBytesOrDataUrl, maxHeight: 60 },
eyebrow: "Indian Institute of Technology Indore",
title: "Certificate of Appointment",
body:
"This is to certify that {{name}} ({{rollNumber}}) has been appointed as\n" +
"{{position}} of {{club}} for the tenure {{tenure}}.",
theme: { accentColor: "#1360AB", orientation: "landscape" },
},
data: {
name: "Asha Rao",
rollNumber: "210123",
position: "General Secretary",
club: "Robotics Club",
tenure: "2025–2026",
},
signatures: [
{ name: "Dr. A. Mehta", position: "Dean, Student Affairs", image: deanSigBytes },
{ name: "Asha Rao", position: "Student", text: "Asha Rao" },
],
});
downloadBytes(pdfBytes, "por-certificate.pdf");Signature layout
The footer adapts to the number of signatures:
| Count | Layout | | ----- | --------------------------------------- | | 1 | right-aligned | | 2 | left and right | | 3+ | evenly spaced (wraps to rows if needed) |
API
renderCertificate(options): Promise<Uint8Array>— core renderer (isomorphic).applyTemplateVariables(text, data): string— substitute{{vars}}.extractTemplateVariables(text): string[]— list{{vars}}referenced (handy for admin UIs).downloadBytes(bytes, filename, mimeType?)— browser download helper.fetchAsBytes(url, init?): Promise<Uint8Array>— fetch an (e.g. signed) image URL as bytes.compressImage(fileOrBlob, options?): Promise<CompressedImage>— downscale/recompress images client-side so signatures (and the PDF) stay tiny.
Output uses only PDF standard fonts (no embedding), so files are small; keep logo/signature
images small via compressImage for best results.
