Generate PDFs from a template using JavaScript
Generating PDFs programmatically is a common requirement in modern web applications. Whether you’re building invoices, reports, or other documents, Nutrient enables you to create PDF documents entirely on the client-side in a browser by merging predefined PDF templates with data. This guide explores key methods, use cases, and best practices to empower your PDF generation workflows.
Methods for creating PDFs in JavaScript
Nutrient Web SDK provides versatile methods for creating PDFs with JavaScript, whether through client-side generation for quick downloads or server-side rendering for high-fidelity output.
Client-side PDF generation
Nutrient Web SDK enables the creation of PDFs directly within the browser, making it a great solution for scenarios where users need instant downloads without server dependencies.
Key features
-
Embed text, images, and shapes into PDFs dynamically.
-
Works seamlessly in modern web applications.
-
Simple to implement for lightweight use cases.
Server-side PDF generation
In the context of backend/server-side workflows, PDF generation typically refers to converting predesigned HTML templates into PDFs. This approach enables the creation of advanced layouts with precise styling, making it ideal for scenarios where high-fidelity output is required. Server-side generation also ensures better control over sensitive data, as the process is handled securely on the server.
Key features
-
Converts HTML and CSS templates into pixel-perfect PDFs.
-
Ideal for documents requiring accurate styling and complex layouts.
-
Enhances security by keeping data processing on the server.
Loading the PDF template
This guide uses our Vanilla JavaScript getting started project as a basis for generating PDFs. Make sure to follow the steps in that guide to set up your project.
First, you’ll need to load the PDF document you wish to populate with the data. Depending on your use case, the document can be loaded in a PDF viewer where a user interface is presented to the user, or headlessly, without a UI.
Load the document in the PDF viewer:
import "./assets/pspdfkit.js"; const baseUrl = `${window.location.protocol}//${window.location.host}/assets/`; (async () => { const instance = await PSPDFKit.load({ baseUrl, document: "/document.pdf", // Path to the PDF document. container: "#pspdfkit" }); })();
Load in headless mode so that no UI is presented to the user:
import "./assets/pspdfkit.js"; const baseUrl = `${window.location.protocol}//${window.location.host}/assets/`; (async () => { const instance = await PSPDFKit.load({ baseUrl, document: "/document.pdf", // Path to the PDF document. headless: true }); })();
Populating the document with data
To populate the document, you can overlay annotations onto the PDF template. In the following example, you’ll take a JSON data set and overlay TextAnnotations
at predefined coordinates:
// data.json { "company": "PSPDFKit", "companyInfo": "PSPDFKit", "companyName": "PSPDFKit" }
If you look at this guide’s example PDF template, you’ll see placeholders for COMPANY
, [Company Info]
, and Company Ltd.
. To detect the position of these placeholders, use the search API:
const searchQuery = "Company Ltd."; // The text to search for. const bbox = (await instance.search(searchQuery)) .first() .rectsOnPage.get(0);
This will show the current position of the text in the document.
Now, create the annotations with the text you want to overlay. For the text
property, bring in the data from the JSON file:
// index.js // Create a free text annotation. const textAnnotation = new PSPDFKit.Annotations.TextAnnotation({ boundingBox: bbox, // Set the bounding box of the text annotation. fontSize: 8, text: { format: "plain", value: data.companyName }, // The text to overlay. pageIndex: 0, // The page index to overlay the text on. fontColor: PSPDFKit.Color.RED, backgroundColor: PSPDFKit.Color.WHITE }); // Add the annotations to the document. await instance.create(textAnnotation);
The backgroundColor
property is set to white
. This will help create an opaque text annotation to hide the page text underneath.
You can also change the fontSize
property; just be aware that you need to adapt the boundingBox
size proportionally to the new font size.
The data from the JSON file will now appear in the PDF template as text annotations.
See our guide on programmatically creating annotations for more details.
It’s also possible to overlay other annotation types, such as signatures, images, and stamps.
Flattening annotations
Once the annotations have been overlaid on top of the PDF template, they can optionally be flattened to prevent modification:
await instance.exportPDF({ flatten: true });
See our flatten annotations guide for more details.
After flattening the annotations, the PDF template will look like what’s shown below.
You can find the example PDF template and the code on GitHub.
The example demo first loads the document in headless mode and then loads with the UI. This allows you to process the PDF before sending it over the network, or you can use it for light processing, like adding watermarks to the document.
Serving the example project
You can serve the PDF template to the user in a browser. For this, use the serve
HTTP package.
-
Install the serve package:
npm install --global serve
-
Serve the contents of the current directory:
serve -l 8080 .
-
Navigate to http://localhost:8080 to view the website.
Using annotations
Another way to do this is via annotations instead of using page text placeholders. (The example above tried to find the position of placeholders and updated it with dynamic data.) Use text annotations with predefined visuals (font, size, color, etc.) but with a replacement string. Here, you’ll retrieve all annotations on the page, iterate through all text annotations, and update them if they have the placeholder text.
For example, you could have the following text annotation as part of the template.
Then, you can perform the token replacement via the following:
const replacements = { "[[Company]]": "PSPDFKit" }; const annotationsToUpdate = // Retrieve annotations for a page. (await instance.getAnnotations(0)) // Filter to text annotations. .filter((it) => it instanceof PSPDFKit.Annotations.TextAnnotation) // Replace annotations with text that matches any replacement token. .map((annotation) => replacements[annotation.text.value] ? annotation.set("text", { format: annotation.text.format, value: replacements[annotation.text.value] }) : annotation ); // Annotations are immutable. `annotationsToUpdate` contains new instances of annotations. You need to use `instance.update` to actually update them. await instance.update(annotationsToUpdate);
This will replace the [Company]
annotation with PSPDFKit
.
Saving the PDF document
See our guide for saving a document.
You can also check out this blog post to learn more.
Best practices for PDF generation in JavaScript
When creating PDFs in JavaScript, follow these guidelines to ensure optimal results. Note that some practices, such as creating annotations or advanced features, apply specifically to backend HTML-to-PDF conversion and may not be achievable in client-side generation workflows.
-
Optimize performance
-
Use compression options to reduce file size.
-
Minimize the size of embedded assets like images or fonts.
-
Ensure accessibility
-
Include proper metadata for screen readers.
-
Add alternative text for any images embedded in the PDF.
-
Security considerations
-
Avoid embedding sensitive information in client-side PDFs.
-
Use server-side generation for documents with critical data.
-
Leverage modular code
-
Separate your logic for data processing and PDF generation.
-
Use reusable templates for consistent styling and formatting.
Conclusion
By leveraging Nutrient Web SDK’s robust capabilities for PDF creation, you can simplify workflows and enhance user experiences. Whether generating documents dynamically on the client-side or creating complex templates on the server, our SDK provides the flexibility and power needed to efficiently create high-quality PDFs.