# Template Customization Complete guide for creating and customizing invoice templates in nullInvoice. ## Template Overview - Templates live in `invoice_templates` and must include HTML content. - Invoice generation requires an effective default template (supplier-specific or global). - Suppliers can override the global default with a supplier-specific template. - Generated invoices store an HTML snapshot for consistent re-rendering. - PDFs are rendered from the stored HTML snapshot when available. ## Example Templates Example templates are available in 6 languages in the [`templates/`](../../templates/) directory: - English (EN) - Bulgarian (BG) - German (DE) - Spanish (ES) - Italian (IT) - Russian (RU) These templates can be used as starting points for your custom designs. ## Template Format Requirements Templates must use **XHTML** format for proper PDF rendering: - Include XML declaration: `` - Use XHTML namespace: `` - All CSS must be **inline** within a ` ``` ## Template Placeholders Templates use `{{placeholder}}` variables. If a placeholder is omitted from a template, that data will not be rendered in the final invoice. The service does not validate which placeholders are present or missing. ### Supported Placeholders **Invoice Details:** - `{{invoiceNumber}}` - Invoice number - `{{issueDate}}` - Issue date - `{{dueDateRow}}` - Full `
` row with due date or empty if not set **Supplier Information:** - `{{supplierName}}` - Supplier/company name - `{{supplierAddressLine1}}` - Address line 1 - `{{supplierAddressLine2Row}}` - Full `
` row with address line 2 or empty - `{{supplierCityRegionPostal}}` - City, region, and postal code - `{{supplierCountry}}` - Country - `{{supplierTaxIdRow}}` - Full `
` row with tax ID or empty - `{{supplierVatIdRow}}` - Full `
` row with VAT ID or empty - `{{supplierEmailRow}}` - Full `
` row with email or empty - `{{supplierPhoneRow}}` - Full `
` row with phone or empty **Client Information:** - `{{clientName}}` - Client/company name - `{{clientAddressLine1}}` - Address line 1 - `{{clientAddressLine2Row}}` - Full `
` row with address line 2 or empty - `{{clientCityRegionPostal}}` - City, region, and postal code - `{{clientCountry}}` - Country - `{{clientTaxIdRow}}` - Full `
` row with tax ID or empty - `{{clientVatIdRow}}` - Full `
` row with VAT ID or empty - `{{clientEmailRow}}` - Full `
` row with email or empty - `{{clientPhoneRow}}` - Full `
` row with phone or empty **Invoice Items and Totals:** - `{{itemsRows}}` - Rendered `` rows for invoice line items - `{{subtotal}}` - Subtotal before discounts and tax - `{{discountTotal}}` - Total discount amount - `{{taxTotal}}` - Total tax amount - `{{total}}` - Final total amount **Additional:** - `{{notesSection}}` - Full `
` section with notes or empty ### Row Placeholders Explained Placeholders ending with `Row` (e.g., `{{dueDateRow}}`, `{{supplierEmailRow}}`) return either: - A complete HTML row/div with the data if it exists - An empty string if the data is not present This allows conditional rendering without template logic: ```html {{supplierEmailRow}} ``` ## PDF Fonts PDFs are rendered using OpenHTMLToPDF. The application bundles the **DejaVu** font family which supports Latin, Cyrillic, Greek, and other Unicode characters. ### Using Bundled Fonts ```css body { font-family: "DejaVu Sans", sans-serif; } ``` ### Using Custom Web Fonts Templates can load external fonts via `@font-face` in the inline `