AI-powered professional PDF generation from Markdown. Generate whitepapers, term sheets, SAFEs, and more with AI or from your own content.
npm install ai-pdf-builder🤖 AI-Powered Professional PDF Generation — Create beautiful business documents with AI or from Markdown. Generate whitepapers, memos, agreements, and term sheets instantly. Perfect for AI agents, chatbots, and automation workflows.
> New in v0.4: AI document generation! Just describe what you need and let Claude create professional PDFs automatically.
---
Built for: Clawdbot • Moltbot • LangChain • AutoGPT • Custom AI Agents
---
- 🤖 AI Agents & Chatbots — Generate documents on-the-fly from conversational AI
- ⚖️ Legal Tech — Automate NDA, contract, and agreement generation
- 💰 Fintech — Create term sheets, SAFEs, and investment documents programmatically
- 🔄 Automation Workflows — Integrate with n8n, Zapier, Make, or custom pipelines
- 📱 Messaging Bots — Let users request documents via Telegram, WhatsApp, Discord, Slack, or Signal
- 🏢 Enterprise — Bulk document generation with consistent branding
---
- Works With
- Perfect For
- Features
- 🤖 AI Generation (NEW!)
- Prerequisites
- Installation
- Quick Start
- Usage Examples
- Basic PDF Generation
- Generate a Business Memo
- Generate a Legal Agreement
- Generate a Term Sheet
- Generate a Whitepaper
- Custom Colors
- Save to File
- Custom Templates
- List Available Templates
- Check System Requirements
- Integration with Next.js
- API Reference
- Built-in Templates
- Troubleshooting
- Error Handling
- TypeScript Best Practices
- Advanced Topics
- Production Deployment
- FAQ
- Integrations
- License
- Contributing
- 🤖 AI Document Generation: Describe what you need → get a professional PDF (powered by Claude)
- Company-Aware AI: Use --company to auto-include your company details in generated docs
- Multiple Document Types: Built-in templates for memos, agreements, term sheets, and whitepapers
- Custom Styling: Apply custom colors and branding to any template
- TypeScript Support: Full type definitions included
- Flexible Output: Get PDF as Buffer or save directly to file
- Template System: Use built-in templates or register your own
- Security: Built-in content sanitization for LaTeX safety
Generate professional documents by describing what you need. No Markdown required!
``bashGenerate a business memo
npx ai-pdf-builder ai "Write a memo about Q1 2026 hiring plans" -o hiring-memo.pdf
$3
Create a
company.json file in your project root with your company details:`json
{
"name": "Acme Corp",
"legalName": "Acme Corporation Inc.",
"address": "123 Main St, San Francisco, CA 94102",
"website": "https://acme.com",
"industry": "Enterprise Software",
"description": "We build productivity tools for modern teams."
}
`Then use
--company to automatically inject these details:`bash
AI knows your company context
npx ai-pdf-builder ai "Write an investor update for Q4" --company -o q4-update.pdf
npx ai-pdf-builder ai "Create a partnership proposal" --company -o proposal.pdf
`$3
| Flag | Description |
|------|-------------|
|
--company, -c | Load company context from company.json |
| --template, -t | Use specific template (memo, agreement, termsheet, whitepaper) |
| --output, -o | Output file path |
| --model | Claude model to use (default: claude-sonnet-4-20250514) |
| --verbose, -v | Show AI generation progress |$3
`typescript
import { generateWithAI } from 'ai-pdf-builder';// Simple AI generation
const result = await generateWithAI({
prompt: "Write a professional memo about remote work policy changes",
template: "memo",
metadata: {
title: "Remote Work Policy Update",
author: "HR Department"
}
});
// With company context
const result = await generateWithAI({
prompt: "Create an advisor agreement",
template: "agreement",
companyContext: {
name: "Acme Corp",
legalName: "Acme Corporation Inc."
}
});
if (result.success) {
fs.writeFileSync('output.pdf', result.buffer);
}
`$3
- Anthropic API Key: Set
ANTHROPIC_API_KEY environment variable
- Pandoc and LaTeX (same as regular PDF generation)Prerequisites
This package requires Pandoc and LaTeX to be installed on your system:
$3
`bash
Install Pandoc
brew install pandocInstall BasicTeX (minimal LaTeX)
brew install --cask basictexAfter installing BasicTeX, install required packages
sudo tlmgr update --self
sudo tlmgr install collection-fontsrecommended fancyhdr titlesec enumitem xcolor booktabs longtable geometry hyperref setspace array multirow listings
`$3
`bash
Install Pandoc and TeX Live
sudo apt-get update
sudo apt-get install -y pandoc texlive-latex-base texlive-latex-extra texlive-fonts-recommended
`$3
1. Download and install Pandoc
2. Download and install MiKTeX
$3
For containerized environments, use a Pandoc/LaTeX image:
`dockerfile
FROM pandoc/latex:latest
`Installation
`bash
npm install ai-pdf-builder
`Or with yarn:
`bash
yarn add ai-pdf-builder
`$3
Set your Anthropic API key:
`bash
export ANTHROPIC_API_KEY="your-api-key"
`Or add to
.env:`
ANTHROPIC_API_KEY=your-api-key
`Quick Start
$3
`bash
One command to generate a professional PDF
npx ai-pdf-builder ai "Write a business proposal for a SaaS product" -o proposal.pdf
`$3
`typescript
import { generatePDF } from 'ai-pdf-builder';
import * as fs from 'fs';const result = await generatePDF({
content: '# My Document\n\nThis is the content of my PDF.',
metadata: {
title: 'My First PDF',
author: 'John Doe',
date: 'January 2026'
}
});
if (result.success && result.buffer) {
fs.writeFileSync('output.pdf', result.buffer);
console.log(
PDF generated! Size: ${result.fileSize} bytes);
}
`Usage Examples
$3
`bash
CLI - Instant memo generation
npx ai-pdf-builder ai "Write an executive memo about launching our new mobile app in Q2. Include timeline, resource needs, and risk factors." --template memo -o app-launch-memo.pdfWith company context for branded output
npx ai-pdf-builder ai "Create a board update covering our Series A progress, key metrics, and next quarter goals" --company --template memo -o board-update.pdf
`$3
`bash
NDA with your company details
npx ai-pdf-builder ai "Generate an NDA for sharing proprietary technology with a potential partner" --company -o tech-nda.pdfAdvisor agreement
npx ai-pdf-builder ai "Create an advisor agreement offering 0.5% equity over 2 years with monthly vesting" --company --template agreement -o advisor-agreement.pdf
`$3
`typescript
import { generatePDF } from 'ai-pdf-builder';const result = await generatePDF({
content:
This document outlines our strategic initiatives for Q1 2026.
- Increase market share by 15%
- Launch new product line
- Expand to 3 new markets
Implementation begins February 1st, 2026.
,`
metadata: {
title: 'Q1 Strategic Plan',
subtitle: 'Confidential',
author: 'Strategy Team',
date: 'January 2026',
version: 'v1.0'
},
toc: true,
numberSections: true
});
`typescript
import { generateMemo } from 'ai-pdf-builder';
const memo = await generateMemo(
Key findings from our market analysis indicate strong growth potential.
1. Accelerate product development
2. Increase marketing budget by 20%
3. Hire 5 additional engineers
,`
{
title: 'Product Whitepaper',
subtitle: 'Intelligence Infrastructure for Financial Markets',
author: 'John Smith',
date: 'January 2026'
}
);
`typescript
import { generateAgreement } from 'ai-pdf-builder';
const agreement = await generateAgreement(
This Advisor Agreement is entered into as of the Effective Date.
The Advisor agrees to provide strategic guidance and introductions to potential investors.
In consideration of the Services, the Company shall pay the Advisor:
- 8% of cash raised through Advisor's introductions
- 0.25% equity per $250,000 raised, up to 1% maximum
This Agreement shall remain in effect for 12 months from the Effective Date.
,`
{
title: 'Capital Introduction Agreement',
subtitle: 'Acme Corp',
date: 'January 15, 2026'
}
);
`typescript
import { generateTermsheet } from 'ai-pdf-builder';
const termsheet = await generateTermsheet(
$2,000,000 (Two Million Dollars)
$8,000,000
Series Seed Preferred Stock
Lead Investor: TBD
,`
{
title: 'Series Seed',
company: 'Acme Corp',
doctype: 'Term Sheet',
date: 'January 2026'
}
);
`typescript
import { generateWhitepaper } from 'ai-pdf-builder';
const whitepaper = await generateWhitepaper(
This paper presents a novel approach to financial market intelligence.
Financial markets generate vast amounts of data...
Our system consists of three main components...
We have demonstrated a scalable solution for...
,`
{
title: 'Product Whitepaper',
subtitle: 'A Canonical Asset Resolution System',
author: 'Research Team',
version: 'v1.0',
date: 'January 2026'
}
);
`typescript
import { generatePDF } from 'ai-pdf-builder';
const result = await generatePDF({
content: '# Branded Document\n\nWith custom colors!',
metadata: { title: 'Custom Branded PDF' },
customColors: {
primary: '#3B82F6', // Blue
secondary: '#6B7280', // Gray
accent: '#111827' // Dark
}
});
`
`typescript
import { generatePDF } from 'ai-pdf-builder';
const result = await generatePDF({
content: '# My Document',
metadata: { title: 'Saved PDF' },
outputPath: './output/my-document.pdf'
});
if (result.success) {
console.log(PDF saved to: ${result.path});`
}
`typescript
import { generatePDF, registerTemplate } from 'ai-pdf-builder';
// Register a custom template
registerTemplate({
name: 'company-branded',
path: './templates/company.latex',
description: 'Company branded template with logo',
supportedDocTypes: ['memo', 'whitepaper', 'report']
});
// Use the custom template
const result = await generatePDF({
content: '# Company Report',
metadata: { title: 'Annual Report' },
template: 'company-branded'
});
`
`typescript
import { listTemplates } from 'ai-pdf-builder';
const templates = listTemplates();
templates.forEach(t => {
console.log(${t.name}: ${t.description}); Supports: ${t.supportedDocTypes.join(', ')}
console.log();`
});
`typescript
import { checkSystem } from 'ai-pdf-builder';
const status = checkSystem();
if (status.ready) {
console.log('System ready:', status.message);
} else {
console.error('Missing dependencies:', status.message);
if (!status.pandoc.available) {
console.error('Pandoc:', status.pandoc.error);
}
if (!status.latex.available) {
console.error('LaTeX:', status.latex.error);
}
}
`
`typescript
// app/api/generate-pdf/route.ts
import { generatePDF } from 'ai-pdf-builder';
import { NextResponse } from 'next/server';
export async function POST(request: Request) {
const { content, title, type } = await request.json();
const result = await generatePDF({
content,
metadata: { title },
template: type === 'memo' ? 'memo' : 'default'
});
if (!result.success) {
return NextResponse.json({ error: result.error }, { status: 500 });
}
return new NextResponse(result.buffer, {
headers: {
'Content-Type': 'application/pdf',
'Content-Disposition': attachment; filename="${title}.pdf"`
}
});
}
`typescript
// app/actions/pdf.ts
'use server';
import { generateMemo } from 'ai-pdf-builder';
export async function createMemo(content: string, title: string) {
const result = await generateMemo(content, { title });
if (!result.success) {
throw new Error(result.error);
}
return result.buffer?.toString('base64');
}
`
#### ai - AI Document Generation
`bash`
npx ai-pdf-builder ai
| Option | Alias | Description | Default |
|--------|-------|-------------|---------|
| --output | -o | Output file path | output.pdf |--template
| | -t | Template: memo, agreement, termsheet, whitepaper | Auto-detected |--company
| | -c | Load company context from company.json | false |--model
| | | Claude model | claude-sonnet-4-20250514 |--verbose
| | -v | Show progress | false |
#### generate - Markdown to PDF
`bash`
npx ai-pdf-builder generate
| Option | Alias | Description | Default |
|--------|-------|-------------|---------|
| --output | -o | Output file path | .pdf |--template
| | -t | Template name | default |--title
| | | Document title | Filename |--author
| | | Document author | |--toc
| | | Include table of contents | true |
#### check - System Check
`bash`
npx ai-pdf-builder check
Verifies Pandoc and LaTeX are properly installed.
Main function to generate a PDF from Markdown content.
#### PDFOptions
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| content | string | Yes | Markdown content to convert |metadata
| | DocumentMetadata | No | Document metadata (title, author, etc.) |template
| | string | No | Template name or path (default: 'default') |customColors
| | ColorConfig | No | Custom color configuration |outputPath
| | string | No | Save PDF to this path instead of returning buffer |toc
| | boolean | No | Include table of contents (default: true) |tocDepth
| | number | No | Depth of TOC (1-3, default: 2) |numberSections
| | boolean | No | Number sections (default: true) |fontSize
| | number | No | Font size in points (default: 11) |margin
| | string | No | Page margins (default: '1in') |paperSize
| | 'letter' \| 'a4' | No | Paper size (default: 'letter') |timeout
| | number | No | Timeout in ms (default: 60000) |
#### PDFResult
| Property | Type | Description |
|----------|------|-------------|
| success | boolean | Whether generation succeeded |buffer
| | Buffer | Generated PDF (if outputPath not specified) |path
| | string | Path to saved PDF (if outputPath specified) |error
| | string | Error message if failed |pageCount
| | number | Estimated page count |fileSize
| | number | File size in bytes |generationTime
| | number | Generation time in ms |
Generate a PDF using AI to create the content.
#### AIGenerationOptions
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| prompt | string | Yes | Description of what document to generate |template
| | string | No | Template to use (auto-detected if not specified) |metadata
| | DocumentMetadata | No | Override document metadata |companyContext
| | CompanyContext | No | Company details for context |model
| | string | No | Claude model (default: claude-sonnet-4-20250514) |
#### Example
`typescript
import { generateWithAI } from 'ai-pdf-builder';
const result = await generateWithAI({
prompt: "Write an executive summary about our AI product launch",
template: "memo",
companyContext: {
name: "TechCorp",
industry: "AI/ML Software"
}
});
`
All preset functions have the signature:
`typescript`
function preset(
content: string,
metadata: DocumentMetadata,
options?: Partial
): Promise
Available presets:
- generateMemo - Business memosgenerateAgreement
- - Legal agreementsgenerateTermsheet
- - Investment term sheetsgenerateWhitepaper
- - Technical whitepapersgenerateReport
- - Business reportsgenerateProposal
- - ProposalsgenerateCapitalIntroAgreement
- - Fundraising agreementsgenerateSAFE
- - SAFE documentsgenerateNDA
- - Non-disclosure agreements
- getTemplate(name: string): string | null - Get template contentlistTemplates(): TemplateConfig[]
- - List all templatesregisterTemplate(config: TemplateConfig): void
- - Register custom templatehasTemplate(name: string): boolean
- - Check if template exists
- checkSystem(): SystemCheck - Check Pandoc/LaTeX availabilitycheckPandoc(): PandocCheck
- - Check Pandoc installationcheckLaTeX(): LaTeXCheck
- - Check LaTeX installationsanitizeContent(content: string): string
- - Sanitize for LaTeX safety
| Template | Description | Best For |
|----------|-------------|----------|
| default | Clean, professional styling | Whitepapers, reports |memo
| | Compact business memo | Executive summaries |agreement
| | Formal legal document | Contracts, agreements |termsheet
| | Premium dark + gold finance | Term sheets, investment docs |
Install Pandoc:
- macOS: brew install pandocsudo apt-get install pandoc
- Ubuntu:
- Windows: Download from pandoc.org
Install LaTeX:
- macOS: brew install --cask basictexsudo apt-get install texlive-latex-base texlive-latex-extra
- Ubuntu:
- Windows: Install MiKTeX
`bash`
sudo tlmgr install
Common packages needed:
`bash`
sudo tlmgr install fancyhdr titlesec enumitem xcolor booktabs longtable geometry hyperref
Increase the timeout for large documents:
`typescript`
const result = await generatePDF({
content: longContent,
timeout: 120000 // 2 minutes
});
Proper error handling is crucial for production applications.
`typescript
import { generatePDF } from 'ai-pdf-builder';
try {
const result = await generatePDF({
content: markdownContent,
metadata: { title: 'My Document' }
});
if (!result.success) {
console.error('PDF generation failed:', result.error);
// Handle specific errors
if (result.error?.includes('Pandoc')) {
console.error('Pandoc is not installed. Please install it first.');
// Guide user to installation instructions
} else if (result.error?.includes('pdflatex')) {
console.error('LaTeX is not installed. Please install TeX Live or MiKTeX.');
} else if (result.error?.includes('timeout')) {
console.error('Generation timed out. Try increasing the timeout option.');
}
return;
}
// Success - use result.buffer or result.path
console.log(PDF generated successfully: ${result.fileSize} bytes);`
} catch (error) {
console.error('Unexpected error:', error);
// Handle system-level errors
}
`typescriptAttempt ${attempt}/${maxRetries} failed:
async function generateWithRetry(
options: PDFOptions,
maxRetries: number = 3
): Promise
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const result = await generatePDF(options);
if (result.success) {
return result;
}
console.warn(, result.error);PDF generation failed after ${maxRetries} attempts
// Wait before retry (exponential backoff)
if (attempt < maxRetries) {
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
throw new Error();`
}
`typescriptattachment; filename="${title}.pdf"
app.post('/api/pdf', async (req, res) => {
try {
const { content, title } = req.body;
const result = await generatePDF({
content,
metadata: { title },
timeout: 30000
});
if (!result.success) {
return res.status(500).json({
error: 'PDF generation failed',
details: result.error
});
}
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', );`
res.send(result.buffer);
} catch (error) {
console.error('PDF generation error:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
Get the most out of TypeScript's type system for safer code.
`typescript
import {
generatePDF,
PDFOptions,
PDFResult,
DocumentMetadata,
ColorConfig,
TemplateConfig
} from 'ai-pdf-builder';
// Type-safe metadata
const metadata: DocumentMetadata = {
title: 'Annual Report',
author: 'Jane Doe',
date: new Date().toLocaleDateString('en-US'),
version: 'v2.0',
subtitle: 'Financial Year 2025'
};
// Type-safe color configuration
const colors: ColorConfig = {
primary: '59,130,246', // RGB format
secondary: '107,114,128',
accent: '17,24,39'
};
// Complete options with type checking
const options: PDFOptions = {
content: markdownContent,
metadata,
customColors: colors,
template: 'default',
toc: true,
tocDepth: 2,
numberSections: true,
fontSize: 11,
margin: '1in',
paperSize: 'letter',
timeout: 60000
};
const result: PDFResult = await generatePDF(options);
// Type-safe result handling
if (result.success && result.buffer) {
const size: number = result.fileSize || 0;
const pages: number = result.pageCount || 0;
console.log(Generated ${pages} pages (${size} bytes));`
}
`typescript
import { PDFResult } from 'ai-pdf-builder';
function isSuccessfulResult(result: PDFResult): result is PDFResult & {
success: true;
buffer: Buffer
} {
return result.success && !!result.buffer;
}
// Use the type guard
const result = await generatePDF(options);
if (isSuccessfulResult(result)) {
// TypeScript knows result.buffer is defined here
saveToFile(result.buffer);
}
`
`typescript
import { DocumentMetadata } from 'ai-pdf-builder';
// Extend with custom metadata
interface CustomMetadata extends DocumentMetadata {
department?: string;
classification?: 'public' | 'internal' | 'confidential';
reviewers?: string[];
}
const metadata: CustomMetadata = {
title: 'Security Report',
author: 'Security Team',
date: '2026-01-22',
department: 'IT Security',
classification: 'confidential',
reviewers: ['Alice', 'Bob']
};
`
Generate multiple PDFs concurrently:
`typescript
import { generatePDF } from 'ai-pdf-builder';
import pLimit from 'p-limit';
async function generateBatch(documents: Array<{ content: string; title: string }>) {
// Limit concurrent operations to avoid overwhelming the system
const limit = pLimit(3);
const tasks = documents.map(doc =>
limit(() => generatePDF({
content: doc.content,
metadata: { title: doc.title }
}))
);
const results = await Promise.all(tasks);
// Process results
const successful = results.filter(r => r.success);
const failed = results.filter(r => !r.success);
console.log(Generated ${successful.length}/${results.length} PDFs);`
return { successful, failed };
}
Tips for large documents:
`typescript
// 1. Increase timeout for large documents
const result = await generatePDF({
content: largeMarkdownContent,
timeout: 180000 // 3 minutes
});
// 2. Disable TOC for faster generation
const result = await generatePDF({
content,
toc: false, // Skip table of contents
numberSections: false
});
// 3. Use simpler templates
const result = await generatePDF({
content,
template: 'default' // Simpler than termsheet template
});
// 4. Process in chunks for very large documents
async function generateLargeDocument(sections: string[]) {
const pdfs = await Promise.all(
sections.map(section => generatePDF({
content: section,
toc: false
}))
);
// Merge PDFs using a library like pdf-lib
}
`
For high-volume operations:
`typescript
import { generatePDF } from 'ai-pdf-builder';
// Monitor memory usage
function logMemoryUsage() {
const used = process.memoryUsage();
console.log({
rss: ${Math.round(used.rss / 1024 / 1024)}MB,${Math.round(used.heapUsed / 1024 / 1024)}MB
heapUsed:
});
}
// Process in batches to avoid memory issues
async function processLargeQueue(queue: any[], batchSize = 10) {
for (let i = 0; i < queue.length; i += batchSize) {
const batch = queue.slice(i, i + batchSize);
await Promise.all(batch.map(item => generatePDF(item)));
// Allow garbage collection between batches
await new Promise(resolve => setImmediate(resolve));
logMemoryUsage();
}
}
`
Create your own LaTeX templates:
`typescript
import { registerTemplate, generatePDF } from 'ai-pdf-builder';
import * as path from 'path';
// Register a custom template
registerTemplate({
name: 'company-branded',
path: path.join(__dirname, 'templates', 'company.latex'),
description: 'Company branded template with logo',
supportedDocTypes: ['memo', 'whitepaper', 'report']
});
// Use the custom template
const result = await generatePDF({
content: markdownContent,
template: 'company-branded',
customColors: {
primary: '0,102,204', // Company blue
secondary: '128,128,128'
}
});
`
See TEMPLATE_GUIDE.md for a complete guide to creating custom LaTeX templates.
Dockerfile:
`dockerfile
FROM pandoc/latex:latest
EXPOSE 3000
CMD ["node", "server.js"]
`
docker-compose.yml:
`yaml
version: '3.8'
services:
pdf-generator:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- MAX_CONCURRENT_PDFS=3
volumes:
- pdf-cache:/app/cache
mem_limit: 2g
mem_reservation: 1g
volumes:
pdf-cache:
`
`typescript
// next.config.js
module.exports = {
experimental: {
serverComponentsExternalPackages: ['ai-pdf-builder']
},
// Increase API route timeout for PDF generation
api: {
responseLimit: '8mb'
}
};
// app/api/pdf/route.ts
import { generatePDF } from 'ai-pdf-builder';
import { NextResponse } from 'next/server';
export const maxDuration = 60; // 60 seconds timeout
export async function POST(request: Request) {
const { content, title } = await request.json();
const result = await generatePDF({
content,
metadata: { title },
timeout: 50000 // Leave buffer before Next.js timeout
});
if (!result.success) {
return NextResponse.json({ error: result.error }, { status: 500 });
}
return new NextResponse(result.buffer, {
headers: {
'Content-Type': 'application/pdf',
'Content-Disposition': attachment; filename="${title}.pdf",`
'Cache-Control': 'no-store'
}
});
}
AWS Lambda:
`typescript
// Lambda function with custom runtime
// NOTE: Lambda has a 512MB /tmp limit and 15min timeout
import { generatePDF } from 'ai-pdf-builder';
export const handler = async (event) => {
// Use /tmp for working directory
const result = await generatePDF({
content: event.content,
metadata: event.metadata,
workDir: '/tmp/pdf-work',
timeout: 840000 // 14 minutes (leave buffer)
});
if (result.success) {
// Upload to S3 instead of returning (size limits)
await uploadToS3(result.buffer, event.key);
return { statusCode: 200, body: JSON.stringify({ url: s3Url }) };
}
return { statusCode: 500, body: JSON.stringify({ error: result.error }) };
};
`
Note: For serverless, consider using the container approach or a dedicated PDF generation service due to Pandoc/LaTeX size requirements.
Sentry Integration:
`typescript
import * as Sentry from '@sentry/node';
import { generatePDF } from 'ai-pdf-builder';
Sentry.init({ dsn: process.env.SENTRY_DSN });
async function generateWithMonitoring(options) {
const transaction = Sentry.startTransaction({
op: 'pdf.generate',
name: 'Generate PDF'
});
try {
const result = await generatePDF(options);
if (!result.success) {
Sentry.captureMessage('PDF generation failed', {
level: 'error',
extra: { error: result.error, options }
});
}
transaction.setStatus('ok');
return result;
} catch (error) {
Sentry.captureException(error);
transaction.setStatus('internal_error');
throw error;
} finally {
transaction.finish();
}
}
`
The ai command sends your prompt to Claude (Anthropic's AI), which generates professional Markdown content based on your description. This content is then converted to PDF using Pandoc and LaTeX.
What makes it smart:
- Automatically detects document type from your prompt
- Structures content appropriately (headers, sections, formatting)
- Uses professional language and business conventions
- With --company, includes your company details naturally
| Aspect | AI Generation | Manual (Markdown) |
|--------|--------------|-------------------|
| Input | Natural language prompt | Structured Markdown |
| Control | AI decides structure | You control everything |
| Speed | Fastest for drafts | Better for precise docs |
| Best for | First drafts, ideas, quick docs | Final versions, exact specs |
Pro tip: Use AI to generate a first draft, then export the Markdown for manual refinement.
PDF generation involves multiple steps (Markdown parsing, LaTeX compilation, font rendering). Typical generation times:
- Simple document (1-5 pages): 1-3 seconds
- Medium document (10-20 pages): 3-8 seconds
- Large document (50+ pages): 10-30 seconds
To improve performance:
- Disable TOC if not needed (toc: false)template: 'default'
- Use simpler templates ()
- Process documents concurrently for batch operations
- Cache generated PDFs when possible
Yes, but with caveats:
- Docker-based serverless (AWS Fargate, Cloud Run): ✅ Recommended
- Traditional Lambda/Functions: ⚠️ Challenging due to Pandoc/LaTeX dependencies (~300MB)
For traditional serverless, consider:
1. Using a custom Lambda layer with Pandoc/LaTeX
2. Calling a dedicated PDF generation service
3. Using AWS Lambda Container Images
`typescript
// Enable detailed error logging
const result = await generatePDF({
content: markdownContent,
metadata: { title: 'Debug Test' }
});
if (!result.success) {
console.error('Full error:', result.error);
// LaTeX errors typically mention line numbers and commands
// Example: "LaTeX Error: Environment Shaded undefined"
}
`
Common LaTeX errors:
- "pdflatex not found": Install LaTeX (see Prerequisites)
- "Unicode character not set up": Use ASCII alternatives or configure unicode support
- "Environment undefined": Missing LaTeX package
Supported (via Pandoc):
- ✅ Headers (H1-H6)
- ✅ Lists (ordered, unordered, nested)
- ✅ Bold, italic, code
- ✅ Links and URLs
- ✅ Tables (simple and grid)
- ✅ Code blocks with syntax highlighting
- ✅ Blockquotes
- ✅ Horizontal rules
- ✅ Images (if file paths are accessible)
Limited support:
- ⚠️ HTML (basic tags only)
- ⚠️ Complex tables (may need LaTeX syntax)
- ⚠️ Emojis (depends on LaTeX font support)
Not supported:
- ❌ GitHub-flavored Markdown task lists
- ❌ Mermaid diagrams (consider rendering to image first)
`typescript
const content =
Regular text here.
!Chart{ width=80% };
const result = await generatePDF({
content,
metadata: { title: 'Document with Images' }
});
`
Requirements:
- Image paths must be accessible from where the code runs
- Supported formats: PNG, JPG, PDF
- Use relative or absolute paths
- Control size with Pandoc syntax: { width=50% } or { height=3in }
Yes, convert HTML to Markdown first or use Pandoc's HTML input:
`typescript
import { generatePDF } from 'ai-pdf-builder';
import TurndownService from 'turndown';
// Convert HTML to Markdown
const turndown = new TurndownService();
const markdown = turndown.turndown(htmlContent);
const result = await generatePDF({
content: markdown,
metadata: { title: 'From HTML' }
});
`
Use a queue system to limit concurrent PDF generations:
`typescript
import Queue from 'bull';
import { generatePDF } from 'ai-pdf-builder';
const pdfQueue = new Queue('pdf-generation', process.env.REDIS_URL);
// Limit to 3 concurrent jobs
pdfQueue.process(3, async (job) => {
return await generatePDF(job.data.options);
});
// Add jobs
app.post('/api/pdf', async (req, res) => {
const job = await pdfQueue.add({ options: req.body });
res.json({ jobId: job.id });
});
`
ai-pdf-builder is designed to work seamlessly with AI agents and automation platforms:
| Framework | Integration |
|-----------|-------------|
| Clawdbot / Moltbot | Native support — generate PDFs from chat commands |
| LangChain | Use as a tool in your agent chains |
| AutoGPT | Add as a plugin for document generation |
| CrewAI | Integrate as an agent capability |
| Semantic Kernel | Use via function calling |
Works with any bot framework that can execute Node.js:
- Telegram — node-telegram-bot-api, telegrafwhatsapp-web.js
- WhatsApp — , @whiskeysockets/baileysdiscord.js
- Discord — @slack/bolt
- Slack — signal-cli
- Signal —
- n8n — Use the Execute Command or Code node
- Zapier — Via Code by Zapier or webhooks
- Make (Integromat) — HTTP module + hosted endpoint
- Pipedream — Native Node.js support
`typescript
import { Tool } from "langchain/tools";
import { generateWithAI } from "ai-pdf-builder";
const pdfTool = new Tool({
name: "generate_pdf",
description: "Generate a professional PDF document from a description",
func: async (prompt: string) => {
const result = await generateWithAI({ prompt });
if (result.success) {
// Save or return the PDF
return PDF generated: ${result.fileSize} bytes;Error: ${result.error}
}
return ;`
}
});
`typescript
import TelegramBot from 'node-telegram-bot-api';
import { generateWithAI } from 'ai-pdf-builder';
const bot = new TelegramBot(process.env.BOT_TOKEN, { polling: true });
bot.onText(/\/pdf (.+)/, async (msg, match) => {
const chatId = msg.chat.id;
const prompt = match[1];
await bot.sendMessage(chatId, '📄 Generating your PDF...');
const result = await generateWithAI({ prompt });
if (result.success) {
await bot.sendDocument(chatId, result.buffer, {
filename: 'document.pdf'
});
}
});
``
Built by @NextXFrontier — Follow for AI tools, automation, and building in public.
MIT
Contributions welcome! Please read our CONTRIBUTING.md guidelines before submitting PRs.