pdf-catalog-generator
v3.1.4
Published
Generate product catalog PDFs from Excel, CSV, or JSON data
Downloads
181
Maintainers
Readme
PDF Catalog Generator
Generate beautiful product catalog PDFs from Excel, CSV, or JSON data with multiple professional templates.
Features
- 🎨 4 Professional Templates - Choose from multiple layout options
- 📊 Multiple Input Formats - Excel, CSV, and JSON support
- 🏢 Customizable Branding - Add your company logo and name
- 📦 Dual Package - Supports both ESM and CommonJS
- 🔒 Type Safe - Full TypeScript support with type definitions
- ✅ Tested - Comprehensive unit test coverage
- 📚 Well Documented - Interactive Storybook documentation
Installation
npm install pdf-catalog-generatorQuick Start
import { generateProductCatalog } from 'pdf-catalog-generator';
import fs from 'fs';
const pdfBuffer = await generateProductCatalog({
products: [
{
Title: 'Laptop Pro 15',
Description: 'High-performance laptop',
Image: 'https://example.com/laptop.jpg',
Price: 1299.99,
Rating: 4.5,
Link: 'https://store.example.com/laptop'
}
],
companyName: 'Tech Store',
companyLogo: 'https://example.com/logo.png',
template: 'template1'
});
// Save to file
fs.writeFileSync('catalog.pdf', pdfBuffer);Platform Compatibility
This library works seamlessly across different JavaScript environments:
- ✅ Node.js - Backend servers, build scripts, CLI tools
- ✅ Browser/React - Client-side web applications
- ✅ Next.js - Both server components (SSR) and client components
Browser/React Usage
import { parseExcelFile, generateProductCatalog } from 'pdf-catalog-generator';
async function handleFileUpload(event: React.ChangeEvent<HTMLInputElement>) {
const file = event.target.files?.[0];
if (!file) return;
// Use browser File API
const arrayBuffer = await file.arrayBuffer();
// Parse with ArrayBuffer (cross-platform compatible)
const products = parseExcelFile(arrayBuffer);
// Generate PDF
const pdfBuffer = await generateProductCatalog({
products,
companyName: 'My Store',
template: 'template1',
});
// Download in browser
const blob = new Blob([pdfBuffer], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'catalog.pdf';
link.click();
URL.revokeObjectURL(url);
}Next.js Usage
Server Component (App Router):
// app/api/generate-catalog/route.ts
import { parseExcelFile, generateProductCatalog } from 'pdf-catalog-generator';
export async function POST(request: Request) {
const formData = await request.formData();
const file = formData.get('file') as File;
// Convert File to ArrayBuffer
const arrayBuffer = await file.arrayBuffer();
const products = parseExcelFile(arrayBuffer);
const pdfBuffer = await generateProductCatalog({
products,
companyName: 'My Store',
});
return new Response(pdfBuffer, {
headers: {
'Content-Type': 'application/pdf',
'Content-Disposition': 'attachment; filename="catalog.pdf"',
},
});
}Client Component:
'use client';
import { useState } from 'react';
import { parseExcelFile, generateProductCatalog } from 'pdf-catalog-generator';
export default function CatalogGenerator() {
const handleGenerate = async (file: File) => {
const arrayBuffer = await file.arrayBuffer();
const products = parseExcelFile(arrayBuffer);
const pdfBuffer = await generateProductCatalog({
products,
companyName: 'My Store',
});
// Download
const blob = new Blob([pdfBuffer], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'catalog.pdf';
link.click();
};
return (
<input
type="file"
accept=".xlsx,.csv"
onChange={(e) => e.target.files?.[0] && handleGenerate(e.target.files[0])}
/>
);
}Input Types
The parser functions accept multiple input types for cross-platform compatibility:
- Node.js Buffer -
fs.readFileSync()returns Buffer - ArrayBuffer - Browser
File.arrayBuffer()returns ArrayBuffer - Uint8Array - Universal typed array format
All input types are automatically detected and handled correctly.
API Reference
generateProductCatalog(config)
Generates a PDF catalog from the provided configuration.
Parameters:
config(CatalogConfig):products(ProductData[]): Array of product datacompanyName(string): Your company namecompanyLogo(string | null, optional): Logo URL or base64 stringtemplate(TemplateType, optional): Template to use (default: 'template1')imageOptimization(ImageOptimizationOptions, optional): Resize/compress supported remote image URLs before rendering. Enabled by default.
Returns: Promise<Uint8Array> - PDF file as Uint8Array (works in both Node.js and browser)
parseExcelFile(buffer)
Parse Excel file buffer into product data.
Parameters:
buffer(Buffer | ArrayBuffer | Uint8Array): Excel file data- Node.js: Use
Bufferfromfs.readFileSync() - Browser: Use
ArrayBufferfromfile.arrayBuffer() - Universal:
Uint8Arrayworks everywhere
- Node.js: Use
Returns: ProductData[] - Array of products
Example (Node.js):
import { parseExcelFile, generateProductCatalog } from 'pdf-catalog-generator';
import fs from 'fs';
const excelBuffer = fs.readFileSync('products.xlsx');
const products = parseExcelFile(excelBuffer);
const pdfBuffer = await generateProductCatalog({
products,
companyName: 'My Store'
});Example (Browser/React):
import { parseExcelFile, generateProductCatalog } from 'pdf-catalog-generator';
const file = event.target.files[0];
const arrayBuffer = await file.arrayBuffer();
const products = parseExcelFile(arrayBuffer);
const pdfBuffer = await generateProductCatalog({
products,
companyName: 'My Store'
});parseCSVFile(csvString)
Parse CSV string into product data.
Parameters:
csvString(string): CSV content as string
Returns: ProductData[] - Array of products
Example:
import { parseCSVFile, generateProductCatalog } from 'pdf-catalog-generator';
import fs from 'fs';
const csvString = fs.readFileSync('products.csv', 'utf-8');
const products = parseCSVFile(csvString);
const pdfBuffer = await generateProductCatalog({
products,
companyName: 'My Store'
});parseCSVBuffer(buffer)
Parse CSV buffer into product data.
Parameters:
buffer(Buffer | ArrayBuffer | Uint8Array): CSV file data- Node.js: Use
Bufferfromfs.readFileSync() - Browser: Use
ArrayBufferfromfile.arrayBuffer() - Universal:
Uint8Arrayworks everywhere
- Node.js: Use
Returns: ProductData[] - Array of products
parseJSON(data)
Parse JSON product data. No fields are mandatory - data is passed through as-is.
Parameters:
data(any[]): Array of product objects
Returns: ProductData[] - Products passed through without modification
Note: parseJSON no longer validates or normalizes data. It simply passes through your data as-is, just like the Excel/CSV parsers.
Example:
import { parseJSON, generateProductCatalog } from 'pdf-catalog-generator';
const rawData = [
{ Title: 'Product 1', Link: 'https://example.com/1' },
{ sku: 'ABC-123', name: 'Custom Product', color: 'Blue' },
{ designNumber: 'DN-001', fabric: 'Cotton', gsm: 180 }
];
const products = parseJSON(rawData); // All pass through without modification
const pdfBuffer = await generateProductCatalog({
products,
companyName: 'My Store'
});Data Format
ProductData
This library is completely schema-free - no fields are mandatory! You can use any data structure you want.
interface ProductData {
[key: string]: string | number | boolean | null | undefined;
}
interface ImageOptimizationOptions {
enabled?: boolean;
maxWidth?: number;
maxHeight?: number;
quality?: number;
logoMaxWidth?: number;
logoMaxHeight?: number;
logoQuality?: number;
}Dynamic Field Rendering:
- All templates automatically detect and display whatever fields you provide
- Common fields (Title, Description, Image, Price, Rating, Link) are displayed prominently if present
- All other fields are rendered dynamically with auto-formatted labels
- Missing fields are gracefully handled - nothing breaks!
Common Field Names (Optional): Templates intelligently look for these common fields (case-insensitive):
- Title/Name/ProductName - Displayed as main heading
- Image/ImageUrl/photo - Used as product image (fallback image if missing)
- Description/Details/Info - Shown as product description
- Price/Cost/Amount - Displayed prominently (formatted if provided)
- Rating/Stars/Score - Shown with star emoji if present
- Link/URL/ProductUrl - Powers "Buy Now" buttons
Custom Fields: Any other fields are automatically displayed with smart formatting:
designNumber→ "Design Number"gsm→ "GSM" (uppercase for known acronyms)fabric_finish→ "Fabric Finish"
Example - Traditional E-commerce:
{
Title: 'Laptop Pro 15',
Description: 'High-performance laptop',
Image: 'https://example.com/laptop.jpg',
Price: 1299.99,
Rating: 4.5,
Link: 'https://store.example.com/laptop'
}Example - Custom Textile Catalog:
{
designNumber: 'DN-12345',
fabric: '100% Cotton',
gsm: 180,
finish: 'Mercerized',
color: 'Navy Blue',
Image: 'https://example.com/fabric.jpg'
}Example - Minimal:
{
name: 'Widget',
sku: 'WDG-001'
}All of the above work perfectly! Templates adapt to your data structure.
Templates
All templates are fully dynamic and adapt to your data structure. They intelligently detect common fields and display all additional fields automatically.
Template 1: Grid Layout
2-column grid layout with product cards. Perfect for showcasing multiple products.
template: 'template1'Best for: Products with mixed field types - automatically displays all fields in a compact grid card.
Template 2: List Layout
Full-width horizontal layout with image on left, details on right. Great for detailed product information.
template: 'template2'Best for: Detailed products - shows all fields with room for descriptions and custom attributes.
Template 3: Full Page Layout
Full-page product view with image background and overlay details box. One product per page.
template: 'template3'Best for: Premium catalogs with hero images - displays key fields in an elegant overlay box (shows up to 5 custom fields).
Template 4: One-Per-Page
Full-page product view with header on each page and all product details listed. One product per page.
template: 'template4'Best for: Maximum detail - displays ALL product fields with formatted labels. Ideal for technical specifications or textile catalogs.
TypeScript Support
This package is written in TypeScript and includes type definitions:
import type { CatalogConfig, ProductData, TemplateType } from 'pdf-catalog-generator';
const config: CatalogConfig = {
products: [],
companyName: 'My Company',
template: 'template1'
};Examples
Check the examples/ directory for complete working examples:
- Basic usage
- Excel to PDF
- CSV to PDF
- Custom templates
Development
# Install dependencies
npm install
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Build package
npm run build
# Run Storybook
npm run storybook
# Lint code
npm run lint
# Format code
npm run formatContributing
Contributions are welcome! Please read CONTRIBUTING.md for details on our code of conduct and the process for submitting pull requests.
Changelog
See CHANGELOG.md for a list of changes.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
Credits
Built with:
- @react-pdf/renderer - PDF generation
- xlsx - Excel/CSV parsing
- TypeScript - Type safety
- Vitest - Testing
- Storybook - Documentation
