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

forge-templates

v1.3.1

Published

A package for rendering dynamic HTML templates with embedded server-side JavaScript without using eval.

Readme

Forge Templates

Forge Templates is package for rendering dynamic HTML templates with embedded server-side JavaScript. The templates fully support JavaScript by being embedded into a script at build time. You build the templates into a script with the forge-templates CLI or using ForgeTemplates.build(....) in your own build script.

Features

  • Full JavaScript support in the templates, without using eval, new Function or similar functions
  • Template inheritance, a template can extend a base template and replace its defined content blocks (see Template Inheritance)
  • Helper functions make it easy to render an array of data, or execute arbitrary JavaScript in a template (see Helper Functions)
  • Building can be done with the CLI, or programmatically with the JavaScript API (see Building the Templates)
  • After building, it requires no Node.js or Web APIs, so it's compatible with all execution environments

Sections

Example

Template file: src/templates/names.tmpl.html

<html lang="en">
    <head>
        <title>${data.title}</title>
    </head>
    <body>
        <h1>${data.title}</h1>
        <p>${data.description}</p>
        <ul>
            ${forEach(data.names, (name, index) => `
                <li>Name ${index}: ${name}</li>
            `)}
        </ul>
    </body>
</html>

Build the templates: CLI

forge-templates src/templates build/forge-build.js --minify-html

Rendering: index.js

import { renderTemplate } from "build/forge-build.js";

const renderedHTML = renderTemplate("names", {
    title: "The Names",
    description: "This page contains a dynamically generated list of names!",
    names: ["Mary", "John", "Kath", "George"]
});

console.log(renderedHTML);

/* Output:

<html lang="en">
    <head>
        <title>The Names</title>
    </head>
    <body>
        <h1>The Names</h1>
        <p>This page contains a dynamically generated list of names!</p>
        <ul>
            <li>Name 0: Mary</li>
            <li>Name 1: John</li>
            <li>Name 2: Kath</li>
            <li>Name 3: George</li>
        </ul>
    </body>
</html>

(Whitespace has been manually added for readability)
*/

Template Format

A template is normal HTML, but with embedded JavaScript that lives in ${}, in the same way that template literals work in JavaScript. A template is required to have .tmpl.html as file extension. Normal .html files will not be recognised as templates during the build stage.

Passing Data

In a template there is a global variable data exposed. This is exactly what you pass in the renderTemplate("<name>", data) function. In general, a simple object with strings or other basic data types is recommended, however, this is not strictly enforced.

Template Inheritance

It is not uncommon to have shared elements between pages, for example a navbar or footer. This is easily done by extending a base template. A key element to understand inheritance are content blocks. A content block starts with a name and ends at the end tag. The start of a block has the format ${"{{ <NAME> }}"} where <NAME> is the name of the content block. The end tag of a content block is ${"{{ end }}"}. Whitespace between the tag identifiers is optional. An example of a base template with content blocks is below.

base-template.tmpl.html

<html lang="en">
    <head>
        ${"{{ html_head }}"}${"{{ end }}"}
    </head>

    <body>
        ${"{{ body }}"}
        <p>This will be removed if a template extends this one and overrides the "body" content block</p>
        ${"{{ end }}"}
    </body>
</html>

To extend this template you add ${"{{ extend <NAME> }}"}. The template above may be extended like so.

contact.tmpl.html

${"{{ extend base-template }}"}


${"{{ html_head }}"}
<link rel="stylesheet" href="/assets/contact.css">
${"{{ end }}"}

${"{{ body }}"}
<p>Contact us at [email protected]</p>
${"{{ end }}"}

Rendering the contact template would result into the following output.

<html lang="en">
    <head>
        <link rel="stylesheet" href="/assets/contact.css">
    </head>

    <body>
        <p>Contact us at [email protected]</p>
    </body>
</html>

Helper Functions

There are a few helpful utility functions available in templates. They are quickly explained below. The implementation of these functions can be found in src/output/html-template/helper-functions.js.


forEach(array: any[], callback: Function): string

This function loops through the given array and executes the given callback for every item. The callback is called with three parameters, the item, index of the item, and the array itself.

<ul>
    ${forEach(data.someArray, (itemOfArray, index, theArray) => `
        <li>The item is: ${itemOfArray}</li>
    `)}
</ul>

renderIf(condition: boolean, body1: string, body2?: string): string

This is a simple shortcut to have content rendered or not based on a condition. It is an if-statement. It renders body1 if the condition is true, it renders body2 if the condition is false. The body2 is optional, you don't have to provide it.

<div>
    ${renderIf(data.success, `
        <p>It was all successful</p>
    `, `
        <p>There was an error</p>
    `)}
</div>

execute(func: Function): string

execute is a function designed to allow for arbitrary JavaScript execution in the template. The given callback is executed during rendering and the given echo function in the callback can be used to have HTML output.

<ul>
    ${execute(echo => {
        for(let i = 0; i < 5; i++) {
            echo(`<li>Random number ${i+1}: ${Math.random()}</li>`);
        }

        // If the callback returns a string, it will also be rendered in the HTML (optional)
        return `<li>This is the end of the list!</li>`
    })}
</ul>

Building the Templates

To be able to access the renderTemplate function, you have to build the templates into a single script. There are two ways you can build the templates. You can either use the CLI or the JavaScript API.

Command Line Interface (CLI)

Building the templates through the CLI is easy. After installing this package, the forge-templates should automatically be available in your terminal. Use the CLI as follows.

Usage: forge-templates <folder> <file> [options...]
Parameters:
    folder            The folder with your template files
    file              Location to save the built script to, a JavaScript file
Options:
    --minify-html     Enables a basic HTML minifier to make the output script smaller
    --only-errors     CLI only; Print errors but don't print success messages

JavaScript API

To assist with more automated ways of building the templates, you can also build by calling a function in JavaScript. An example of this is below.

import ForgeTemplates from "forge-templates";

// Options are optional
const options = {
    minify_html: true
}
ForgeTemplates.build("<folder>", "<file>", options);