npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@priom7/json2pdf

v1.0.0

Published

A lightweight, browserless REST API that generates print-ready PDF question papers from structured JSON data using PDFKit — ideal for educational platforms that require professional formatting without the overhead of headless browsers like Puppeteer.

Readme

📄 Custom PDF Generator for Question Papers

A lightweight, browserless REST API that generates print-ready PDF question papers from structured JSON data using PDFKit — ideal for educational platforms that require professional formatting without the overhead of headless browsers like Puppeteer.


🚀 Features

  • 📘 Generates PDF directly from JSON using PDFKit
  • 🧾 Structured two-column question format
  • ✅ Supports multiple question types: MCQ, numerical, descriptive
  • 📑 Separate sections for questions, answer key, and solutions
  • ✏️ Clean and print-friendly layout
  • ⚡ Fast and efficient (no browser required)
  • 🖼️ Supports images, formulas (SVG), and custom logos/fonts

🛠️ Setup Instructions

📋 Prerequisites

  • Node.js (v14 or higher)
  • npm or yarn

📦 Installation

git clone https://github.com/Priom7/JSON-to-PDF-Generator.git
cd JSON-to-PDF-Generator

# Install dependencies
npm install

# Start the server
npm start

API will be available at:
http://localhost:3000/api/generate-pdf


📡 API Documentation

📍 Endpoint

POST /api/generate-pdf

Content-Type: application/json
Response: application/pdf

📥 Request Body Example

{
  "title": "Physics Examination Paper",
  "subject": "Physics",
  "date": "April 15, 2025",
  "duration": "3 hours",
  "totalMarks": 100,
  "instructions": [
    "All questions are compulsory",
    "There is no negative marking"
  ],
  "questions": [
    {
      "type": "mcq",
      "text": "A particle moves along the x-axis...",
      "options": ["300 J", "900 J", "1000 J", "3000 J"],
      "correctOption": 3,
      "solution": "Work done = ∫F(x)dx from x=0 to x=10..."
    }
  ]
}

✅ Success Response

  • Status: 200 OK
  • Content-Type: application/pdf
  • Body: Binary PDF file

❌ Error Responses

  • 400 Bad Request – Invalid JSON
  • 500 Internal Server Error – PDF generation failed

📐 JSON Schema

| Field | Type | Description | | ------------- | ------------------ | ------------------------------------------ | | title | String | Title of the examination paper | | subject | String | Subject name | | date | String | Exam date | | duration | String | Exam duration (e.g., "3 hours") | | totalMarks | Number | Total marks | | instructions| Array<String> | Exam instructions | | questions | Array<Object> | List of questions |

🎯 Question Object

| Field | Type | Description | | -------------- | ------------------ | --------------------------------------------------------- | | type | String | "mcq", "numerical", or "descriptive" | | text | String | Question text | | options | Array<String> | (For MCQ) Answer options | | correctOption| Number | (For MCQ) Index of correct option | | answer | String | Correct answer (numerical/descriptive) | | solution | String | Detailed solution explanation | | images | Array<Object> | (Optional) Images with path, width, height, position |


🎨 Customization

🧱 Layout Configuration (pdfGenerator.js)

const CONFIG = {
  pageSize: 'A4',
  margin: { top: 50, bottom: 50, left: 40, right: 40 },
  columns: 2,
  columnGap: 20,
  fonts: {
    regular: 'Helvetica',
    bold: 'Helvetica-Bold',
    italic: 'Helvetica-Oblique'
  },
  fontSize: {
    title: 16,
    header: 12,
    subHeader: 10,
    normal: 10,
    small: 8
  }
};

🔡 Custom Fonts

  1. Add your .ttf font files to a fonts/ directory.
  2. Register them in pdfGenerator.js:
doc.registerFont('CustomFont', 'fonts/CustomFont.ttf');

Update config:

fonts: {
  regular: 'CustomFont',
  bold: 'CustomFont-Bold',
  italic: 'CustomFont-Italic'
}

🖼️ Logo Support

Include in JSON:

"logoPath": "path/to/logo.png"

🔢 Math & Image Support

  • Simple Math: Unicode math characters
  • Complex Math: Include <svg> in question text or integrate mathjax-node
  • Images:
"images": [
  {
    "path": "path/to/image.png",
    "width": 300,
    "height": 200,
    "position": "center"
  }
]

📄 Page Numbering

Add to pdfGenerator.js:

doc.on('pageAdded', () => {
  const pageCount = doc.bufferedPageRange().count;
  doc.switchToPage(pageCount - 1);
  doc.fontSize(8)
     .text(`Page ${pageCount}`, doc.page.width / 2, doc.page.height - 20, { align: 'center' });
});

🐳 Docker Deployment

🧾 Dockerfile

FROM node:16-alpine

WORKDIR /usr/src/app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 3000

CMD ["node", "server.js"]

📦 Build & Run

docker build -t pdf-generator .
docker run -p 3000:3000 pdf-generator

☁️ Cloud Deployment

AWS Elastic Beanstalk

eb init
eb create pdf-generator-env
eb deploy

Heroku

heroku create
git push heroku main

🧪 Test Script

Create sample-data.json, then run:

node test.js

test.js example:

const fs = require('fs');
const path = require('path');
const { generatePDF } = require('./pdfGenerator');

async function testPDFGeneration() {
  const dataPath = path.join(__dirname, 'sample-data.json');
  if (!fs.existsSync(dataPath)) return console.error('sample-data.json not found');

  const data = JSON.parse(fs.readFileSync(dataPath, 'utf8'));
  const pdf = await generatePDF(data);
  fs.writeFileSync('output-test.pdf', pdf);
  console.log('PDF generated → output-test.pdf');
}

testPDFGeneration().catch(console.error);

🛡️ Security & Optimization

  • ✅ Input validation & sanitization
  • 🔐 Add authentication for production
  • ⏳ Use queues for batch requests
  • 🧠 Add caching for templates
  • 🚫 Rate limiting to prevent abuse

🐞 Troubleshooting

| Issue | Solution | | ------------------------------ | ------------------------------------------------------------- | | Large JSON payload | bodyParser.json({ limit: '50mb' }) | | Fonts not rendering | Ensure correct path and supported format (TTF/OTF) | | Images not displaying | Check file path and permissions | | Memory issues with large PDFs | Use streaming instead of buffering |

Enable debug logs:

DEBUG=true node server.js

🤝 Contributing

  1. Fork the repo
  2. Create a feature branch: git checkout -b feature/your-feature
  3. Commit: git commit -m "Add your feature"
  4. Push: git push origin feature/your-feature
  5. Open a Pull Request 🚀