Authoring

Authoring workflow

How a template you write becomes a signed, printable A4 PDF served to a national.

The path of a document

  1. 1. A national clicks Download Electronic Copy on demoportal.
  2. 2. demoportal fetches the underlying register row from Veritas, mints a serial number, computes the SHA-256 hash + HMAC signature + 9-digit control number, writes a row to issued_documents, and generates a QR SVG for the verify URL.
  3. 3. demoportal POSTs { docType, tier, header, subject, parents, envelope } to kaharagia-docgen.
  4. 4. docgen loads your template file, fills the {{tag}} placeholders with values from the request body, and renders the HTML.
  5. 5. Puppeteer prints the HTML to a single A4 page; docgen returns the PDF bytes.
  6. 6. demoportal streams the PDF to the national's browser.

Where your template lives

Path
/opt/kaharagia/internal/docgen/src/templates/ ├── shared/ │ ├── arms.tsx # coat-of-arms SVG component │ └── envelope-panel.html # auto-injected verify panel ├── birth/ │ ├── certified.html # ← you author this │ └── electronic.html # ← you author this ├── marriage/ │ ├── certified.html │ └── electronic.html └── ... (one folder per doc type)

Per-tier vs shared

You don't need to author two completely separate files per doc type. The recommended layout uses a shared partial for the data sections and tier-specific files just for the chrome:

Handlebars
<!-- birth/certified.html --> {{> ceremonial-masthead}} {{!-- centered arms + state name --}} <h1>{{header.document_title}}</h1> {{> birth/data-sections}} {{!-- shared partial --}} {{> signature-and-seal-row}} <div data-envelope-strip></div> <!-- birth/electronic.html --> {{> red-id-bar}} {{> horizontal-masthead}} <h1>{{header.document_title}}</h1> {{> birth/data-sections}} {{!-- same shared partial --}} <div data-envelope-panel></div>

Iteration loop

  1. Edit the template file under internal/docgen/src/templates/.
  2. Rebuild + restart docgen: docker compose build docgen && docker compose up -d --force-recreate --no-deps docgen
  3. Re-render by hitting POST /api/render with the sample request body for that doc type. docgen returns the PDF in < 1s.

While iterating, use POST /api/preview-html with PUBLIC_PREVIEW=1 set on the container to get the HTML output without going through the PDF roundtrip — much faster for layout tweaks.

Things you should never put in your template