One Template Engine for Server Edge and Browser

Compile Once, Render Anywhere
Portability matters more than features, and this engine compiles templates into safe output on any JavaScript runtime, zero deps.
One compile call parses the template, one render call fills it, and the result lands as a string or stream that works on Deno, Node, Bun, Workers, and the browser with no adapter because the engine uses only standard JavaScript primitives inside.
Templates carry variables, loops, conditionals, and layouts in one syntax, and the same compiled form renders to a string or stream. Moving from server to edge to browser changes nothing in the code, keeping the surface tiny and focused on the page.
Heavy or Locked
Most template engines fall into two camps. Either they are heavy frameworks pulling a dependency tree, or they bind to one runtime and break when moved. The gap was a tiny engine that treats safe HTML as the default and runs anywhere JavaScript runs.
Reading the landscape makes the gap obvious. Heavy engines pull a dependency tree that fights the runtime, while runtime-locked engines break when code moves from server to edge. Unsafe defaults leak user data, and streaming renders waiting for the full document raise time-to-first-byte. The choice was safe HTML by default, tiny enough to run anywhere JavaScript runs.

When Defaults Leak
- Heavy template engines pull a dependency tree that fights the runtime.
- Runtime-locked engines break the moment code moves to the edge or browser.
- Unsafe output defaults leak user data into the page without an explicit marker.
- Streaming renders that wait for the full document raise time-to-first-byte.
Safe HTML, Any Runtime
- Render templates to a string or a stream from the same pipeline.
- Escape user data by default and require an explicit marker for raw output.
- Compile once and reuse the compiled form across many renders.
- Run on any JavaScript runtime with zero third-party dependencies.
- Compose layouts, includes, conditionals, and loops in one syntax.
Tiny by Design
The strategy is safe by default and tiny by design. A sandboxed expression language evaluating variables, operators, and member access without arbitrary code keeps templates safe, while a compiler designed to prepare expressions once and reuse them keeps throughput high. Layouts, conditionals, and loops share a pipeline writing to a sink, returning a string or stream.
Tracing the flow shows how pieces fit. A sandboxed expression language evaluates variables, operators, and member access without arbitrary code, keeping templates safe. A compiler prepares expressions once and reuses them, keeping throughput high.
Layouts, conditionals, and loops share one sink-based pipeline. String and stream output stay aligned, first-byte time stays low.

Tokens, Nodes, Sinks
Every template compiles into a reusable form that renders again with different data. A tokenizer designed to split template text into tags, expressions, and HTML feeds a parser building a node tree, while a renderer designed to walk it writes escaped values and raw output to a sink. Streaming starts on the first chunk, so first-byte time stays low without waiting for it.
// Compile once, render many times with different data
const compiled = dve.compile('Hello {{ user?.name ?? "Guest" }}.')
dve.render(compiled, { user: { name: 'Ada' } })
// returns 'Hello Ada.'
Safety is not optional. User data is escaped by default, raw output requires an explicit marker, and the expression language has no access to globals or functions. The engine powers server apps, edge functions, static builds, and email templates.

Battle-Tested in Production
Note
Open source on GitHub at NeaByteLab/DVE. MIT licensed and installable from JSR, it ships zero dependencies and is battle-tested as the built-in view engine inside Deserve, powering HTML rendering across many production-grade internal projects.
| Feature | Delivered |
|---|---|
| Rendering | String and stream from one pipeline |
| Safety | Escape by default, raw output on explicit marker |
| Syntax | Variables, loops, conditionals, layouts, includes |
| Portability | Any JavaScript runtime with zero dependencies |
| Performance | Compile once, reuse across renders |
Sandboxing Paid Off
- Sandboxing the expression language removed an entire class of injection risk.
- Preparing expressions once kept render throughput high across reuses.
- One sink-based pipeline kept string and stream output aligned.
- Shipping zero dependencies kept the same code portable across runtimes.
Data Into Safe HTML
What began as a view engine inside another framework became a standalone library rendering safe HTML on any runtime. Templates, layouts, and streams share one pipeline, keeping the surface small and the loop from data to HTML short across projects.
The editor closes on an engine that earned its place here. One pipeline, safe HTML by default, zero dependencies in the bundle.
Server apps, edge functions, static builds, and email templates render through the same compiled form, keeping the surface small and consistent. Sandboxing removes an entire class of injection risk, escaping user data by default keeps pages safe, and the sink-based pipeline holds string and stream output on same path. Moving runtimes changes nothing in templates.