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

@funcstache/funcstache

v0.1.19

Published

A JavaScript library to render mustache templates into documents. For example, webpages that are dynamically generated on a server.

Readme

funcstache

A JavaScript library to render Mustache templates into documents. For example, webpages that are dynamically generated on a server.

  • File-based routing.
  • Stream-based to deliver a rendered document as quickly as possible.
  • Defined interfaces and conventions that simplify document rendering.

The proven pattern of rendered templates, combined with modern JavaScript capabilities, plus some conventions, to simplify rendering documents dynamically.

Contents

Usage

You'll need to create an instance of a Renderer to do the work of creating web pages. First create the options to pass to the Renderer.

const options: WebRendererOptions<ModuleState> = {
  indexDirectory,
  moduleState,
  path: requestUrl.pathname,
  rootDirectory,
};

Then create an instance of the Renderer.

const renderer = new Renderer(options);

renderer
  .render(Writable.toWeb(stream))
  .then(() => {
    stream.end();
  })
  .catch((err) => {
    stream.end();
  });

You may notice the stream argument of renderer.render(Writable.toWeb(stream)) and be wondering where stream comes from; it's the destination stream where the rendered template output will be written (note that this is a web WritableStream - not NodeJs's native WritableStream). This stream comes from the surrounding environment. For example, in KOA this is the value of context.body. If using a framework look for documentation that describes how to return a stream in the response.

See the apps in the repo for more examples of how to create an instance of a Renderer.

File-based routing

funcstache uses two different files to render a document:

  • A JavaScript file - known as a module file - that:
    • must return a path to the Mustache file to be rendered
    • optionally returns context information to be used when rendering the document
  • A Mustache template file that defines the document to be rendered.

[!NOTE] The module file could also be a TypeScript file if you are using Deno or some other runtime that supports TypeScript. The module file extension is set separately in the RendererOptions options.

Here's a simple example of an index and Mustache file inside a directory named "root."

root/
├── index.js
└── main.mustache

The module file

[!NOTE] The example code is written in TypeScript to illustrate the interfaces and types available to developers.

The module file (index.js) implements the FuncStacheModule interface, defining the Mustache template to render and the context associated with that template to be used during the rendering process.

context returns an object whose keys will be matched to Tag keys in the Mustache template and the value will replace the tag. The type of a context property value varies depending on the tag type. See stache-stream documentation.

The template function returns information about the template to be rendered either:

  • a string that is the name of the template - without a file extension - the name must refer to a file with the same name in the same directory as the module file
  • a tuple with two elements: first the name of the template file and second a path to the directory where the template file is located; the path is relative to the location of the module file.
/*
root/index.ts
*/
import { type FuncStacheModule } from "@funcstache/funcstache";

export const { context, template }: FuncStacheModule<ModuleState> = {
  context: async (options: Options<ModuleState> | WebOptions<ModuleState>): Promise<Record<string, ContextTypes>> => ({
    title: "Hello World",
  }),

  template: async (options: Options<ModuleState> | WebOptions<ModuleState>): Promise<TemplateName> => ["layout", "./layouts/default/layout"],
};

Mustache template

Mustache templates are text files with optional tags that follow the rules defined by the Mustache standards.

<!--
root/main.mustache
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>{{title}}</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
  </head>

  <body>
    <p>Hello funcstache!</p>
  </body>
</html>

Notice that this template has one variable tag {{title}} that will be replaced by context data.

Rendering the document

When created a Renderer instance is passed a fully-qualified path to a file system directory, this is known as the "root directory." funcstache will be able to traverse all the directories and files under the root. The root directory must contain a module file (index.js). funcstache will read the module file to determine which template to render at the root.

After the Renderer is created invoke the asynchronous render function to begin transforming a Mustache file and writing the output to the provided stream.

import { Renderer } from "@funcstache/funcstache";

const options: WebRendererOptions<ModuleState> = {
  indexDirectory: ".",
  moduleState: {},
  path: "/",
  rootDirectory: "/home/user/funcstache/root"
};

const renderer = new Renderer(options);

renderer
  .render(Writable.toWeb(stream))
  .then(() => {
    stream.end();
  })
  .catch((err) => {
    stream.end();
  });

After the files are processed, and a rendered document created, the contents of stream will be an HTML document with the {{title}} tag replaced with the value of context's title property - "Hello World".

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
  </head>

  <body>
    <p>Hello funcstache!</p>
  </body>
</html>

Using these basic building blocks you can create complex templates composed of smaller individual - partial - templates.

Develop

Install

npm i @funcstache/funcstache

Logging

Logging can be set by adding an environment variable named LOG_LEVEL. The following values are supported: "debug", "log", "warn", "error".