npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rhinostone/swig

v2.4.3

Published

A simple, powerful, and extendable templating engine for node.js and browsers, similar to Django, Jinja2, and Twig.

Readme

Swig

CI NPM version NPM Downloads Socket Badge

Multi-flavor template engine for Node.js and browsers — native Swig syntax (Jinja2/Django-inspired) and Twig syntax via dedicated frontends sharing one IR backend. gina-io/swig started as a maintained continuation of the abandoned paularmstrong/swig (last released 2014) and is now a standalone project. Security and bug fixes ship here.

Part of the Gina ecosystem. This is the built-in template engine for Gina (npm), a Node.js MVC framework with HTTP/2, multi-bundle architecture, and scope-based data isolation.

Swig is a Jinja2/Django-inspired template engine for node.js and browsers. The syntax will feel familiar to Jinja2 and Django users, but Swig is not drop-in compatible with either — porting templates from an existing project requires a handful of changes. See the Migration Guide for the full parity list and workaround patterns.

Coming from Twig? Install @rhinostone/swig-twig instead — a dedicated Twig-syntax frontend with closer parity than working around incompatibilities here.

Workspace packages

| Package | Description | When to use | | --- | --- | --- | | @rhinostone/swig | Native Swig syntax (Jinja2/Django-inspired). Drop-in for @rhinostone/[email protected] consumers. | Upgrading from @rhinostone/[email protected], or starting fresh with Swig syntax. | | @rhinostone/swig-twig | Twig-syntax frontend with closer Twig parity. | Migrating from PHP Twig, or writing new templates in Twig syntax. | | @rhinostone/swig-core | Shared IR, backend, and runtime primitives. | Building a custom flavor frontend. Otherwise pulled in transitively. |

Each frontend pins the matching @rhinostone/swig-core version exactly during the alpha cycle — the IR is not stable across alpha minors. From 2.0.0 stable onward, frontends and the core release in lockstep.

Features

  • Available for node.js and major web browsers.
  • Express compatible.
  • Object-Oriented template inheritance.
  • Apply filters and transformations to output in your templates.
  • Hardened against prototype-pollution__proto__ / constructor / prototype blocked at parser, tag-side, and IR-emission layers. CVE-2023-25345 fully patched. 9 regression cases under tests/regressions.test.js.
  • Automatically escapes all variable output (HTML by default; configurable per-call).
  • Lots of iteration and conditionals supported.
  • Robust without the bloat.
  • Extendable and customizable — register custom filters, tags, and loaders per-instance.

Benchmarks

benchmarks/render.js measures sync-render throughput across five workload shapes against Nunjucks.

cd benchmarks && npm install && node render.js

In production-typical settings (autoescape on), @rhinostone/swig outperforms Nunjucks on iteration-heavy templates by 2–3.5× and ties on simple control flow. See benchmarks/README.md for the methodology, the full result table, and how to reproduce on your own hardware.

Need Help? Have Questions? Comments?

  • File an issue at gina-io/swig/issues.
  • Swig v0.x → v1.x migration notes — the original upstream wiki has been deleted; see HISTORY.md entries around v1.0.0 for the individual breaking changes. For porting from Jinja2 or Django into Swig, see the Migration Guide.

Installation

npm install @rhinostone/swig

For Twig syntax:

npm install @rhinostone/swig-twig

Documentation

User-facing documentation lives in the Gina Docusaurus site under the Swig Template Engine section, maintained in gina-io/docs at docs/swig/. The JSDoc blocks in lib/swig.js, lib/filters.js, lib/tags/, and lib/loaders/ remain the canonical source-of-truth for the public API and are mirrored into the Docusaurus pages.

Basic Example

Template code

<h1>{{ pagename|title }}</h1>
<ul>
{% for author in authors %}
    <li{% if loop.first %} class="first"{% endif %}>{{ author }}</li>
{% endfor %}
</ul>

node.js code

var swig  = require('@rhinostone/swig');
var template = swig.compileFile('/absolute/path/to/template.html');
var output = template({
    pagename: 'awesome people',
    authors: ['Paul', 'Jim', 'Jane']
});

Output

<h1>Awesome People</h1>
<ul>
    <li class="first">Paul</li>
    <li>Jim</li>
    <li>Jane</li>
</ul>

For working example see examples/basic.

Migrating from @rhinostone/[email protected]

@rhinostone/[email protected] is drop-in for 1.x consumersswig.compileFile, swig.renderFile, swig.setFilter, swig.setTag, and the rest of the public API are unchanged. The internal carve into @rhinostone/swig-core is transparent (test gate during the alpha cycle: byte-identical compiled output against the 1.x test suite).

2.0.0 also ships @rhinostone/swig-twig, a sibling Twig-syntax frontend. Switching is opt-in — your existing @rhinostone/swig install keeps working.

Migrating from Jinja2 or Django

Swig is inspired by Jinja2 and Django, not a drop-in replacement. Common pitfalls when porting existing templates:

  • No is / is not / not in operators — rewrite {% if x is defined %} as {% if x !== undefined %}, {% if x not in xs %} as {% if not (x in xs) %}.
  • Django forloop.counter → Swig loop.index (Swig follows Jinja2 loop-variable naming).
  • {{ super() }} / {{ block.super }}{% parent %} — Swig uses a dedicated tag inside the overriding block.
  • Django filter args use a colon (|date:"Y-m-d") — Swig uses parens (|date("Y-m-d")).
  • {% with x=1 %}{% set x = 1 %}, and no block-form {% set %}…{% endset %}.
  • No {% from "f" import x %} — use {% import "f" as ns %} + ns.x instead.
  • Method calls require parens — Django auto-invokes x.get_absolute_url; Swig needs x.get_absolute_url().
  • ~25 Jinja2 filters are absentdefault, truncate, tojson, round, int, float, map, select, batch, trim, etc. Register them via swig.setFilter(name, fn).

Full parity tables and workaround patterns: Migration Guide.

How it works

Swig reads template files and translates them into cached JavaScript functions. The pipeline is: parse → emit IR → lower IR to JS source → new Function(...). At render time, the compiled function runs against a context object to produce the output string.

In 2.x, frontend parsers (native Swig syntax in @rhinostone/swig, Twig syntax in @rhinostone/swig-twig) emit a shared intermediate representation. The backend in @rhinostone/swig-core lowers IR to JS. New flavors plug in at the frontend without touching the runtime.

License

MIT. Copyright (c) 2010-2016 Paul Armstrong and contributors, (c) 2026 Rhinostone. See LICENSE for the full text and AUTHORS for the contributor roster.