13 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
PDFme is an open-source TypeScript-based PDF generation and manipulation library for web and Node.js applications. It provides a complete solution for creating, designing, and manipulating PDFs with a focus on performance, minimal dependencies, and ease of use.
Claude Code Integration
Triggering Claude Code
- Use
@claudein GitHub issues, PR comments, or reviews to trigger Claude Code assistance - Claude Code is configured via
.github/workflows/claude.ymlwith appropriate permissions - Best practices:
- Be specific about the problem or task
- Include relevant error messages or logs
- Mention specific files or components when applicable
GitHub Workflow Integration
- Claude Code automatically runs on issue comments, PR reviews, and new issues containing
@claude - Has read access to repository contents, pull requests, and issues
- Can assist with code analysis, debugging, and implementation suggestions
Environment Requirements
Node.js and Package Manager
- Node.js: Version 16 or higher (recommended: 18+ or 20+ for better performance)
- npm: Compatible with Node.js version (npm 8+ recommended)
- Memory: Minimum 4GB RAM, 8GB+ recommended for large PDF operations
Required Development Tools
- TypeScript: For type checking and compilation
- Vite+ (
vp): Unified task runner used for install/run/lint/fmt - Oxlint/Oxfmt: Native linting and formatting through
vp - Vitest: Testing framework with image snapshot support
OS-Specific Considerations
- Windows: Use Git Bash or WSL for shell commands
- macOS/Linux: Standard terminal works fine
- Memory limits: Increase Node.js heap size for large PDFs:
node --max-old-space-size=8192
Common Development Commands
Initial Setup and Build
npm install # Install all dependencies
npm run build # Build all packages in correct order
Development Workflow
To work on packages with live reloading:
- Run development mode in the packages you're working on:
cd packages/[package-name] && npm run dev - Run the playground to test changes:
cd playground && npm run dev # Opens at localhost:5173
Testing
npm run test # Run all tests
npm run test -w packages/ui -- -u # Update UI snapshot tests
# Run tests in specific package:
cd packages/[package-name] && npm run test
Code Quality
npm run lint # Run vp native lint
npm run fmt # Format code with vp native fmt
Building Individual Packages
npm run build -w packages/common # Build @pdfme/common
npm run build -w packages/schemas # Build @pdfme/schemas
npm run build -w packages/generator # Build @pdfme/generator
npm run build -w packages/ui # Build @pdfme/ui
Architecture and Code Structure
Monorepo Structure
- packages/common: Core types, utilities, and shared logic
- packages/pdf-lib: Forked pdf-lib with custom modifications
- packages/schemas: Built-in field types (text, image, table, barcode, etc.)
- packages/generator: PDF generation from templates
- packages/ui: React components (Designer, Form, Viewer)
- packages/manipulator: PDF operations (merge, split, rotate)
- packages/converter: Format conversion utilities
- playground: Interactive development and testing environment
- website: Documentation site (Docusaurus)
Key Architectural Patterns
1. Plugin-Based Field System
Each field type (text, image, table, etc.) is a plugin with three components:
pdf: Renders in the PDF using pdf-libui: Renders interactively in the browserpropPanel: Configuration UI for the Designer
Location: packages/schemas/src/[field-type]/index.ts
2. Template Structure
Templates consist of:
basePdf: Either blank PDF with dimensions or custom PDF fileschemas: 2D array where each sub-array represents a pagestaticSchemas: Optional fields that appear on every page
Type definitions: packages/common/src/types.ts
3. Dynamic Layout Engine
Handles:
- Dynamic height calculation for expandable fields
- Automatic page breaking
- Layout tree management
Key function: packages/generator/src/dynamicTemplate.ts:getDynamicTemplate
4. UI Component Hierarchy
All UI components extend BaseUIClass and support three modes:
viewer: Read-only displayform: Interactive inputdesigner: Template creation
Base class: packages/ui/src/class.ts
5. Expression System
Secure JavaScript expression evaluator for dynamic content:
- Uses Acorn for parsing
- AST validation for security
- Cached compilation
Implementation: packages/common/src/expression.ts
Important Implementation Details
-
Build Order: Due to dependencies, packages must be built in order: pdf-lib → common → converter → schemas → parallel(generator, ui, manipulator)
-
Font Management: Custom fonts are loaded and cached in the UI components and embedded with subsetting in PDFs
-
Validation: Uses Zod schemas for runtime validation throughout the codebase
-
Caching: Multiple caching layers for expressions, parsed data, and render-time optimization
-
Cross-Platform: Works in both Node.js and browser environments with different implementations
Development Tips
- Testing Changes: Always test in the playground after making changes
- Type Safety: Leverage TypeScript - check type definitions in
packages/common/src/types.ts - Plugin Development: Follow existing schema patterns in
packages/schemas/src/ - UI Changes: May take 5-10 seconds to reflect in playground due to build process
- Snapshot Tests: Update snapshots when UI changes are intentional
- Hot Reload Setup: Run
npm run devin multiple packages simultaneously for efficient development - Playground Testing: Use
cd playground && npm run devto test changes in real-time - Memory Management: Monitor memory usage when working with large PDFs or multiple templates
Contribution Guidelines
Pull Request Workflow
- Branch Naming: Use format
feature/descriptionorfix/description - Base Branch: Always create PRs against
mainbranch - Testing Requirements:
- Run
npm run testand ensure all tests pass - Run
npm run lintand fix any linting issues - Update snapshots if UI changes are intentional:
npm run test -w packages/ui -- -u
- Run
Code Standards
- TypeScript: All new code must be written in TypeScript
- Lint: Follow the shared
vp lint/.oxlintrc.jsonsetup - Format: Format code using
npm run fmt - Type Safety: Ensure proper type definitions and avoid
anytypes
Commit Message Standards
- Use conventional commit format:
type(scope): description - Types:
feat,fix,docs,style,refactor,test,chore - Examples:
feat(generator): add support for dynamic page breaksfix(ui): resolve Designer canvas rendering issuedocs(readme): update installation instructions
Code Review Process
- All PRs require review before merging
- Address reviewer feedback promptly
- Ensure CI checks pass before requesting review
- Keep PRs focused and reasonably sized
Performance Optimization
Memory Management for Large PDFs
- Heap Size: Increase Node.js heap size for large operations:
node --max-old-space-size=8192 your-script.js - Streaming: Use streaming approaches for very large PDFs when possible
- Cleanup: Properly dispose of PDF documents and clear caches
Rendering Optimization
- Lazy Loading: Implement lazy loading for large template lists
- Caching: Leverage built-in caching for expressions and parsed data
- Batch Operations: Process multiple PDFs in batches rather than individually
- Font Subsetting: Use font subsetting to reduce PDF file sizes
Bundle Size Optimization
- Tree Shaking: Ensure proper tree shaking in webpack configurations
- Dynamic Imports: Use dynamic imports for large dependencies
- Package Analysis: Regularly analyze bundle sizes with tools like webpack-bundle-analyzer
Browser vs Node.js Performance
- Browser: Limited by available memory and processing power
- Node.js: Can handle larger operations but watch for memory leaks
- Worker Threads: Consider worker threads for CPU-intensive operations in Node.js
Troubleshooting
Build Errors
TypeScript Compilation Issues
# Clear TypeScript cache
rm -rf packages/*/dist packages/*/.tsbuildinfo
npm run build
Webpack/Bundling Problems
# Clear node_modules and reinstall
rm -rf node_modules packages/*/node_modules
npm install
npm run build
Dependency Resolution Issues
# Check for version conflicts
npm ls
# Fix peer dependency warnings
npm install --legacy-peer-deps
Type Errors
Missing Type Definitions
- Check
packages/common/src/types.tsfor core type definitions - Ensure proper imports:
import type { Template } from '@pdfme/common' - Update type definitions when adding new features
Import Resolution Problems
# Rebuild packages in correct order
npm run build -w packages/common
npm run build -w packages/schemas
npm run build -w packages/generator
npm run build -w packages/ui
Environment Issues
Node Version Conflicts
# Check Node version
node --version
# Use nvm to switch versions
nvm use 18
Package Manager Issues
# Clear npm cache
npm cache clean --force
# Remove package-lock.json and reinstall
rm package-lock.json
npm install
Memory Issues
Large PDF Processing
# Increase heap size
export NODE_OPTIONS="--max-old-space-size=8192"
npm run dev
Memory Leaks in Development
- Restart development servers regularly
- Monitor memory usage in browser dev tools
- Clear caches periodically
Font Issues
Font Loading Failures
- Ensure fonts are properly embedded in PDFs
- Check font file paths and accessibility
- Verify font format compatibility (TTF, OTF)
CJK Font Problems
- Use the forked
@pdfme/pdf-libwhich includes CJK support - Ensure proper font subsetting for large character sets
- Test with actual CJK content
Dependency Conflicts
Package Version Mismatches
# Check for outdated packages
npm outdated
# Update specific packages
npm update @pdfme/common @pdfme/generator
Peer Dependency Issues
# Install with legacy peer deps
npm install --legacy-peer-deps
# Or fix peer dependencies manually
npm install <missing-peer-dependency>
Common Error Patterns
Font-Related Errors
- Error:
Font not foundorInvalid font - Solution: Verify font file exists and is accessible, check font embedding settings
- Prevention: Test with standard fonts first, then add custom fonts
Memory Allocation Errors
- Error:
JavaScript heap out of memory - Solution: Increase heap size with
--max-old-space-size=8192 - Prevention: Process large PDFs in smaller chunks, implement proper cleanup
Import/Export Resolution Issues
- Error:
Module not foundorCannot resolve module - Solution: Check build order, ensure packages are built before importing
- Prevention: Follow proper build sequence, use TypeScript path mapping
Plugin Development Pitfalls
- Error: Plugin not rendering correctly
- Solution: Ensure plugin exports
{ ui, pdf, propPanel }correctly - Prevention: Follow existing plugin patterns in
packages/schemas/src/
Playground Connection Issues
- Error: Changes not reflecting in playground
- Solution: Restart development servers, check if packages are in dev mode
- Prevention: Ensure proper hot reload setup across packages
Enhanced Development Workflow
Hot Reload Setup
-
Start package development servers:
# Terminal 1 cd packages/common && npm run dev # Terminal 2 cd packages/schemas && npm run dev # Terminal 3 cd packages/generator && npm run dev # Terminal 4 cd packages/ui && npm run dev -
Start playground:
# Terminal 5 cd playground && npm run dev
E2E Testing Procedures
# Run full test suite
npm run test
# Run playground E2E tests
cd playground && npm run test
# Update UI snapshots after intentional changes
npm run test -w packages/ui -- -u
Debugging with Playground
- Use playground for rapid prototyping and testing
- Add console.log statements for debugging
- Test with various template configurations
- Verify changes across different browsers
CI/CD Integration
- All PRs automatically run tests via GitHub Actions
- Ensure local tests pass before pushing
- Monitor CI status and address failures promptly
- Use Claude Code integration for assistance with CI issues
Key Files to Understand
packages/common/src/types.ts: Core type definitionspackages/generator/src/generate.ts: Main PDF generation logicpackages/ui/src/components/Designer/index.tsx: Designer implementationpackages/schemas/src/text/index.ts: Example of a complete pluginplayground/public/template-assets/: Template examples and definitions