| name | ingest-document-sample |
| description | Take an existing document sample (PDF/image/Word) — typically an invoice, receipt, statement, or business letter — and convert it into a Typst template plus a JSON schema describing its variable fields. Use when the user says they have an example document they want to "templatise", "convert to Typst", "extract a schema from", or use as the basis for programmatic generation. |
ingest-document-sample
Convert a sample billing/business document into a reusable parameterised template.
When to use
Auto-trigger when the user provides or references a sample document (PDF, image, DOCX) and wants to:
- Turn it into a Typst template.
- Define a schema for the variable fields it contains.
- Use it as a starting point for an automated rendering pipeline.
Inputs
- Sample file path — PDF, PNG/JPG, or DOCX.
- Document type hint — invoice / receipt / statement / contract / letter / report / other.
- What's variable vs fixed — ideally the user marks this up; otherwise infer (next section).
Approach
1. Read the sample
- For PDF: read directly (Claude Code can read PDFs natively).
- For images: read directly — visual inspection.
- For DOCX: convert to text or markdown first (
pandoc <file.docx> -o <out.md> or unzip + parse), then read.
2. Identify structure
Walk the document and label each region:
- Fixed branding — logo position, business name/address block, footer boilerplate. → Pulled from
brand.json, not from the per-document data.
- Header fields — invoice number, issue date, due date, customer ref. → Top-level scalar fields.
- Party blocks — biller, recipient. → Nested objects (
from: {...}, to: {...}).
- Line items / repeating rows — table body. → Array of objects (
items: [{description, qty, unit_price, total}, ...]).
- Totals block — subtotal, tax, discount, total. → Either computed in the template or supplied.
- Notes / terms / footer — free-text or boilerplate.
3. Emit the schema
Write schema.json (JSON Schema draft-07) describing every variable field, with types, descriptions, and which are required.
4. Emit the Typst template
Write template.typ that:
- Loads brand from the brand profile if available.
- Loads data from
data.json.
- Reproduces the sample's layout as closely as Typst allows (page size, margins, column structure, heading hierarchy).
- Uses
#for loops for repeating rows.
5. Emit an example payload
Write data.example.json matching the schema, populated from the values actually in the sample (so the user can immediately render and visually compare to the original).
6. Round-trip verify
Run typst compile template.typ sample-rendered.pdf against the example data. Show the user both the original and the rendered version side-by-side (or at least describe the diff if visual comparison isn't available).
Output layout
<output-dir>/
├── template.typ
├── schema.json
├── data.example.json
├── sample-rendered.pdf # produced by the round-trip step
└── README.md # what each schema field maps to
<output-dir> is user-chosen — suggest ~/Documents/doc-templates/<doc-type>/ or a path under their existing repo.
Storage rules
Templates and schemas live where the user wants them — never under the plugin install dir. The plugin may cache the most recent ingestion under $CLAUDE_USER_DATA_ROOT/cache/last-ingest/ for reference, but this is regenerable.