A DOM-based JavaScript templating library that treats templates as functions and JSON as function applications
Get StartedTemplate-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:
data-fn attributes in HTMLtemplate property specifies which function to applydata-tme for element replacement (> for children, < for the element itself) and data-tma for attributesThis 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.
Template-M supports two distinct modes for different use cases:
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.
templateM(templateId, data, targetElementId) functiondata-fntemplate propertyDemo 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.
data-tmd-view attributes to mark nodes in a DOM treeUse Render Mode when:
Use Demo Mode when:
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:
data-fn attributes do get rendered, so their placement matters for visual presentationThis 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.
<!-- 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>.
Works directly with the DOM, creating DocumentFragments instead of string manipulation.
Templates are composable functions defined with data-fn, enabling powerful abstraction.
Data attributes (data-fn, data-tme, data-tma) declare behavior directly in HTML.
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"}
]
}
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"}
}
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).
Set attributes, toggle classes, and attach handlers:
<input data-tma="$placeholder:placeholder;$isValid:.valid">
<button data-tma="handleClick($id, $name):onclick">Click</button>
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.
Template-M excels at structured, declarative rendering but isn't designed for highly interactive, reactive applications that major frameworks target.
Ready to try Template-M? Check out our documentation: