HTML Template to PDF

HTML template rendering combines a reusable HTML layout with structured data to create personalized PDFs. Place variables in the HTML and supply their values through PDFCrowd's HTML to PDF API.

This guide walks through a complete event-pass example that you can adapt to certificates, cards, letters, and marketing materials. You can provide template data as JSON, XML, CSV, or YAML.

Quick Start

PDFCrowd templates use Jinja syntax for variables, loops, conditions, and filters. This example uses each of these features to create a personalized event pass.

HTML Template

The HTML template defines the layout and contains placeholders for the event and attendee details. You can reuse it with different data for each pass. Save it as event-pass.html.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>{{ event.name }}</title>
    <style>
      body { font-family: Arial, sans-serif; margin: 24px; color: #222; }
      h1 { color: #146c94; }
      .vip { font-weight: bold; }
    </style>
  </head>
  <body>
    <main class="event-pass">
      <p>{{ event.type|upper }}</p>
      <h1>{{ event.name }}</h1>

      <h2>{{ attendee.name }}</h2>
      {% if attendee.vip %}<p class="vip">VIP access</p>{% endif %}

      <p><strong>Date:</strong> {{ event.date }}</p>
      <p><strong>Venue:</strong> {{ event.venue }}</p>

      <ul>
        {% for session in event.sessions %}
          <li>{{ session.time }} &mdash; {{ session.title }}</li>
        {% endfor %}
      </ul>

      <p>Pass {{ attendee.pass_id }} &middot; {{ attendee.ticket_type }}</p>
    </main>
  </body>
</html>

Template Data

The template data provides the values inserted into the HTML. This example uses JSON to describe one attendee and event. Save it as attendee-data.json.

{
  "attendee": {
    "name": "Jordan Lee",
    "pass_id": "NS-2048",
    "ticket_type": "All Access",
    "vip": true
  },
  "event": {
    "type": "Design conference",
    "name": "Northstar Design Summit",
    "date": "October 18",
    "venue": "Harbor Hall, Seattle",
    "sessions": [
      { "time": "09:00", "title": "Opening keynote" },
      { "time": "11:30", "title": "Design systems workshop" },
      { "time": "15:00", "title": "Product critique" }
    ]
  }
}

Generate the PDF

Keep both files in the same directory, choose your preferred language, and run its example. The result is saved as event-pass.pdf.

curl -f -s -S \
  -u 'demo:demo' \
  -o event-pass.pdf \
  -F file=@event-pass.html \
  -F data_file=@attendee-data.json \
  -F content_viewport_width=576px \
  -F data_format=json \
  -F no_margins=true \
  -F page_height=4in \
  -F page_width=6in \
  https://api.pdfcrowd.com/convert/24.04/
import pdfcrowd

client = pdfcrowd.HtmlToPdfClient('demo', 'demo')

client.setContentViewportWidth('576px')
client.setDataFormat('json')
client.setNoMargins(True)
client.setPageHeight('4in')
client.setPageWidth('6in')
client.setDataFile('attendee-data.json')
client.convertFileToFile('event-pass.html', 'event-pass.pdf')
<?php
require 'vendor/autoload.php';

$client = new \Pdfcrowd\HtmlToPdfClient('demo', 'demo');

$client->setContentViewportWidth('576px');
$client->setDataFormat('json');
$client->setNoMargins(true);
$client->setPageHeight('4in');
$client->setPageWidth('6in');
$client->setDataFile('attendee-data.json');
$client->convertFileToFile('event-pass.html', 'event-pass.pdf');
const pdfcrowd = require('pdfcrowd');

const client = new pdfcrowd.HtmlToPdfClient("demo", "demo");

client.setContentViewportWidth("576px");
client.setDataFormat("json");
client.setNoMargins(true);
client.setPageHeight("4in");
client.setPageWidth("6in");
client.setDataFile("attendee-data.json");
client.convertFileToFile(
    "event-pass.html", "event-pass.pdf",
    (error, filePath) => {
        if (error) {
            console.error(error.toString());
            return;
        }
        console.log("Saved:", filePath);
    }
);
import com.pdfcrowd.Pdfcrowd;

class Example {
    public static void main(String[] args) throws Exception {
        Pdfcrowd.HtmlToPdfClient client =
            new Pdfcrowd.HtmlToPdfClient("demo", "demo");

        client.setContentViewportWidth("576px");
        client.setDataFormat("json");
        client.setNoMargins(true);
        client.setPageHeight("4in");
        client.setPageWidth("6in");
        client.setDataFile("attendee-data.json");
        client.convertFileToFile("event-pass.html", "event-pass.pdf");
    }
}
using System;

class Example
{
    static void Main()
    {
        var client = new pdfcrowd.HtmlToPdfClient("demo", "demo");

        client.setContentViewportWidth("576px");
        client.setDataFormat("json");
        client.setNoMargins(true);
        client.setPageHeight("4in");
        client.setPageWidth("6in");
        client.setDataFile("attendee-data.json");
        client.convertFileToFile("event-pass.html", "event-pass.pdf");
    }
}
require 'pdfcrowd'

client = Pdfcrowd::HtmlToPdfClient.new('demo', 'demo')

client.setContentViewportWidth('576px')
client.setDataFormat('json')
client.setNoMargins(true)
client.setPageHeight('4in')
client.setPageWidth('6in')
client.setDataFile('attendee-data.json')
client.convertFileToFile('event-pass.html', 'event-pass.pdf')
package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("576px")
    client.SetDataFormat("json")
    client.SetNoMargins(true)
    client.SetPageHeight("4in")
    client.SetPageWidth("6in")
    client.SetDataFile("attendee-data.json")
    err := client.ConvertFileToFile("event-pass.html", "event-pass.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}
html2pdf --content-viewport-width=576px \
    --data-format=json \
    --no-margins \
    --page-height=4in \
    --page-width=6in \
    --data-file=attendee-data.json \
    --output event-pass.pdf \
    event-pass.html

Result

The template and data produce this personalized event pass. Download the generated PDF to view the full-size result.

Template Syntax

Template syntax controls how data is inserted, repeated, formatted, or shown conditionally. PDFCrowd templates use Jinja for these operations; the sections below summarize common constructs and supported filters.

Constructs

  • Insert a value: {{ attendee.name }}
  • Loop over items: {% for session in event.sessions %} ... {% endfor %}
  • Show content conditionally: {% if attendee.vip %} ... {% endif %}
  • Apply a filter: {{ event.type|upper }}
  • Format a number:
    • Thousands separator: {{ "{:,}".format(number) }}
    • Two decimal places: {{ "{:.2f}".format(number) }}

Supported Filters

Template filters transform values before they are inserted into the output, for example to change capitalization, provide a default value, sort a list, or format text. The following filters are supported:

  • capitalize
  • center
  • default
  • escape
  • first
  • forceescape
  • format
  • indent
  • join
  • last
  • length
  • list
  • lower
  • replace
  • reverse
  • safe
  • slice
  • sort
  • string
  • striptags
  • title
  • trim
  • truncate
  • unique
  • upper
  • wordcount
  • wordwrap