Overview
Read this article if you ...
- ...want to learn how to create custom PDF-Templates (using Hublify HTML-Template-Engine)
 - ...and use those PDF-Templates within Hublify's standard List-Actions and Document-Handling functionalities (E-Mail Attachments, ...) .
 - Examples of typical PDF-Templates, addressed here ...
- Invoice (PDF)
 - Delivery Note (PDF)
 - Offer / Quote (PDF)
 - ...
 
 
Keep in mind: It is commonly expected that a (PDF-) "Document Template" is targeted to be used for a specific dataset and a dynamic record of that!
Templating
This is a very important part to regard: This describes how you get all your data you want to render and on what data Hublify already injects into your template render-process.
- Hublify provides in some way the Primarykey-Value for the specific dataset-record for which to render the PDF. This can be in one of those twig-variables (automatically initialized and injected ....
- data[<primarykey-var>] = "<primarykey-value>"
(Occurs most often in Hublify Flows contexts, e.g. E-Mail-Attachments, ...)
or - filter[<primarykey-var>] = "<primarykey-value>"
(Occurs most often in List-Action contexts) 
 - data[<primarykey-var>] = "<primarykey-value>"
 - Since your template should be dataset-specific (e.g. for dataset "invoice") you then know (can look-up in Hublify Docs) the dataset's primarykey-var (e.g. "inv_id" for dataset "invoice").
So, it should be easy for you to detect the primarykey-value from the previously mentioned "data" or "filter" twig-Global-Vars. - Once you have "detected" the actual primarykey-value in your twig-template, you have everything you need to query more related data from Hublify which you want to render in your template.
For that use twig functions, such as: hublify.dataset()... and hublify.requireDatasetRecord()... . 
Example
For "invoice"-dataset Document (PDF), twig template:
{# --------  Example INVOICE Template (HTML for PDF)  -------- #}
{# ---- DEFINE which dataset-fields we want. #}
{% set fieldsWanted = [
    'inv_id','inv_code',
    'inv_gender','inv_title','inv_firstname','inv_lastname','inv_company', 
    'inv_street','inv_housenr','inv_addrextra','inv_zip','inv_town','inv_country',
    'inv_txt_header','inv_txt_title',
    'inv_amount','inv_currency','inv_amount_netto','inv_amount_brutto','inv_amount_vat','vat_sums',
    'inv_time_invoice',
    'orderid','o_time_ordered','o_pers_reftext','o_orderid_external',
    'personid'
] %}
{# ---- DETECT:  ...the primarykey-value and get/ensure all other record-fields we want! #}
{% if data['inv_id']>0 %}
    {# DATA: Obviously, we have definitely the primarykey-value and
        optionally some dataset-data provided. So, we can use performant
        hublify.requireDatasetRecord(...) to query all other fields wanted - but only
        if they are not already available!
    #}
    {% set data = hublify.requireDatasetRecord(
        'invoice',
        fieldsWanted,
        data['inv_id'],
        data)
    %}
{% elseif filter|length>0 %}
    {# FILTER: We have a filter-expression! Probably with the primarykey-var involved.
       But we can NOT RELY on that! So, we simply use the filter with
       hublify.dataset(...) as we were told and get that record!
    #}
    {% set data = hublify.dataset('invoice')
        .filters(filter)
        .fields(fieldsWanted)
        .one() %}
{% else %}
    {# Uh, ERROR!   Missing necessary possibility to retrieve data! Handle... #}
    {% set data = null %}
{% endif %}
{# --- RENDER here, your template! :-)  --- #}
<html>
  <body>
    <h1>Invoice Number: {{ data.inv_code }}</h1>
    ...
    (!) This simplified HTML source code is only to show the structure.
        Please write better code yourself! ;-)
  </body>
</html>