PDFStudio v0.2.0 is now isomorphic - it works in both Node.js AND browsers!
Created a new platform abstraction layer to support multiple environments:
src/
├── platform/
│ ├── interfaces/ # Abstract interfaces
│ │ ├── IFileSystem.ts
│ │ └── IImageProcessor.ts
│ ├── node/ # Node.js implementations
│ │ ├── NodeFileSystem.ts
│ │ └── NodeImageProcessor.ts
│ ├── browser/ # Browser implementations
│ │ ├── BrowserFileSystem.ts
│ │ └── BrowserImageProcessor.ts
│ └── PlatformFactory.ts # Auto-detects environment
- Node.js: Still uses
sharpfor optimal performance - Browser: Uses Canvas API for image processing
- Interface:
IImageProcessorprovides unified API
- Node.js: Uses native
fsmodule - Browser: Uses FileReader API, fetch API, and Blob API
- Interface:
IFileSystemprovides unified API
Several methods are now async to support browser file loading:
// Before (Node.js only)
doc.registerFont({ name: 'MyFont', source: './font.ttf' });
doc.save('output.pdf');
// After (Node.js + Browser)
await doc.registerFont({ name: 'MyFont', source: './font.ttf' });
await doc.save('output.pdf');The following methods are now async:
PDFDocument.registerFont()→async registerFont()PDFDocument.save()→async save()PDFDocument.toBuffer()→async toBuffer()PDFDocument.end()→async end()PDFWriter.registerCustomFont()→async registerCustomFont()PDFWriter.generate()→async generate()PDFWriter.embedImage()→async embedImage()ImageParser.load()→async load()
Before (v0.1.x):
const doc = new PDFDocument();
doc.registerFont({ name: 'MyFont', source: './font.ttf' });
doc.text('Hello', 100, 100);
doc.save('output.pdf');After (v0.2.x):
const doc = new PDFDocument();
await doc.registerFont({ name: 'MyFont', source: './font.ttf' });
doc.text('Hello', 100, 100);
await doc.save('output.pdf');buffer- Buffer polyfill for browsersesbuild- Build tool for browser bundle
sharp- Moved tooptionalDependencies(not required in browsers)
New build scripts:
{
"scripts": {
"build": "npm run build:node && npm run build:browser",
"build:node": "tsc",
"build:browser": "node scripts/build-browser.js"
}
}Output files:
dist/index.js- Node.js version (CommonJS)dist/pdfstudio.standalone.js- Browser version (IIFE, minified)dist/pdfstudio.standalone.debug.js- Browser version (IIFE, debug)
- ✅ Generate PDFs directly in the browser
- ✅ No server required
- ✅ Same API as Node.js
- ✅ Modern browsers (Chrome, Firefox, Safari, Edge)
- ✅ Load images from URLs
- ✅ Load images from File objects (
<input type="file">) - ✅ Load images from data URLs
- ✅ Load fonts from URLs or File objects
- ✅ Download PDFs or get as Blob
// Download PDF
await doc.save('output.pdf'); // Triggers download
// Get as Blob (for upload, viewing, etc.)
const buffer = await doc.toBuffer();
const blob = new Blob([buffer], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
// View in browser
window.open(url, '_blank');
// Upload to server
const formData = new FormData();
formData.append('pdf', blob, 'document.pdf');
await fetch('/api/upload', { method: 'POST', body: formData });New documentation:
BROWSER.md- Complete browser guideexamples/browser/- Browser examplesexamples/browser/README.md- Browser examples documentation- Updated main README with browser section
For existing users upgrading from v0.1.x to v0.2.x:
- Update all
doc.save()calls toawait doc.save() - Update all
doc.registerFont()calls toawait doc.registerFont() - Update all
doc.toBuffer()calls toawait doc.toBuffer() - Update all
doc.end()calls toawait doc.end() - Update all
ImageParser.load()calls toawait ImageParser.load() - Wrap affected code in
asyncfunctions - Test your application
Before:
function generateInvoice() {
const doc = new PDFDocument();
doc.registerFont({ name: 'Arial', source: './arial.ttf' });
doc.text('Invoice', 100, 100);
doc.save('invoice.pdf');
}After:
async function generateInvoice() {
const doc = new PDFDocument();
await doc.registerFont({ name: 'Arial', source: './arial.ttf' });
doc.text('Invoice', 100, 100);
await doc.save('invoice.pdf');
}- Universal: Write once, run anywhere (Node.js + Browser)
- No Breaking API: Same API for both environments
- Better Performance: Optimized implementations for each platform
- Modern: Uses latest browser APIs (Canvas, Blob, Web Crypto)
- Future-Proof: Foundation for other platforms (React Native, Electron)
- Memory: Large PDFs (>50MB) may hit browser memory limits
- Performance: Image processing slightly slower than Node.js (Canvas vs sharp)
- Sync Crypto: Some crypto operations are async in browsers
- 📖 Browser Documentation
- 📖 Main Documentation
- 💬 GitHub Issues
- 📧 Email: hello@ideas2code.dev