Skip to content

Runjucks

Fast, Jinja-flavored templates for Node — the Nunjucks-style API you already know, with rendering in Rust instead of compiling templates to JavaScript. Strong fit for sync servers and CLIs; CPU-heavy templates benefit most.
{% extends "base.njk" %}
{% block title %}{{ page.title | upper }}{% endblock %}
{% block body %}
<ul>
{% for id, item in items %}
<li>{{ id }}: {{ item.label }}</li>
{% endfor %}
</ul>
{% endblock %}

For the full language and Node API, see the guides below.

Leaving Nunjucks npm?

Same patterns: renderString, Environment, configure, compile, loaders via setTemplateMap / setLoaderRoot, optional Express helper. Follow the migration guide for a precise “drop-in” boundary (sync Node only — no async tags or precompile yet).

Jinja2-shaped & fast

Familiar filters, inheritance, and macros — see Jinja2 background. The core is Rust with parse caching; Performance includes a versioned vs-Nunjucks snapshot for the published npm package.

Rust-powered engine

No compile-to-JavaScript step or eval on the hot path. Custom delimiters, trim markers, and whitespace options match Nunjucks-oriented behavior.

TypeScript

Types ship with the package (index.d.ts). The Node API reference is generated on build.

Tested vs Nunjucks

Golden fixtures and parity.test.mjs vs the nunjucks npm package reduce regressions. Contributor workflow: Development.

Template language: control flow (if, for, switch), set, include, extends, block, import / from, macro, call / caller, filter blocks, raw / verbatim, and rich {{ }} expressions with filters and is tests — see Template language.

Node API: environment options (autoescape, throwOnUndefined, trimBlocks, lstripBlocks, custom delimiters), in-memory template maps, custom filters, tests, tag extensions, and globals — see JavaScript API and Limitations.