nunjucks
A powerful, Jinja2-inspired templating engine for JavaScript, with inheritance, autoescaping, and async control.
Repository Health
Technical Analysis
Nunjucks is a full-featured templating engine for JavaScript, built by Mozilla and heavily inspired by Python’s Jinja2. It compiles templates to JavaScript for fast repeated rendering and runs identically in Node.js and in the browser, making it a natural fit for teams porting Jinja2-style templates to a JS stack or wanting one templating syntax shared across server and client.
Beyond basic variable interpolation and loops, Nunjucks supports template inheritance (extends/block), macros, custom filters and tags, asynchronous control flow for filters and extensions that need to hit a database or API mid-render, and autoescaping to guard against XSS by default. A dedicated Express integration and a precompiler for shipping templates as plain JS (avoiding a runtime compile step and eval-like execution in the browser) round out the toolkit.
What You Get
- Template inheritance via
extends/blockand reusable macros - A configurable autoescaping engine to prevent XSS by default
- Asynchronous filters, tests, and extensions via a callback/waterfall-based async API
- Built-in loaders for the filesystem, the browser (via HTTP), and precompiled template bundles
- A
nunjucks-precompileCLI and precompiler API to ship templates as plain JS, skipping runtime compilation - First-class Express integration (
nunjucks.configure(app)) as a view engine - An optional Jinja2 compatibility layer (
installJinjaCompat()) for closer parity with Python templates
Common Use Cases
- Server-side HTML rendering in Express apps that want Jinja2-style templates instead of EJS/Pug syntax
- Sharing one templating syntax between a Python/Jinja2 backend and a JavaScript frontend or build pipeline
- Precompiling templates at build time and shipping them to the browser as static JS bundles for fast client-side rendering
- Generating emails, static site pages, or config/code files from data using inheritance and macros
Under The Hood
Architecture — Nunjucks follows a classic compile pipeline: lexer.js tokenizes template source, parser.js builds an AST of nodes.js node types, transformer.js performs AST transforms (e.g. hoisting async operations), and compiler.js (~1200 lines) walks the tree to emit a JavaScript rendering function as source text, which environment.js’s Template class then executes against a runtime (runtime.js) that provides context/frame variable lookups, autoescaping (markSafe/suppressValue), and error handling (handleError). Environment (extending an internal EmitterObj) owns the loader chain (FileSystemLoader, WebLoader, PrecompiledLoader from loaders.js), filter/test/global registries, and both sync and async render/renderString entry points; async rendering is driven by the a-sync-waterfall and asap packages so callback-based async filters and extensions compose correctly with the compiled template code.
Tech Stack — Pure JavaScript (93% of the codebase) with a small set of runtime dependencies: a-sync-waterfall and asap for async control flow, and commander for the nunjucks-precompile CLI (bin/precompile). chokidar is an optional peer dependency used only for filesystem template watching. The build uses Babel (@babel/preset-env targeting old browsers down to IE9 and Node 6) plus a custom Webpack bundling script (scripts/bundle.js) to produce the browser bundle declared in package.json’s browser field, reflecting the library’s dual Node/browser design goal.
Code Quality — The test suite is substantial (~6,500 lines across tests/api.js, compiler.js, parser.js, lexer.js, runtime.js, filters.js, loader.js, express.js, jinja-compat.js, and others, run with Mocha and instrumented with nyc/Istanbul for coverage), and includes 29 template fixture files for integration-style rendering tests. Code style is enforced via ESLint (eslint.config.js with the Airbnb extended config). Error handling is centralized through a TemplateError/handleError mechanism in runtime.js/lib.js that attaches line/column info to compile and render errors, which is a deliberate ergonomics choice for debugging templates.
API Design — The public surface is intentionally small and Jinja2-familiar: nunjucks.configure(), .render(), .renderString(), .compile(), plus addFilter/addGlobal/addExtension for customization, so developers coming from Jinja2/Django templates can be productive with almost no new concepts. The optional installJinjaCompat() compatibility shim and the precompiler’s parallel sync/async APIs add some surface-area complexity, but the common path (configure a loader, call render) requires very little boilerplate.
Used by 4 apps in this directory
GrowthBook
Developer Tools · Analytics · Monitoring
Open source feature flags, A/B testing, and warehouse-native experimentation that queries your existing data infrastructure—no data movement required.
Kimi Code CLI
AI Code Assistants · AI Agents · Developer Tools
A single-binary, terminal-native coding agent that reads, edits, and runs code end to end, built by Moonshot AI for Kimi models but pluggable with Anthropic, OpenAI, and Google providers too.
Lightdash
Analytics · Data Engineering
The open-source Looker alternative that turns your dbt project's metrics and dimensions into governed, self-serve charts and dashboards — no license key required.
Promptfoo
AI Development
An open-source CLI and library for evaluating and red-teaming LLM applications — replace trial-and-error prompt engineering with systematic evals, vulnerability scanning, and CI/CD integration.