Dash and the browser’s missing piece

Building websites closer to the browser by only adding the missing pieces as you need them.


In this article

The Etch team recently attended Web Day Out in Brighton. The talks reinforced something we already believed – that we should lean into the browser to build websites that stay fast and work for everyone.

If you’re going to build for the web, build on the web and build with the web.

Harry Roberts

Inspired by the idea of getting back to the browser’s roots, I started making a website with no fancy tools or npm installs. I let myself be purposely naive and had fun sticking as close to the browser as possible. Creating a webpage is still as easy as creating a single file with a .html extension and opening it in a browser. It’s easy to forget that among today’s complex development tooling.

My website quickly needed a second page. This is where I hit the browser’s missing piece – there’s no way of including HTML from one page in another. It all has to be duplicated. The problem sounds trivial but it isn’t. It quickly becomes hard to keep consistent elements like headers, footers, and meta tags in sync across pages.

This is where an extra tool is needed to provide what the browser currently can’t, and there are plenty out there, from full frameworks to static site generators and small build tools.

Unfortunately, most of these abstract us away from HTML instead of sticking with it. From this point forward it’s as if the browser is deemed not good enough. Instead of adding a file with a .html extension we install something with npm and in many cases end up writing to JS files or an abstract templating language.

This all felt too complex and far removed from the humble HTML code I currently had. I wanted to stick with the browser, not abandon it. Given all the capabilities of modern browsers, moving away actually feels like a downgrade.

It turned out it doesn’t take much to build a solution to share HTML layout code between files.

Dash is a tiny Bun script with no dependencies. It takes a layout file and swaps out HTML comment placeholders with content from your page files.

A layout file looks like this:

html
<!DOCTYPE html>
<html lang="en">
<head>
  <title><!--- title ---></title>
</head>
<body>
  <header>...</header>
  <main><!--- content ---></main>
  <footer>...</footer>
</body>
</html>

The three-dash comments are valid HTML, so your pages still work in a browser without a build step. Dash simply replaces them with the matching content from each page.

An optional callback is available to add customisations to the build process and a serve command is included for local development, to help with serving the HTML files and stripping .html from the URL.

You can install it as a dependency, but the build script is under 90 lines of unminified code, you could just copy it locally and adjust it to fit.

Showing off Dash isn’t really why I’m writing this. Something similar probably already exists somewhere, and Dash is far from giving everything we might need. What would I do if I needed to integrate data from a CMS or loop out paginated articles? I don’t know because my website doesn’t need that yet. That’s the point – this is a different way of building, one that uses the browser first and builds in the missing pieces as we go, instead of trying to optimise for use cases that don’t exist and may never exist.

As all the talks at Web Day Out showed, modern browsers can do far more than ever before. Web components let us build reusable UI without a framework’s component model. CSS custom properties handle theming. Native dialogs, customisable select boxes and view transitions cover what used to require JavaScript libraries. The browser platform has quietly caught up, meanwhile frameworks have prevented making full use of it and typically produce a worse end result whilst locking us into a version treadmill.

Building the missing pieces as we go might sound less comfortable than the well-trodden framework path. But it brings us closer to the end result in the browser which in turn means fewer layers, fewer versions and fewer things that can go wrong.