Skip to main content
TemplateDX combines Markdown and JSX to create powerful, type-safe templates for LLM prompts. This page provides a comprehensive overview of the syntax.

Basic Structure

Every TemplateDX template is a .mdx file with optional frontmatter and a mix of Markdown and JSX:
---
title: My Prompt Template
description: A brief description
---

# Your prompt content here

You are a helpful assistant specializing in {props.domain}.

<If condition={props.showInstructions}>
## Instructions
{props.instructions}
</If>

Frontmatter

Frontmatter is optional metadata at the top of your file:
---
title: Customer Support Prompt
description: Template for customer support interactions
version: 1.0
---

Variables

Access dynamic data using curly braces:
{props.userName}           // Simple variable
{props.user.email}         // Nested property
{props.items[0]}          // Array access
{props.user?.name}        // Optional chaining
Learn more about variables →

Expressions

Evaluate JavaScript expressions inline:
{props.score >= 90 ? "Excellent" : "Good"}
{props.items.length}
{props.name.toUpperCase()}
{props.tags.join(", ")}
Learn more about expressions →

Control Flow

Conditionals

Use <If>, <ElseIf>, and <Else> tags:
<If condition={props.userType === "premium"}>
  You have access to premium features.
</If>
<ElseIf condition={props.userType === "standard"}>
  You have access to standard features.
</ElseIf>
<Else>
  You have access to basic features.
</Else>

Loops

Use <ForEach> to iterate over arrays:
<ForEach arr={props.items}>
  {(item, index) => (
    <>
      {index + 1}. {item.name} - {item.description}
    </>
  )}
</ForEach>
Learn more about control flow →

Filters

Transform data with built-in filters. TemplateDX ships 10 filters out of the box: abs, capitalize, dump, join, lower, replace, round, truncate, upper, urlencode.
{upper(props.status)}              {/* ACTIVE */}
{lower(props.email)}               {/* user@example.com */}
{capitalize(props.name)}           {/* Note: only capitalizes first char — doesn't lowercase the rest */}
{truncate(props.content, 100)}     {/* First 100 chars + "..." */}
{join(props.tags, ", ")}           {/* tag1, tag2, tag3 */}
Learn more about filters →

Components

Create reusable template components:
import SystemRole from './system-role.mdx';
import Examples from './examples.mdx';

<SystemRole role="expert" domain={props.domain} />

## Task

{props.taskDescription}

<Examples data={props.examples} />
Learn more about components →

Raw output

Use <Raw> to emit the enclosed content as literal source text — expressions inside <Raw> are not evaluated. The plugin re-serializes its children through Markdown, so you get exactly what you wrote.
<Raw>
  {props.variableName}
</Raw>
Output: {props.variableName} (literal text, not the value of props.variableName).

XML tags

Lowercase XML tags are preserved as-is in the output, making them ideal for prompt engineering patterns like <examples>, <context>, and <instructions>. A fixed allow-list of HTML tags (per supported-tags.ts) also passes through unchanged. Expressions inside these tags are evaluated normally.
<User>
<examples>
<example>What is 2+2? The answer is 4.</example>
<example>What is 3+3? The answer is 6.</example>
</examples>

Now answer: What is {props.a}+{props.b}?
</User>
Output:
<examples>
<example>What is 2+2? The answer is 4.</example>
<example>What is 3+3? The answer is 6.</example>
</examples>

Now answer: What is 5+5?
XML tags support attributes and nesting:
<User>
<context type="system">You are an expert assistant.</context>
<instructions>
<rule>Be concise</rule>
<rule>Cite sources</rule>
</instructions>
</User>
Only lowercase tags are treated as XML passthrough. PascalCase tags like <User>, <System>, and <ForEach> are reserved for TemplateDX built-in tags and components. Variables and expressions inside XML tags are still evaluated normally.

Comments

Use JSX-style comments:
{/* This is a comment */}

{/**
  * Multi-line comment
  * for documentation
  */}

Fragments

Use fragments to group elements without adding markup:
<>
  First line
  Second line
</>

Markdown Support

TemplateDX supports all standard Markdown:
# Heading 1
## Heading 2

**Bold text**
*Italic text*

- Bullet list
- Item 2

1. Numbered list
2. Item 2

[Link text](https://example.com)

`inline code`

\`\`\`javascript
// Code block
const x = 10;
\`\`\`

Whitespace

TemplateDX preserves whitespace in your templates:
Line 1
Line 2

Paragraph with blank line above

Escaping literal braces

To emit literal { or } in output, wrap the content in <Raw>:
<Raw>{`{literal-braces}`}</Raw>

Type safety

See Type safety for the canonical flow — npx agentmark generate-types emits AgentmarkTypes from your prompt schemas. That’s the codegen pipeline AgentMark actually uses at runtime. TemplateDX itself doesn’t evaluate JSDoc or TypeScript types; comments are stripped at bundle time (bundler.ts:150 removeComments).

Best practices

  1. Use descriptive variable namesprops.customerName instead of props.n.
  2. Keep templates modular — break large templates into components.
  3. Generate types — run npx agentmark generate-types and pass the result to createAgentMarkClient<AgentmarkTypes>() for compile-time prop validation.
  4. Use conditionals wisely — make prompts adapt to context.
  5. Leverage filters — transform data at the template level instead of reshaping it in your application code.

Complete Example

Here’s a full example combining multiple features:
---
title: Product Review Analysis
---

{/**
  * @typedef Props
  * @property {string} productName
  * @property {Array<{author: string, rating: number, comment: string}>} reviews
  * @property {string} analysisType
  */}

# Product Review Analysis for {props.productName}

You are an expert product analyst. Analyze the following customer reviews and provide insights.

## Reviews ({props.reviews.length} total)

<ForEach arr={props.reviews}>
  {(review, index) => (
    <>
      ### Review {index + 1}
      **Rating**: {review.rating}/5
      **Author**: {capitalize(review.author)}

      "{truncate(review.comment, 200)}"

      ---
    </>
  )}
</ForEach>

## Analysis Instructions

<If condition={props.analysisType === "sentiment"}>
  Focus on overall sentiment and emotional tone in the reviews.
</If>
<ElseIf condition={props.analysisType === "features"}>
  Identify the most mentioned product features and customer opinions about them.
</ElseIf>
<Else>
  Provide a comprehensive analysis covering sentiment, features, and improvement suggestions.
</Else>

Please provide your analysis in a structured format.

Next Steps