Create a professional, shareable PDF document — invoices, receipts, certificates, reports, resumes, letters. Returns a link that opens the document in the PDFMakerAPI editor to preview, edit any field, and download the PDF.
Design a THOROUGH, realistic document (don't leave it sparse) that exactly follows this model, then pass it as `document`.
DOCUMENT MODEL (PDFMakerAPI):
Document:
- id: string (short slug)
- name: string
- description: string (one short sentence)
- pageSize: "letter" | "a4" | "legal" | "letter-landscape" | "a4-landscape" | "square" | "auto" (default "a4"; "auto" = letter width with the height growing to fit the content — use it for certificates/awards so there's no empty space below)
- pageBackgroundColor: hex string (default "#ffffff")
- margin: "none"|"sm"|"md"|"lg" // page margin (inset from the page edge); default "lg"
- gap: "none"|"sm"|"md"|"lg" // vertical spacing between top-level sections; default to "lg" (most spacing) for an airy layout
- variables: Variable[] // every {{placeholder}} you use MUST be declared here
- children: Node[] // the document body, top to bottom
Variable: { id, name (snake_case, used as {{name}}), label (human), type: "text"|"date"|"number"|"currency", defaultValue?: string }
Node is one of (every node has: id, name, width: "full"|"1/2"|"1/3"|"1/4"|"2/3"|"3/4"|"auto", order: number, align?: "left"|"center"|"right", style?: NodeStyle):
container: { type:"container", layout: { direction:"row"|"column", gap:"none"|"sm"|"md"|"lg", justify?:"start"|"center"|"end"|"between", alignItems?:"start"|"center"|"end"|"stretch" }, children: Node[] }
text: { type:"text", content: string (supports \n, {{vars}}, and **inline bold** — wrap part of the text in double asterisks to bold just that part, e.g. "Total: **{{total}}**"), fontSize?:"xs"|"sm"|"base"|"lg"|"xl", fontWeight?:"normal"|"medium"|"semibold"|"bold" }
table: { type:"table", columns: { id, name (data key), label (header), width?: "40%", align?: "left"|"center"|"right" }[], rowVariable: string (a variable holding the row array) }
spacer: { type:"spacer", height: "sm"|"md"|"lg"|"xl" }
divider: { type:"divider", lineStyle?: "solid"|"dashed"|"dotted" }
NodeStyle: { backgroundColor?: hex, backgroundMode?: "none"|"solid"|"gradient", gradientTo?: hex, textColor?: hex, padding?: "none"|"sm"|"md"|"lg"|"xl", borderRadius?: "none"|"sm"|"md"|"lg", fullBleed?: boolean }
VARIABLES — how data is inserted:
- In text content, insert a value with double braces and the exact snake_case name, e.g. {{invoice_number}} — no spaces inside the braces. Every {{name}} you use MUST be declared in variables[].
- ALWAYS fill every variable's defaultValue — never leave one blank. If the user gave you specific data/values to use, put those exact values in the defaultValues; otherwise invent realistic dummy data. This is required: the Filled preview must show a complete, non-empty document.
- TABLES do NOT use {{}}. A table auto-renders one row per item in its rowVariable array, pulling item[column.name] for each cell — so each column "name" must match the row object's key. The rowVariable variable's defaultValue must be a JSON-encoded string of the row array, i.e. equal to JSON.stringify([{ description: "Brand design", qty: "1", amount: "$2,400.00" }]).
RULES:
- Use containers (direction:"row") to place items side by side (e.g. logo left / details right).
- ROW WIDTHS — a direction:"row" container lays ALL its children on ONE line; they never wrap. The
children's widths must add up to AT MOST "full". Treat the fractions as: full=1, 3/4=.75, 2/3≈.67,
1/2=.5, 1/3≈.33, 1/4=.25. So 1/3+1/3+1/3, 1/2+1/2, and 2/3+1/3 fit (sum ≤ full); but 1/2+1/2+1/2
(=1.5) or 2/3+2/3 (≈1.33) overflow and break the layout. Do NOT add another child to a row if it
would push the total past "full" — instead split the items into multiple row containers (stacked in
a column), or narrow each child's width so the row's total stays ≤ full.
- For label/value pairs (dates, totals, "Bill To", reference numbers), nest a direction:"row" container
with two text children — a BOLD label (fontWeight:"bold") and the value as a {{variable}} — each with a
width (e.g. label "1/3", value "2/3") so they align in columns. Stack such rows in a column container.
- Put real, realistic content with {{variables}} for the data that changes; declare each variable.
- Use a table node for any repeating rows (line items, attendees) and set rowVariable.
- INLINE BOLD: to bold PART of any text, wrap it in **double asterisks** — e.g. a text node's content "Total: **{{total}}**". Bold is applied purely via the text string (there is NO per-run style flag and NO per-column weight); wrapping in ** ** is the ONLY way to bold part of a string. Only apply bold where the user actually asks for it — never add it on your own. It also works inside TABLES: to bold the values of a specific column the user named, wrap each of that column's values inside the rowVariable's row data with ** **; to bold a header, wrap that column's label in ** **.
- Spacing between top-level sections comes from the document "gap" — set it to "lg" by default and
do NOT insert spacer nodes between sections. Use a spacer only for fine spacing inside a container.
- Table column alignment: left-align text columns, right-align money/number columns (price, amount,
total, qty totals), center only short codes/status; a header's alignment matches its column.
- CERTIFICATES / AWARDS / DIPLOMAS: set pageSize:"auto" so the page grows to fit the content (no empty space below). Center-align the text (align:"center"), make the recipient name large (fontSize "xl", bold), and place signature lines near the bottom.
- Every id must be unique. Keep the design clean and professional.
After the tool returns a url, share it and tell the user they can open it to preview, edit any field, and download the PDF.