Getting started
temples renders data into plain HTML. A template is a normal HTML fragment decorated with a few
data-* attributes. Nothing else: no framework, no build step, no non-HTML syntax.
Install
Pick the packages you need. All of them depend on @temples/engine.
| Package | Install | Use it for |
|---|---|---|
@temples/engine | bun add @temples/engine | Direct rendering in the browser. |
@temples/components | bun add @temples/components | Declarative Web Components. |
@temples/ssr | bun add @temples/ssr | Server-side rendering and static site generation. |
@temples/jquery | bun add @temples/jquery jquery | jQuery pages (jQuery is a peer dependency). |
Your first template
Write the markup you would write anyway, with sample content inside. Add one data-bind
attribute per bound element:
<div id="logged-user">
<img data-bind="src=user.avatar" src="http://avatar.com/default.png" />
<div data-bind="user.fullname" class="active">John DOE</div>
</div>
The sample content stays visible before any data arrives — designers work on real pages, and the bindings never break their markup.
Build a Renderer from the template and render a data dictionary into it. The source is an
element id, a DOM element, or an HTML string:
import { Renderer } from "@temples/engine";
const renderer = new Renderer("#logged-user");
renderer.render({
user: {
avatar: "http://avatar.com/johndoe",
fullname: "John DOE",
},
});
A string starting with # names an element already in the page: the renderer binds it in place,
so every render writes into the live DOM. An unknown id throws a clear error. The other forms
bind a detached element or a freshly parsed fragment:
const fromElement = new Renderer(document.getElementById("logged-user"));
const fromString = new Renderer("<h1 data-bind='article.title'>Title</h1>");
The binding paths (user.avatar, user.fullname) resolve against the data dictionary you pass.
See Data-binding syntax for the complete reference.
Partial updates
render(data) touches only the paths present in the data. Absent paths keep their current state.
To change one value in real time, update(path, value) re-renders only the bindings bound to
that exact path:
renderer.update("user.fullname", "Jane DOE");
This is what makes temples suitable for live updates: a websocket message that carries one value re-renders one binding, not the page.
Serialize to HTML
On the server, pair the engine with @temples/ssr: prepare(source) returns an async render
function whose result is the rendered HTML string.
import { prepare } from "@temples/ssr";
const render = prepare("<h1 data-bind='article.title'>Title</h1>");
const html = await render({ article: { title: "The Great Race" } });
console.log(html); // <h1>The Great Race</h1>
See SSR and static site generation for prepare(), full-page rendering, and
component rendering.
Next steps
- Data-binding syntax —
data-bind,data-iterate, and the conditional bindings. - Components — declarative Web Components with reactive state.
- API reference — every public class, method, and type.