What the Prompt Template Builder does
This builder turns a one-off prompt into a reusable template: you mark the parts that change as typed variables, wrap optional instructions in conditions, and render the template against a set of test cases to see every prompt it will actually produce - with missing values and wrong types reported before anything reaches a model.
The template language is deliberately small - {{name}}, {{#if}}, {{else}}, {{#unless}} - and is interpreted by a parser in your browser, never executed as code. Values are inserted literally, so a customer message containing {{ or a formula cannot change the template. The finished template, its variable definitions and its test cases export as one JSON file you can keep in version control.
How to use it
- Write or paste your prompt. Replace the parts that vary with
{{variable_name}}and wrap optional paragraphs in{{#if flag}} ... {{/if}}, with an optional{{else}}branch. - Press Detect variables. Names used only in conditions become optional booleans; the rest become required text. Change types to number, enum (with a values list) or list, and add defaults and descriptions.
- Add test cases: typical inputs, edge cases and at least one deliberately bad input. Each case is a name and a values object.
- Render the test cases. Read the problems for each, open the rendered prompts to check the wording, then download the template JSON or the renders as JSONL for an evaluation run.
Reading the results
Render cleanly counts the cases with no missing required variable, no type error and no unknown value. A case that renders cleanly can still be a bad prompt - read it.
Template problems are structural: an {{#if}} never closed, an {{else}} outside a block, an unsupported tag. They are reported with line numbers and stop rendering until fixed, because a half-parsed template would silently drop text.
Used but not declared means the template references a name with no definition; it is treated as required text. Declared but never used usually means a typo in one place or the other.
Worked example: one template, a good case and a bad one
Template: "Reply in a {{tone}} tone, in at most {{max_words}} words." followed by {{#if is_vip}}Offer a call with their account manager.{{else}}Point them to the help centre.{{/if}} and "Customer message: {{message}}". Variables: tone is an enum of friendly, formal or brief (default friendly); max_words a number (default 150); is_vip a boolean (default false); message required text.
Case one sets tone to formal, is_vip to true and message to "Backups failed." It renders cleanly as: "Reply in a formal tone, in at most 150 words." then "Offer a call with their account manager." then "Customer message: Backups failed." The default of 150 filled the word limit.
Case two sets tone to angry and max_words to lots, and gives no message. It reports three problems: tone must be one of friendly, formal or brief; max_words must be a number; the required message is missing. The rendered text shows the gaps - "Reply in a tone, in at most words" - which is exactly the prompt your application would have sent without validation.
Why typed variables and test cases
Most prompt bugs are not clever failures of the model but plain assembly errors: an empty variable, a number formatted as text, a conditional paragraph that never appears, or user input pasted where an instruction belonged. Rendering a template against named test cases catches these before an evaluation run spends money finding them the slow way.
Keep user-supplied text inside clear delimiters, as the examples do with <<< and >>>, and state in the instructions that it is data. Delimiters do not make prompt injection impossible, but they make the boundary visible to the model and to reviewers.
Limitations: what the result does not prove
- It checks structure and values, not quality. A template that renders cleanly can still produce poor answers; test the rendered prompts against a model with an evaluation set.
- The syntax is a deliberate subset. Loops, partials, helpers and expressions are not supported, so a template written for Handlebars, Jinja or LangChain may need small edits.
- Token figures shown per case are a characters-divided-by-four estimate; use the AI Token Counter for exact OpenAI counts.
- Nothing is saved in the browser. Download the template JSON to keep your work.
Privacy: where your data goes
Everything you paste, type or drop is processed in this browser tab. It is not uploaded, logged, stored or sent to analytics. Session recording and tag-manager scripts are switched off on this page.
Standards and sources
- Anthropic - Prompt templates and variables
- OpenAI - Prompt engineering guide
- Mustache manual (the syntax this subset resembles)
- OWASP - LLM01 Prompt injection
Frequently asked questions
What syntax does the prompt template use?
Double curly braces: {{name}} inserts a variable, {{#if name}} ... {{/if}} includes a section when the value is truthy, {{else}} gives an alternative, and {{#unless name}} is the inverse. It resembles Mustache and Handlebars so templates stay readable, but only these tags are recognised.
Can a variable value break or inject into the template?
Not into the template structure: values are inserted as literal text after parsing, so a value containing {{other}} or {{#if}} is printed as-is and never re-rendered. The model will still read whatever the value says, so delimit user text and treat it as data in your instructions.
What counts as true for an if block?
A non-empty string, a non-zero number, the boolean true, or a list with at least one item. Boolean values can be given as true/false, yes/no or 1/0; anything else is reported as a type error rather than guessed.
How should I choose test cases for a prompt template?
Cover the branches and the edges: every enum value at least once, each condition both on and off, the longest realistic input, an empty optional value, non-English text, and one deliberately invalid case so you can see the validation work. Ten well-chosen cases usually beat a hundred random ones.
Can I use the exported template in my own code?
Yes. The JSON holds the template text, the variable definitions and the test cases. Any Mustache-style renderer handles the variables and if blocks; keep the variable checks in your code too, since the renderer you use may not validate types the way this page does.
Why are condition-only variables detected as booleans?
A name that appears only in {{#if}} or {{#unless}} is usually a switch, so Detect variables makes it an optional boolean defaulting to false. If the same name is also inserted as text somewhere, it is detected as a string instead. You can change either in the JSON.
Last reviewed by the A2Z.Tools team against the sources listed above.