🇵🇸 Donate eSIMs to Gaza 🇵🇸

Higgledy-Piggledy Static Site Templating

A screenshot of template string substitution code that reads: const page = pageTemplate.replace('#NAV', navTemplate).replace('#HEAD', headTemplate).replace('#FOOTER', footerTemplate);
A simple way to build a static site

A friend recently asked me how they should do templating for their new static website.

Their website is small, only a handful of HTML pages, which don’t need to be updated regularly.

They wanted something that let them, say, have a nav bar on every website page, but keep the HTML code for it in a single file, so they only have to change it in one place. Their website is small, only a handlful of HTML pages, and they don’t need to update it very frequently, but when they do update it they want it to be as frictionless as possible.

They’d done some Googling, which recommended PHP, but they didn’t want to have to learn a whole new language for what seemed like a simple thing.

PHP is a valid option. It’s been making solid websites for decades and is still used in lots of places you wouldn’t expect.

Then there’s all the static site generators, like 11ty or Hugo. I know plenty of people who use these and really like them, but they definitely have a learning curve, and come with a bunch of dependencies.

So, what should they do?


My advice is to just use simple string substitutions.

Have a nav.html file that contains the snippet for the nav bar, and then have a placeholder string (like #NAV) in your page files.

To build your website, just replace #NAV with the contents of your nav.html file.

Here’s some example HTML files:

<nav>
    <ol>
        <li><a href="/">Home</a></li>
        <li><a href="/about/">About</a></li>
        <!-- etc -->
    </ol>
</nav>
<html>
    <body>
        <header>
            #NAV
        </header>
        <main>
            some content about me
        </main>
    </body>
</html>

And here’s some example NodeJS code to do the substitution:

const fs = require('fs');

// some directory that your static site will get built to
const OUT_DIR = '/path/to/out/dir'

// readFileSync reads the contents of the file into the variable
const navTemplate = fs.readFileSync('/path/to/nav.html', 'utf8');

function buildPage(htmlPath, pageName) {
    const pageTemplate = fs.readFileSync(htmlPath, 'utf8');

    // this does the replacing of #NAV in about.html
    const page = pageTemplate.replace('#NAV', navTemplate);

    // this writes the filled-in HTML file to the out directory
    const outPath = path.join(outPath, pageName+'.html');
    fs.writeFileSync(outPath, page);
}

buildPage('/path/to/about.html', 'about');
buildPage('/path/to/home.html', 'index');
// etc

At the end of this you’ll have a file called /path/to/out/dir/about.html that looks like:

<html>
    <body>
        <header>
            <nav>
                <ol>
                    <li><a href="/">Home</a></li>
                    <li><a href="/about/">About</a></li>
                </ol>
            </nav>
        </header>
        <main>
            some content about me
        </main>
    </body>
</html>

You want to add a new page? Just copy an existing html file and add a new call to buildPage in the JS code.

Want to templatize something else, like a <head> block maybe? Just add more .replace calls to the buildPage function:

const page = pageTemplate
    .replace('#NAV', navTemplate)
    .replace('#HEAD', headTemplate)
    .replace('#FOOTER', footerTemplate);

It’s simple, there’s no dependencies other than your programming language (and you really could use any language, including Bash or PHP), and you completely understand and control how it works.

Over time, as my friend adds more and more to their website, they might find that this does start to get unwieldy. They’ve bolted on too many features, added a markdown compiler somewhere along the way, have too many special case functions for weird corners of their website (ahem /kleks).

The tech debt has come a calling, and it’s time for a refactor or a rewrite. But at this point, they’ll have a solid understanding of what the needs of their website are, and can choose a solution accordingly.

Maybe that’ll be PHP or 11ty, or maybe they’ll just add some abstractions into their static site builder that better suit the shape of their website.

But, I think you’d be surprised at how far simple higgledy-piggledy string substitution can get them!