#hashJS

One template language, on the server and in the browser

«Plain and powerful JavaScript Syntax»

Get started Examples Github
A hashJS template beside the page it renders

Syntax you already know

#if(x) {# compiles to if (x) {. There is no second language to learn, no directives to memorise and no template dialect that behaves almost like JavaScript.

Server and browser

The same template renders the first response on a server and every update in the browser. One implementation, not two that have to be kept in step with each other.

Nothing in the way

A template compiles once into an ordinary function, which the engine then optimises like any other. No virtual DOM, no diffing pass, no build step.

11 kBone file, unminified
0dependencies
0build steps
MITlicence
In the browser
<div id="app">
    <h1>#title#</h1>
    <ul>
    #for(let item of items) {#
        <li>#item#</li>
    #}#
    </ul>
</div>

<script>
    const data = {
        title: 'Reading list',
        items: ['Dune', 'Solaris', 'Ubik']
    };

    const view = new hashJS("app");
    view.bind(data);
</script>
On a server — same template
const hashJS = require('./hashJS.js');

// Compile once at startup.
const list = hashJS.compile(`
    <h1>#title#</h1>
    <ul>
    #for(let item of items) {#
        <li>#htmlEncode(item)#</li>
    #}#
    </ul>`);

// Render per request.
app.get('/books', async (req, res) => {
    res.end(list({
        title: 'Reading list',
        items: await db.books.titles()
    }));
});

Nothing about the template changes when it moves between the two. See it running →

🚀 Getting started

Drop in one file. There is nothing to install and nothing to configure:

The same file works under require on a server: it exports through module.exports as well as to the global scope.

🔒 Writing templates safely

A template is compiled and executed, so the template itself is code — treat it exactly as you would treat a .js file.
Never build a template out of user input.
Concatenating submitted text into the template string lets that text run as JavaScript. This is the one thing the library cannot protect you from.
Rendering user data is fine.
Data is substituted, never executed. Wrap anything that came from a user in #htmlEncode(value)# so it lands as text rather than as markup.
One more thing worth knowing: templates are compiled with new Function, so a page served under a Content Security Policy needs script-src 'unsafe-eval'.