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

view-gate

v1.1.0

Published

An express js templating engine with clean syntax and support for builtin layout and all loops

Readme

View gate

Overview

This is a lightweight CommonJS template engine for Node.js/Express that supports:

  • <% %> JavaScript code blocks
  • {{ }} → Text and number output
  • {{{ }}} → Raw HTML output
  • include() → Partial templates
  • layout() → Layouts with nested templates
  • Global and per-render helpers
  • Template caching for performance

It is designed to be simple, flexible, and easy to integrate with Express.


Or include it locally in your project:

const { renderFile, registerHelper } = require("view-gate");

Features

1. JavaScript Code Blocks

Use <% %> to run arbitrary JavaScript in your templates:

<% for (let i = 0; i < items.length; i++) { %>
  <li>{{ i }} - {{ items[i] }}</li>
<% } %>

Supports:

  • for, while, do…while
  • if, else if, else
  • forEach, map
  • Any valid JavaScript code

2. Variable Interpolation

Escaped Output

  • Syntax: {{ expression }}
  • Automatically escapes HTML to prevent XSS attacks.
<p>User Name: {{ user.name }}</p>

Raw Output

  • Syntax: {{{ expression }}}
  • Inserts raw HTML without escaping.
<p>HTML Content: {{{ user.htmlContent }}}</p>

3. Layouts

You can wrap your template in a layout:

{{ layout("layouts/main", { title: "Homepage" }) }}
  • Layout files can contain {{ body }} or {{{ body }}} for inner template content.
  • Additional variables can be passed as the second argument.

Example layouts/main.html:

<!DOCTYPE html>
<html>
<head>
  <title>{{ title }}</title>
</head>
<body>
  {{{ body }}}
</body>
</html>

4. Includes (Partials)

Include partial templates with optional data:

{{ include("partials/header", { user }) }}
  • Paths are relative to the current template.
  • Variables can be passed as an object.

5. Helpers

Global Helpers

You can register helpers once, and they are available in all templates:

registerHelper("upper", str => String(str).toUpperCase());
registerHelper("lower", str => String(str).toLowerCase());
registerHelper("repeat", (str, n) => String(str).repeat(n));

Usage in templates:

<p>{{ upper(user.name) }}</p>
<p>{{ lower(user.name) }}</p>
<p>{{ repeat("-", 10) }}</p>

Per-render Helpers

You can also pass helpers per render:

res.render("home", {
  data,
  helpers: {
    shout: s => s.toUpperCase() + "!!!"
  }
});
  • Per-render helpers override global helpers if names collide.

6. Template Caching

  • Compiled templates are cached in memory for faster rendering.
  • The engine automatically reuses compiled functions for repeated renders.

API

renderFile(filePath, data, callback)

Render a template file.

renderFile(filePath, data, (err, html) => {
  if (err) throw err;
  console.log(html);
});
  • filePath → path to the template file
  • data → object containing variables and optionally helpers
  • callback(err, html) → receives the rendered HTML

registerHelper(name, fn)

Registers a global helper function.

registerHelper("upper", str => str.toUpperCase());

Express Integration

const express = require("express");
const path = require("path");
const { renderFile, registerHelper } = require("./templateEngine");

const app = express();

// Register the engine
app.engine("html", renderFile);
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "html");

// Global helpers
registerHelper("upper", s => String(s).toUpperCase());
registerHelper("lower", s => String(s).toLowerCase());

app.get("/", (req, res) => {
  res.render("home", {
    user: { name: "Felix", age: 21 },
    items: ["Apple", "Banana", "Orange"]
  });
});

app.listen(3000, () => console.log("Server running on http://localhost:3000"));

Example Template (views/home.html)

{{ layout("layouts/main", { title: "Homepage" }) }}

<h2>User Information</h2>
<p>Name (escaped): {{ user.name }}</p>
<p>Name (raw): {{{ user.name }}}</p>

<p>Uppercase (helper): {{ upper(user.name) }}</p>

<h3>Items List</h3>
<ul>
<% items.forEach((item, i) => { %>
  <li>{{ i }} - {{ item }} </li>
<% }) %>
</ul>

{{ include("partials/footer") }}

Notes & Best Practices

  1. HTML Escaping: Use {{ }} for user input to prevent XSS. Use raw versions only for trusted content.
  2. Helpers: Use global helpers for reusable functions. Per-render helpers are useful for one-off templates.
  3. Includes & Layouts: Paths are relative to the template file. Pass variables via objects.
  4. Caching: Templates are cached automatically; restarting the server reloads them.
  5. JS Blocks: Any valid JS code is allowed inside <% %> blocks. Use them for loops, conditionals, and variable manipulation.

Syntax Summary

| Feature | Syntax Examples | Description | | ------------------ | ------------------------------------------ | --------------------------------- | | Escaped Output | {{ name }} | HTML-escaped text | | Raw Output | {{{ htmlContent }}} | Raw HTML | | JS Code | <% for(let i=0;i<items.length;i++){ %> <li>{{ i }}<li> <%}%> | JS block for loops/conditions. The same concept in all kind of loops | | Include Partial. | {{ include("header") }} | Insert partial template | | Layout | {{ layout("main") }} | Apply layout wrapping | | Global Helpers | {{ upper(name) }} | Registered via registerHelper() | | Per-render Helpers | {{ shout(name) }} | Passed via helpers in render |