Tags are JSX elements backed by a plugin. TemplateDX ships five built-in tags (<If>, <ElseIf>, <Else>, <ForEach>, <Raw>) and exposes two ways to register your own: a global static API and a per-instance API on TemplateDX.
Creating custom tags (TypeScript)
Extend TagPlugin
Create a class that extends TagPlugin and implements transform:
The transform method
transform(props, children, context) must return a Promise<Node | Node[]>.
context: PluginContext exposes:
tagName has type string, but the conditional plugin (tag-plugins/conditional.ts) defensively guards if (!tagName) throw .... Built-in tags can rely on tagName having a value; advanced consumers that invoke a plugin’s transform directly (outside the transformer) should pass a valid name.
nodeHelpers surface
Register the plugin (static or instance API)
The registry exposes both a static API (process-wide) and an instance API (scoped to a TemplateDX engine).
Static (global) registration is the simplest path; everything using the default transform/stringify exports sees it:
Instance (scoped) registration is for when you want plugins isolated per engine (for example, a server handling multiple tenants with different tag sets):
new TemplateDX({ includeBuiltins: true }) copies the static built-ins (If, ElseIf, Else, ForEach, Raw) into the instance; pass false to start empty.
Use the tag in a template
Example: Quote tag
Usage:
Output:
The final stringify step backslash-escapes line-leading > in text nodes (the same mechanism that escapes { and <), so blockquote markers your plugin emits appear escaped in the rendered output.
Creating custom tags (Python)
agentmark-templatedx (Python) mirrors the TS surface. Subclass TagPlugin, implement async def transform, and register via the static (register_global) or instance API.
The Python PluginContext dataclass has node_helpers (snake_case mirror of the TS NodeHelpers surface), create_node_transformer, scope, and tag_name.
For instance-scoped registration, construct the engine and use register_tag_plugin:
Built-in tags
ForEach
The ForEach tag loops over an array.
Syntax
Parameters
arr: Array<T>: an array of items you want to iterate on
children: (item: T, index: number) => any: a callback function for each item
Example
Output
Conditionals
The If, ElseIf, and Else tags let you conditionally output content.
Syntax
Parameters
If / ElseIf:
condition: boolean: the condition to check
children: Node: the node to render if the condition is true
Else:
children: Node: the content to render if no previous condition matched
condition must be an actual boolean. Non-boolean values coerce to false, not truthy: <If condition={props.list}> renders nothing even when the list is non-empty. Pass a comparison instead, such as condition={props.list.length > 0}.
Example
Output
A scope supports one condition chain. After any <If>, <ElseIf>, or <Else> in a scope has rendered, every later conditional tag in that same scope renders nothing, even a new <If> with a true condition. Conditionals nested inside another tag’s children (for example a <ForEach> or <If> body) get a fresh scope, so this limit doesn’t affect them.
Raw
The Raw tag outputs its children verbatim, without expression interpolation.
Syntax
Parameters
children: Node: the raw text
Example
Output
Next steps
Tags handle control flow; for value transformation inside expressions, see Filters.