This smaller version of the Quick Start counter explains how a template reaches the DOM. Start with a fixed zero. In src/main.ts, html describes the view:
// This view has no local setup, so html is enough.
const Counter = html`<main>
<h1>Counter</h1>
<output>0</output>
</main>`;
This view needs no state or component generator. To display it, render into document.body and supply the DOM renderer:
await render(Counter, document.body).pipe(
Fx.drainLayer,
Layer.provide(DomRenderTemplate),
Layer.launch,
Effect.runPromise,
);
Fx.drainLayer runs the render stream for the lifetime of the layer. Layer.launch keeps it running; Effect.runPromise starts it from JavaScript. Keep this launch at the application entrypoint.
Replace src/main.ts with the complete file below. Open Vite’s local URL: you should see Counter and 0, with no buttons yet.
Complete file
src/main.ts
import { Fx } from "@typed/fx";
import { DomRenderTemplate, html, render } from "@typed/template";
import { Effect, Layer } from "effect";
// This view has no local setup, so html is enough.
const Counter = html`<main>
<h1>Counter</h1>
<output>0</output>
</main>`;
await render(Counter, document.body).pipe(
Fx.drainLayer,
Layer.provide(DomRenderTemplate),
Layer.launch,
Effect.runPromise,
);
The Quick Start counter adds state to this render pipeline. See mounting DOM output for host ownership and teardown.