Template Authoring
Codraft templates are standard .docx or .html files with Jinja2-style markup embedded in the content. This guide covers everything you need to write templates that work correctly with the interview engine.
Placeholders
Section titled “Placeholders”Use double-brace syntax to mark any text that should be collected from the user:
This Agreement is entered into by {{ disclosing_party_name }}(the "Disclosing Party") with address at {{ disclosing_party_address }}.Rules:
- Always include spaces inside the braces:
{{ name }}not{{name}} - Variable names must be valid Python identifiers: lowercase letters, numbers, and underscores; no spaces or hyphens
- The same variable can appear any number of times — it is collected once and substituted everywhere
In .docx files, place placeholders directly in the document text. Codraft uses docxtpl, which preserves all formatting around the placeholder. In .html files, placeholders can appear anywhere in the body, attributes, or <style> blocks.
Conditional sections
Section titled “Conditional sections”Use {% if %} / {% else %} / {% endif %} to include or exclude a section based on the user’s answer:
{% if include_warranty %}The Seller warrants that the goods are free from defects for a periodof {{ warranty_period }} from the date of delivery.{% else %}The goods are sold "as is" without warranty of any kind.{% endif %}When Claude reaches a conditional gate variable (include_warranty above), it asks a yes/no question. If the answer is no, the entire {% if %} block — and all variables inside it — is skipped.
Two condition forms
Section titled “Two condition forms”Truthiness — the variable is truthy (boolean true, or any non-empty string):
{% if include_ip_assignment %}...{% endif %}Equality — the variable equals a specific value:
{% if payment_method == 'bank_transfer' %}Bank: {{ bank_name }}Account: {{ account_number }}{% else %}Payment will be made via {{ payment_method }}.{% endif %}For equality conditions, Claude collects the gate variable first (using a choice list if configured), then shows only the relevant branch questions.
{% else %} is optional
Section titled “{% else %} is optional”You can use {% if %} / {% endif %} without an {% else %} block. If the condition is false, the section is simply omitted.
Loop sections
Section titled “Loop sections”Use {% for %} / {% endfor %} for repeating sections — line items, milestones, signatories, or any list:
{% for milestone in milestones %}Milestone: {{ milestone.description }}Due Date: {{ milestone.date }}Amount: {{ milestone.amount }}{% endfor %}Inside the loop body, sub-variables are referenced with dot notation: {{ loop_variable.field_name }}.
Claude collects the first item’s fields, then asks “Would you like to add another milestone?” The loop continues until you say no. The loop variable (milestones) holds a list of objects, each with the sub-fields you defined.
Rules and constraints
Section titled “Rules and constraints”- One template file per directory — each template directory contains exactly one
.docxor.htmlfile, not both - Single-level nesting only — do not place
{% for %}inside{% if %}, or{% if %}inside{% for %} - No
{% elif %}— use separate{% if %}blocks instead - No expressions —
{{ price * quantity }}is not supported; collect pre-calculated values from the user - Variables are always user-supplied — there are no computed or derived fields in v2
File format differences
Section titled “File format differences”| Feature | .docx | .html |
|---|---|---|
| Engine | docxtpl | jinja2 |
| Output | .docx | .html + .pdf |
| Formatting | Preserved from template | Controlled by CSS |
| Syntax | Same Jinja2 syntax | Same Jinja2 syntax |
| Tables | Native Word tables | HTML <table> |
For legal documents where formatting matters (line spacing, fonts, headers), .docx is usually the right choice. For documents that will be sent digitally or embedded in web workflows, .html + PDF is more flexible.