Overview

x(Component, props) is the primary composition primitive. Call it inside any html template to embed a child component. Mates registers the child with its scheduler — only the components whose reactive dependencies changed re-render, not the entire tree.

view() and template() are exact aliases of x() — same implementation, same runtime behaviour. Pick the name that reads most clearly in your codebase.

renderApp(Component, element) is the entry point. Call it once at application startup to mount the root component into a real DOM element. Optionally pass a third argument with initial props that will be forwarded to the root component's propsFn.

x() · view() · template() — identical aliases

Name
Identical to
Notes
x(C, props) primary Short, idiomatic. Preferred for templates with many embeddings.
view(C, props) alias of x() More readable in prose-heavy code; same runtime path.
template(C, props) alias of x() Useful when naming the abstraction 'template' is clearer.

Composing components

PostCard embeds Avatar using x(). Each x() call is handled by the scheduler — Mates re-renders only the parts of the tree whose reactive dependencies changed.

import { html, x, renderApp } from 'mates';

// Small presentational component — no local state
const Avatar = (propsFn) => () => html`
<div class="avatar-sm">${propsFn().initials}</div>
`;

// Composite component — embeds Avatar using x()
const PostCard = (propsFn) => () => html`
<div class="card card-body">
<div class="m-flex m-gap-sm m-b-10">
${x(Avatar, { initials: propsFn().initials })}
<div>
<div>${propsFn().author}</div>
<div class="hint">${propsFn().date}</div>
</div>
</div>
<p class="muted">${propsFn().content}</p>
</div>
`;

const App = () => () => html`
<div class="m-col m-gap-sm">
${x(PostCard, { author:'Alice', initials:'AL', date:'Just now',
content:'Nest x() calls to compose components inside templates.' })}
${x(PostCard, { author:'Bob', initials:'B', date:'2 min ago',
content:'No virtual DOM. No JSX. Pure closures.' })}
</div>
`;

renderApp(App, document.getElementById('app'));

x · view · template — identical

view() and template() are aliases of x(). Pick the name that reads clearest; runtime behaviour is identical.

import { html, x, view, template, renderApp } from 'mates';

const Chip = (propsFn) => () => html`
<span class="tag tag-soft">${propsFn().label}</span>
`;

const App = () => () => html`
<div class="m-flex m-flex-wrap m-gap-sm p-y-10">
${x(Chip, { label: 'x()' })}
${view(Chip, { label: 'view()' })}
${template(Chip, { label: 'template()' })}
</div>
`;

renderApp(App, document.getElementById('app'));

Lazy load via async x()

Pass an async loader to x() — Mates resolves it and mounts the component. See Lazy Components for resolveAsyncValue, isXViewTemplate, and Router usage.

import { html, x, renderApp } from 'mates';

const Feed = () => () => html`
<ul>
<li>Shipped Mates v2</li>
<li>Zero virtual DOM</li>
</ul>
`;

// Same shape as: async () => import('./Feed')
const loadFeed = async () => {
await new Promise((r) => setTimeout(r, 400));
return Feed;
};

const App = () => () => html`
<div class="card card-body">
<h3>My Feed</h3>
${x(loadFeed)}
</div>
`;

renderApp(App, document.getElementById('app'));