How to Create Custom Templates for AIOX: A Complete Guide to the Template Processing System

AIOX's template processing system is a standalone JavaScript engine that renders documents by replacing {{VARIABLE}} placeholders, conditionals, and loops with supplied data, requiring no external dependencies.

The SynkraAI/aiox-core repository ships a zero-dependency template processing system located in .aiox-core/infrastructure/scripts/template-engine.js. This engine transforms any plain-text file—whether Markdown, YAML, or custom formats—into a fully rendered document by processing Mustache-like syntax. You can use it to generate documentation, configuration files, or scaffolding within AIOX workflows.

Core Syntax and Features

The template engine implements four primary syntax constructs. Understanding these patterns is essential before creating custom templates for AIOX.

Simple Variables

Use double curly braces to inject scalar values directly into your template:


{{VAR_NAME}}

The engine substitutes this placeholder with the corresponding value from your variables object.

Conditional Blocks

Wrap content in {{#IF_CONDITION}} tags to include it only when the variable evaluates to truthy:


{{#IF_HAS_NOTES}}

## Notes

{{NOTES}}
{{/IF_HAS_NOTES}}

The closing tag must match the opening tag exactly, prefixed with a forward slash.

Loop Iteration

Repeat blocks for array elements using {{#EACH_ITEMS}}:


{{#EACH_TASKS}}
- {{ITEM.title}} (Priority: {{ITEM.priority}})
{{/EACH_TASKS}}

Inside loops, the engine exposes five automatic variables:

  • {{ITEM}} - The current array element
  • {{INDEX}} - The zero-based index
  • {{FIRST}} - Boolean true for the first iteration
  • {{LAST}} - Boolean true for the last iteration
  • A shortcut variable based on the loop name (e.g., {{TASKS}} refers to the current item when iterating over EACH_TASKS)

Escape Sequences

Prevent processing by prefixing with a backslash:


\{{LITERAL}}

The engine temporarily swaps escaped braces during processing and restores them in the final output.

Processing Pipeline

The process() method executes transformations in a strict order to handle nested logic correctly:

  1. Escaped braces are temporarily replaced with placeholders
  2. Loops expand first (allowing inner conditionals to reference loop variables)
  3. Conditionals evaluate next
  4. Simple variables substitute
  5. Escaped braces restore to literal {{...}} text

TemplateEngine API Reference

The engine exposes five primary methods in .aiox-core/infrastructure/scripts/template-engine.js:

  • process(template, variables) - Synchronously render a template string with a plain object of variables
  • loadAndProcess(templatePath, variables) - Asynchronously read a file from disk and render it (returns a Promise)
  • validateTemplate(template, requiredVars) - Verify that every variable in requiredVars appears in the template; returns { valid, missing, found }
  • getTemplateVariables(template) - Extract all placeholders, categorized into simple, conditionals, and loops
  • escapeInput(input) - Safely escape user-provided data to prevent injection before feeding it to the engine

Rendering Templates: Practical Examples

Inline String Rendering

For quick transformations, instantiate the engine and call process() directly:

const TemplateEngine = require('.aiox-core/infrastructure/scripts/template-engine');
const engine = new TemplateEngine();

const template = `

# {{TITLE}}

Created by {{AUTHOR}} on {{DATE}}

{{#IF_HAS_NOTES}}

## Notes

{{NOTES}}
{{/IF_HAS_NOTES}}

{{#EACH_TASKS}}
- {{ITEM.title}} ({{ITEM.priority}})
{{/EACH_TASKS}}
`;

const variables = {
  TITLE: 'Sprint 42 Summary',
  AUTHOR: 'Dex',
  DATE: new Date().toISOString().split('T')[0],
  HAS_NOTES: true,
  NOTES: 'All stories delivered on time.',
  TASKS: [
    { title: 'Write docs', priority: 'HIGH' },
    { title: 'Add tests', priority: 'MEDIUM' },
  ],
};

console.log(engine.process(template, variables));

This outputs a fully rendered Markdown document with conditional sections and iterated task lists.

Loading External Template Files

Use loadAndProcess() to render templates stored in the product catalogue:

const TemplateEngine = require('.aiox-core/infrastructure/scripts/template-engine');
const engine = new TemplateEngine();

async function generateStory() {
  const templatePath = '.aiox-core/product/templates/story-tmpl.yaml';
  const variables = {
    STORY_ID: '3.12',
    TITLE: 'User onboarding flow',
    AUTHOR: 'Ana',
    DATE: '2025-12-05',
  };

  const output = await engine.loadAndProcess(templatePath, variables);
  console.log(output);
}

generateStory();

Validating Templates Before Rendering

Prevent runtime errors by verifying required variables exist:

const engine = new (require('.aiox-core/infrastructure/scripts/template-engine'))();

const customTemplate = `

# {{COMPONENT_NAME}}

{{#IF_HAS_PROPS}}

## Props

{{#EACH_PROPS}}
- {{ITEM.name}}: {{ITEM.type}}
{{/EACH_PROPS}}
{{/IF_HAS_PROPS}}
`;

const required = ['COMPONENT_NAME', 'HAS_PROPS'];
const validation = engine.validateTemplate(customTemplate, required);

if (!validation.valid) {
  console.error('Missing variables:', validation.missing);
  process.exit(1);
}

const result = engine.process(customTemplate, {
  COMPONENT_NAME: 'Button',
  HAS_PROPS: true,
  PROPS: [{ name: 'variant', type: 'string' }],
});
console.log(result);

Escaping User Input

Sanitize untrusted data to prevent template injection:

const engine = new (require('.aiox-core/infrastructure/scripts/template-engine'))();
const userInput = '<script>alert("xss")</script> {{UNSAFE}}';
const safe = engine.escapeInput(userInput);

const template = 'User comment: {{COMMENT}}';
console.log(engine.process(template, { COMMENT: safe }));

The output displays literal HTML and escaped placeholders rather than executing them.

Creating Custom Templates for AIOX

Follow this workflow to build reusable templates for documentation generation or scaffolding.

Step 1: Create the Template File

Store your template under .aiox-core/product/templates/ or any project directory. For example, create .aiox-core/product/templates/component-tmpl.md:


# {{COMPONENT_NAME}}

**Type:** {{COMPONENT_TYPE}}
**Created:** {{DATE}}
**Author:** {{AUTHOR}}

## Description

{{DESCRIPTION}}

{{#IF_HAS_PROPS}}

## Props

| Name | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
{{#EACH_PROPS}}
| {{ITEM.name}} | {{ITEM.type}} | {{ITEM.default}} | {{ITEM.description}} |
{{/EACH_PROPS}}
{{/IF_HAS_PROPS}}

Step 2: Define a Validation Schema

Add a YAML schema file alongside your template (e.g., component-tmpl.schema.yaml) to document required variables:

name: component-template
version: '1.0'
description: Template for component documentation
variables:
  required:
    - COMPONENT_NAME
    - COMPONENT_TYPE
    - DATE
    - AUTHOR
    - DESCRIPTION
  optional:
    - HAS_PROPS
    - PROPS
validation:
  COMPONENT_TYPE:
    enum: [React, Vue, Angular, Vanilla]
  DATE:
    format: date

Feed the required array into validateTemplate() before rendering to ensure data completeness.

Step 3: Render from Your Script

Import the engine and process your custom template:

const engine = new (require('.aiox-core/infrastructure/scripts/template-engine'))();
const templatePath = '.aiox-core/product/templates/component-tmpl.md';

const variables = {
  COMPONENT_NAME: 'PrimaryButton',
  COMPONENT_TYPE: 'React',
  DATE: '2025-01-15',
  AUTHOR: 'DevTeam',
  DESCRIPTION: 'Main action button with variants',
  HAS_PROPS: true,
  PROPS: [
    { name: 'variant', type: 'string', default: 'primary', description: 'Visual style' }
  ]
};

const output = await engine.loadAndProcess(templatePath, variables);
console.log(output);

Step 4: Integrate with AIOX Workflows

Call loadAndProcess() inside wizard steps, CLI commands, or custom tasks to automate documentation generation during your development pipeline.

Key Implementation Files

Understanding the source structure helps when debugging or extending the template processing system:

Summary

  • The AIOX template processing system resides in .aiox-core/infrastructure/scripts/template-engine.js and requires zero external dependencies
  • Templates use Mustache-like syntax with four constructs: simple variables ({{VAR}}), conditionals ({{#IF}}), loops ({{#EACH}}), and escapes (\{{}})
  • The TemplateEngine API provides process() for strings, loadAndProcess() for files, and validateTemplate() for pre-flight checks
  • Custom templates belong in .aiox-core/product/templates/ and can include companion schema files for validation
  • Always use escapeInput() to sanitize user data before passing it to the engine

Frequently Asked Questions

What file formats does the AIOX template processing system support?

The engine processes any plain-text format including Markdown, YAML, JSON, or custom text files. It performs pure string substitution, so the output format depends entirely on your template's content structure.

How do I validate that my template contains all required variables before rendering?

Call engine.validateTemplate(template, requiredVars) with an array of required variable names. The method returns an object with valid (boolean), missing (array), and found (array) properties, allowing you to abort execution or prompt for missing data before calling process().

Can I nest conditionals inside loops when creating custom templates?

Yes. The processing pipeline explicitly expands loops before evaluating conditionals, so inner {{#IF}} blocks can reference loop variables like {{ITEM}}, {{INDEX}}, {{FIRST}}, or {{LAST}}. This allows complex logic such as alternating row classes or conditional formatting within iterations.

Where should I store custom templates in an AIOX project?

While you can store templates anywhere, the conventional location is .aiox-core/product/templates/. Place companion schema files (.schema.yaml) in the same directory. This structure keeps templates organized alongside AIOX's built-in PRD, ADR, and Story templates for easy discovery and maintenance.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →