← All posts

Build prompt templates with variables you can fill and batch-test

A prompt you only use once can live in the editor. A prompt you reuse — translate, extract, review, answer from retrieved context — should be a template with the moving parts marked.

Templates stores those patterns locally. Built-in templates cover writing, development, RAG, agents, and data extraction. Anything you save yourself stays in this browser, not in an account.

The only placeholder syntax

Variables are double braces with a plain name:

Translate the following text from {{source_lang}} to {{target_lang}}.

Rules:
- Preserve meaning and formatting
- Keep code, IDs, and product names unchanged
- Output only the translation

Text:
{{text}}

Names are simple tokens such as source_lang or text. The variable panel lists every name it finds. Fill the inputs and the preview replaces them. Unfilled names stay as {{text}} so you can see what is still open.

That same syntax is what Variable batch test and the linter understand. Do not invent a second style (${text}, <text>, or single braces) in the same draft or the batch table will miss the column.

Start from a built-in, then save your own

The library is grouped by job. A few that cover most API work:

Template Mode What varies
Translate / Summarize Text Language, tone, source text
Code review ChatML Language, focus, and the code block
RAG system ChatML Domain, language, context, question
Data extract Text Output format, field list, source text

Open one, fill the variables, and send it to the editor when you want token counts and export. If you change the wording, save a custom template. Custom templates are JSON in localStorage. They are not synced, and they disappear with a cleared site storage — export a copy if the wording is the one you ship.

Chat templates keep system and user as separate messages. Text templates are a single buffer. Pick the mode that matches how you will call the API. The ChatML editor article shows why that split matters for export.

Batch-test rows before you call the API

One filled preview proves the template runs. It does not prove the wording survives ten different inputs.

  1. Copy the template, placeholders included, into Variable batch test.
  2. The table builds a column per name (source_lang, target_lang, text, …).
  3. Add a row per case, or paste TSV.
  4. Read each preview. A warning means a placeholder was still unresolved.
  5. Open a row in the editor when you want a token count or ChatML export for that case.

A useful first batch for the translation template is three rows: a short UI string, a paragraph that contains a product name, and a snippet of code that must not be translated. If row 3 rewrites identifiers, the rule line is weak — edit the template, not the row.

For retrieval, the batch is usually one stable system template and many {{question}} / {{context}} pairs. Keep the rules identical across rows so you are testing the question, not accidentally testing a rewritten system prompt. That layout is spelled out in Build a RAG system prompt.

Check leftovers before export

Lint flags {{names}} that are still in the text, and braces that are not valid names. Run it after you fill a template and before you copy JSON. A leftover {{context}} shipped to production is a silent empty retrieval.

Other checks on the same page: missing or empty system message, empty user turn, broken JSON fences, duplicate lines, and a character count that is already past a soft or hard threshold. Lint does not call a model. It only reads the draft.

Keep the release copy

After the batch looks right, save a version snapshot labeled Release, then export. The template can keep its placeholders for the next task. The snapshot is the filled prompt you actually sent.