Template-M

A DOM-based JavaScript templating library that treats templates as functions and JSON as function applications

Get Started

What is Template-M?

Template-M takes a JSON structure, a template DOM element, and a target element, then transforms the JSON into DOM elements and replaces the target. It uses a unique function-based approach where:

This declarative approach lets you define reusable template functions in HTML and apply them to data structures, creating a clean separation between template structure and application logic.

What makes this different? Your template looks exactly like your output HTML. No <?php ?> blocks, no <% %> tags, no JSX syntax that needs transpiling. Just HTML with data attributes. This means you can see what you're building without running any code, and designers can work with templates without understanding your data layer.

Two Modes of Operation

Template-M supports two distinct modes for different use cases:

Render Mode (Default)

In render mode, Template-M transforms JSON data into DOM elements using template functions. This is the primary mode for production applications where you have dynamic data to display.

Demo Mode

Demo mode is designed for development, documentation, and interactive demonstrations. In this mode, there is no data JSON object—the entire template is copied to the target element. Instead of rendering data, demo mode provides a tree-based navigation system.

Demo mode works because your template is already valid HTML. You don't need to mock data, spin up a server, or run a build step to see what you're creating. Just open the template file in a browser. This is only possible because Template-M templates look exactly like their output—unlike PHP templates with embedded code, JSX that needs transpiling, or XSLT that transforms XML into something completely different.

When to Use Each Mode

Use Render Mode when:

  • Building production applications with dynamic data
  • You need to transform JSON into DOM elements
  • Working with APIs or data sources
  • Creating reusable template functions

Use Demo Mode when:

  • Creating interactive documentation
  • Building component showcases or style guides
  • Developing and iterating on templates rapidly
  • You need tree-based navigation through content
  • Working on static templates without dynamic data

Function Placement and Mode Behavior

In render mode, it doesn't matter where functions are defined. You could have the root template followed by a flat list of all functions. Template-M will extract and use them regardless of their placement.

However, it's recommended to define functions at the place where their output will appear. This is better for two reasons:

This means you can design your templates to work well in both modes: structured logically for render mode while maintaining visual coherence in demo mode.

See template-m-demo.js for the demo mode implementation.

Quick Example

<!-- HTML Template -->
<template id="movie-template">
  <nav>
    <h3 data-tme="> $title"></h3>
    <a href="/cast">Cast</a>
    <p data-tme="> $metadata"></p>
  </nav>
  <div data-fn="genre">
    <h4 data-tme="> $name"></h4>
  </div>
</template>

<!-- Target element -->
<div id="content"></div>

<script>
// JSON data with function application
const data = {
  title: "The Master",
  metadata: {
    name: "Drama",
    template: "genre"  // Apply the "genre" function
  }
};

// Render: templateM(templateId, data, targetElementId)
templateM("movie-template", data, "content");

// Result:
// <nav>
//   <h3>The Master</h3>
//   <a href="/cast">Cast</a>
//   <p><h4>Drama</h4></p>
// </nav>
</script>

The metadata object is a function application - it applies the "genre" template function, which replaces $name with "Drama", producing <h4>Drama</h4>.

DOM-Based

Works directly with the DOM, creating DocumentFragments instead of string manipulation.

Function Templates

Templates are composable functions defined with data-fn, enabling powerful abstraction.

Declarative

Data attributes (data-fn, data-tme, data-tma) declare behavior directly in HTML.

Key Features

Arrays with Auto-Templating

Arrays automatically render using the singular form of the property name:

<template>
  <ul>
    <li data-fn="repo:$repos" data-tme="> $name"></li>
  </ul>
</template>

{
  "repos": [
    {"name": "Blueberry"},
    {"name": "Apple"},
    {"name": "Charcoal"}
  ]
}

Parent Property Access

Use $^propertyName to access parent object properties:

<div data-fn="user:$user">
  <h1 data-tme="> $name"></h1>
  <h2 data-tme="> $^title"></h2>  <!-- Parent's title -->
</div>

{
  "title": "Movie Database",
  "user": {"name": "John"}
}

Conditional Rendering

The < symbol in data-tme replaces the element itself. Combined with comparisons or boolean values, this enables conditional rendering:

<ul>
  <li data-tme="< $selected=apple">Item Apple</li>
  <li data-tme="< $selected=banana">Item Banana</li>
</ul>

{"selected": "banana"}  <!-- Only banana item renders -->

When the comparison is false, or the value is null or false, the element is replaced with an empty DocumentFragment (removed).

Dynamic Attributes

Set attributes, toggle classes, and attach handlers:

<input data-tma="$placeholder:placeholder;$isValid:.valid">
<button data-tma="handleClick($id, $name):onclick">Click</button>

Where Template-M Fits

Template-M is a declarative DOM templating library. It sits in a unique position in the JavaScript ecosystem:

It's ideal for applications that need structured, reusable templates with clear data flow, without the complexity of virtual DOM frameworks.

Advantages

Learn more about the advantages →

Disadvantages

Template-M excels at structured, declarative rendering but isn't designed for highly interactive, reactive applications that major frameworks target.

Get Started

Ready to try Template-M? Check out our documentation: