Foliant

Templates / Letter

Letter

DIN 5008 style business letter: sender line, address window, reference block, subject and body paragraphs from JSON. The template that makes generated correspondence look like it came from a person.

1 page, A4. Rendered in 25 ms. 13 inputs, all optional.

Download .typ Open preview

Rendered Letter template, first page
First page, rendered from the source below with the sample inputs.

Inputs

Everything variable comes in through sys.inputs. Missing keys fall back to sensible defaults, so an agent can send only what it knows.

KeySample value
closingKind regards,
date28 September 2026
enclosuresQuote Q-2026-118
logologo.png
paragraphs
JSON, 430 chars
[
  "Thank you for the good conversation on Tuesday. Attached you will find our quote for the redesign of your customer portal, valid until 26 October.",
  "We suggest starting with the two-day discovery workshop in the week of 13 October so the design phase can begin in November. If that timing works for your team, a short confirmation is all we need.",
  "I am happy to walk you through the positions in a call whenever it suits you."
]
recipient
JSON, 71 chars
[
  "Northwind Traders",
  "Lena Hartmann",
  "Kastanienallee 7",
  "10435 Berlin"
]
referenceQ-2026-118
salutationDear Ms Hartmann,
senderMeridian Studio GmbH
sender_lineMeridian Studio GmbH · Rosenthaler Str. 41 · 10178 Berlin
signerMara Ehrlich
signer_roleManaging Director
subjectYour quote for the customer portal redesign

Render it

After copying the template into your account:

curl -X POST https://api.foliant.dev/v1/render \
  -H "Authorization: Bearer $FOLIANT_API_KEY" \
  -H "Content-Type: application/json" \
  -o letter.pdf -d @- <<'JSON'
{ "template": "letter.typ",
  "inputs": {
    "closing": "Kind regards,",
    "date": "28 September 2026",
    "enclosures": "Quote Q-2026-118",
    "logo": "logo.png",
    "paragraphs": "[\"Thank you for the good conversation on Tuesday. Attached you will find our quote for the redesign of your customer portal, valid until 26 October.\",\"We suggest starting with the two-day discovery workshop in the week of 13 October so the design phase can begin in November. If that timing works for your team, a short confirmation is all we need.\",\"I am happy to walk you through the positions in a call whenever it suits you.\"]",
    "recipient": "[\"Northwind Traders\",\"Lena Hartmann\",\"Kastanienallee 7\",\"10435 Berlin\"]",
    "reference": "Q-2026-118",
    "salutation": "Dear Ms Hartmann,",
    "sender": "Meridian Studio GmbH",
    "sender_line": "Meridian Studio GmbH · Rosenthaler Str. 41 · 10178 Berlin",
    "signer": "Mara Ehrlich",
    "signer_role": "Managing Director",
    "subject": "Your quote for the customer portal redesign"
  } }
JSON

Through MCP, render_document with template: "letter.typ" and the same inputs; get_template or fetch lists the keys.

Source

template.typ, 26 lines
#let input(k, default: "") = sys.inputs.at(k, default: default)
#let recipient = json(bytes(input("recipient", default: "[]")))
#let paragraphs = json(bytes(input("paragraphs", default: "[]")))
#let logo = input("logo")
#set page(paper: "a4", margin: (top: 20mm, bottom: 20mm, left: 25mm, right: 20mm))
#set text(font: "Libertinus Serif", size: 11pt, fill: rgb("1a1917"))
#set par(justify: false, leading: 0.7em)
#align(right)[#if logo != "" { image(logo, width: 36mm) } else { text(size: 14pt, weight: 600)[#input("sender")] }]
#v(12mm)
#text(size: 7.5pt, fill: luma(110))[#input("sender_line")]
#v(2mm)
#block(height: 30mm)[#for l in recipient [#l \ ]]
#v(4mm)
#grid(columns: (1fr, auto), [#text(size: 9pt, fill: luma(110))[Reference: #input("reference")]], [#input("date")])
#v(10mm)
#text(weight: 600)[#input("subject")]
#v(5mm)
#input("salutation")
#v(3mm)
#for p in paragraphs [#p #v(3mm)]
#v(2mm)
#input("closing")
#v(14mm)
#input("signer") \ #text(size: 9.5pt, fill: luma(110))[#input("signer_role")]
#if input("enclosures") != "" [#v(8mm) #text(size: 9pt, fill: luma(110))[Enclosure: #input("enclosures")]]