Generate PDF documents programmatically with PDFKit — add text, images, vector graphics, tables, headers/footers, and custom fonts. Use when tasks involve creating invoices, reports, certificates, or any structured PDF output from application data in Node.js.
Programmatic PDF generation for Node.js. Streaming architecture — write to files or HTTP responses.
# Install PDFKit for PDF generation.
npm install pdfkit
npm install -D @types/pdfkit
// src/pdf/basic.ts — Create a simple PDF with text and save to file.
import PDFDocument from "pdfkit";
import fs from "fs";
const doc = new PDFDocument({ size: "A4", margin: 50 });
doc.pipe(fs.createWriteStream("output.pdf"));
doc.fontSize(24).text("Monthly Report", { align: "center" });
doc.moveDown();
doc.fontSize(12).text("Generated on " + new Date().toLocaleDateString());
doc.moveDown(2);
doc.fontSize(11).text(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
"Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
{ align: "justify", lineGap: 4 }
);
doc.end();
// src/pdf/table.ts — Draw a table with headers and rows.
// PDFKit has no built-in table; draw it with lines and positioned text.
import PDFDocument from "pdfkit";
export function drawTable(
doc: PDFKit.PDFDocument,
headers: string[],
rows: string[][],
startY: number
) {
const colWidth = (doc.page.width - 100) / headers.length;
const rowHeight = 25;
let y = startY;
// Header row
doc.font("Helvetica-Bold").fontSize(10);
headers.forEach((header, i) => {
doc.text(header, 50 + i * colWidth, y, { width: colWidth, align: "left" });
});
y += rowHeight;
doc.moveTo(50, y).lineTo(doc.page.width - 50, y).stroke();
// Data rows
doc.font("Helvetica").fontSize(10);
for (const row of rows) {
y += 5;
row.forEach((cell, i) => {
doc.text(cell, 50 + i * colWidth, y, { width: colWidth, align: "left" });
});
y += rowHeight;
// Page break if needed
if (y > doc.page.height - 100) {
doc.addPage();
y = 50;
}
}
}
// src/pdf/graphics.ts — Add images, draw shapes, and use vector graphics.
import PDFDocument from "pdfkit";
import fs from "fs";
const doc = new PDFDocument();
doc.pipe(fs.createWriteStream("report.pdf"));
// Embed an image
doc.image("logo.png", 50, 50, { width: 150 });
// Draw a colored rectangle
doc.rect(50, 250, 200, 100).fill("#3498db");
// Draw a circle
doc.circle(400, 300, 50).fill("#e74c3c");
// Draw a line
doc.moveTo(50, 400).lineTo(550, 400).dash(5, { space: 5 }).stroke("#999");
doc.end();
// src/pdf/headers.ts — Add repeating headers and footers with page numbers.
import PDFDocument from "pdfkit";
import fs from "fs";
export function createDocWithHeaderFooter(title: string, outputPath: string) {
const doc = new PDFDocument({ size: "A4", margin: 50, bufferPages: true });
doc.pipe(fs.createWriteStream(outputPath));
// Write content across multiple pages
doc.fontSize(20).text(title, { align: "center" });
doc.moveDown(2);
for (let i = 0; i < 200; i++) {
doc.fontSize(11).text(`Line ${i + 1}: Sample content for the report.`);
}
// Add headers and footers to all pages
const pageCount = doc.bufferedPageRange().count;
for (let i = 0; i < pageCount; i++) {
doc.switchToPage(i);
// Header
doc.fontSize(8).fillColor("#999")
.text(title, 50, 20, { align: "left" })
.text(new Date().toLocaleDateString(), 50, 20, { align: "right" });
// Footer with page number
doc.text(`Page ${i + 1} of ${pageCount}`, 50, doc.page.height - 30, {
align: "center",
});
}
doc.end();
}
// src/pdf/fonts.ts — Register and use custom fonts for branded documents.
import PDFDocument from "pdfkit";
import fs from "fs";
const doc = new PDFDocument();
doc.pipe(fs.createWriteStream("branded.pdf"));
// Register custom font
doc.registerFont("Inter", "./fonts/Inter-Regular.ttf");
doc.registerFont("Inter-Bold", "./fonts/Inter-Bold.ttf");
doc.font("Inter-Bold").fontSize(24).text("Branded Report");
doc.font("Inter").fontSize(12).text("Using custom Inter font throughout.");
doc.end();
// src/pdf/stream.ts — Generate PDFs on the fly and stream to Express responses.
import PDFDocument from "pdfkit";
import type { Response } from "express";
export function streamPdf(res: Response, title: string) {
const doc = new PDFDocument();
res.setHeader("Content-Type", "application/pdf");
res.setHeader("Content-Disposition", `attachment; filename="${title}.pdf"`);
doc.pipe(res);
doc.fontSize(20).text(title);
doc.end();
}
npx skills add TerminalSkills/pdfkit下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer