Foliant

Templates / Certificate

Certificate

Landscape A4 with a fine border, recipient in display size, two signature lines. For courses, awards and completed reviews.

1 page, A4 landscape. Rendered in 14 ms. 7 inputs, all optional.

Download .typ Open preview

Rendered Certificate 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
courseTypst for Agents: rendering documents with Foliant
date28 September 2026
issuerMeridian Academy
logologo.png
recipientAda Lovelace
serialCERT-2026-0193
signerMartin Karrer, Instructor

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 certificate.pdf -d @- <<'JSON'
{ "template": "certificate.typ",
  "inputs": {
    "course": "Typst for Agents: rendering documents with Foliant",
    "date": "28 September 2026",
    "issuer": "Meridian Academy",
    "logo": "logo.png",
    "recipient": "Ada Lovelace",
    "serial": "CERT-2026-0193",
    "signer": "Martin Karrer, Instructor"
  } }
JSON

Through MCP, render_document with template: "certificate.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 logo = input("logo")
#set page(paper: "a4", flipped: true, margin: 18mm,
  background: place(center + horizon, rect(width: 100% - 24mm, height: 100% - 24mm, stroke: 1.2pt + rgb("b8341c"), inset: 0pt)[#place(center + horizon, rect(width: 100% - 4mm, height: 100% - 4mm, stroke: 0.4pt + rgb("b8341c")))]))
#set text(font: "Libertinus Serif", fill: rgb("1a1917"))
#align(center)[
  #v(6mm)
  #if logo != "" { image(logo, width: 40mm) } else { text(size: 14pt, weight: 600)[#input("issuer")] }
  #v(8mm)
  #text(size: 12pt, tracking: 4pt, fill: luma(110))[CERTIFICATE OF COMPLETION]
  #v(6mm)
  #text(size: 12pt, fill: luma(90))[This certifies that]
  #v(3mm)
  #text(size: 36pt, weight: 600)[#input("recipient")]
  #v(4mm)
  #text(size: 12pt, fill: luma(90))[has successfully completed]
  #v(2mm)
  #text(size: 18pt, style: "italic")[#input("course")]
  #v(12mm)
  #grid(columns: (1fr, 1fr), gutter: 40mm,
    [#line(length: 100%, stroke: 0.5pt) #v(2pt) #text(size: 9.5pt)[#input("signer")]],
    [#line(length: 100%, stroke: 0.5pt) #v(2pt) #text(size: 9.5pt)[#input("date")]])
  #v(1fr)
  #text(size: 8pt, fill: luma(150))[#input("issuer") · #input("serial")]
]