typst

star 0

Use this skill working with Typst template, pdf generation, imprintor library.

sunprema By sunprema schedule Updated 6/7/2026

name: typst description: "Use this skill working with Typst template, pdf generation, imprintor library."

Typst PDF Patterns (Imprintor)

  • You have to be very careful when working with Elixir/JSON data in typst template. There are issues with the types like nil, true/false, string to number conversions.
  • Boolean fields from Elixir/JSON arrive in Typst as strings "true"/"false", not booleans
  • Always coerce at the top of any function that accepts a boolean named param:
    let approximate = if type(approximate) == str { approximate == "true" } else { approximate }
    
  • Named params with boolean defaults (e.g. approximate: false) will still error if the caller passes a string — coercion must be inside the function body
  • Numeric coercion: See feedback_typst_numeric_coercion.md — floats arrive as strings, nil as "nil" string. Always define to-num helper AT THE TOP of every template (before all functions). Never call calc.round/arithmetic on raw Elixir values without to-num. Always nil-guard before division.
  • **nil-string bug **: Never check if v == nonebefore passing toto-num— Elixirnilarrives as the string"nil", not Typst none. The == noneguard misses it, thencalc.round(to-num("nil"))crashes with "expected integer, float, or decimal, found none". **Rule**: always callto-num(v)first, bind the result, then check the result fornone. Pattern: let n = to-num(v); if n == none { "—" } else { calc.round(n, ...) }`

Imprintor data injection — use elixir_data, not sys.inputs

Imprintor injects the Elixir data map as a global Typst variable named elixir_data, defined directly in the Typst library scope via the Rust NIF: library.global.scope_mut().define("elixir_data", typst_value);

In your .typ template, access data as: #elixir_data.project #elixir_data.date #for item in elixir_data.labor [ ... ]

Not sys.inputs.elixir_data.X (sys.inputs is always empty — Imprintor never writes to it) and not sys.inputs.X (the keys are not flattened there either).

Type mapping — Elixir values convert to native Typst types:

  • String → str
  • Integer → int
  • Float → float
  • List → array (so .len() and for work directly)
  • Map → dict (so .at("key", default: "—") works)
  • nil atom → none

typst template location

  • Typst templates live under the consuming app's priv/typst/ folder — apps/postopguard/priv/typst/ for PostOpGuard, apps/steward/priv/typst/ for Steward (slice 46). Phoenix resolves these via Application.app_dir(:<otp_app>, "priv/typst/…"), so the path follows the OTP app. Sub-folders allowed.
Install via CLI
npx skills add https://github.com/sunprema/StudySync --skill typst
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator