Single HTML file apps

One file, no build step, no dependencies to install. It covers more than people expect, and it has three hard limits that decide when to stop.

Single HTML file apps are applications where the markup, the CSS and the JavaScript all sit inside one .html file, so there is nothing to install and nothing to build.

<!doctype html>
<html lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Unit converter</title>
<style> /* everything it looks like */ </style>
<body> <!-- everything it is --> </body>
<script> /* everything it does */ </script>
</html>

That is the entire architecture. Copy the file and you have copied the app, working, including on a machine with nothing installed.

A single .html file in a folder, open beside the running app it produces.
A single .html file in a folder, open beside the running app it produces.

What fits comfortably in one file

The category is wider than most people assume. All of these are routinely built this way:

  • Calculators and converters. Pricing, unit conversion, loan tables, dosage checks.
  • Dashboards over pasted data. A chart library from a CDN and an array of numbers.
  • Checklists and small trackers. A todo list with local storage.
  • Form builders and previewers. Type on the left, rendered result on the right.
  • Internal reference pages. Searchable tables, on-call rotas, a clock board for a distributed team.
  • Report pages. Numbers, a chart, and the commentary that explains them.

The common thread is that the data is small and the state belongs to one reader.

The three hard limits

Limit Why What to do instead
No secrets The source is readable by anyone who opens it Never put an API key in the file
No shared state Storage is per browser, per device Put shared data in a document or a service
No bundler npm packages that assume a build step will not load Use the library's browser build from a CDN

The first is the one that causes real damage. A key pasted into a single file app is public the moment the page is shared, and viewing source is not a hack.

The second surprises people building trackers. Your ticks are in your browser. The reader's browser starts empty. That is correct for a personal tool and wrong for a team one.

Keeping it readable

The file has no module system, so structure has to come from discipline.

  1. One <style> block near the top, one <script> block at the bottom. Scattered inline styles are what makes a single file unmaintainable.
  2. Keep state in one object or array. Read from it, write to it, render from it.
  3. Redraw fully after every change. At this size a full redraw is faster to reason about than selective updates.
  4. Name the file with a version. pricing-v3.html beats three copies called pricing (2).html.
  5. Put a <title> in. It is the browser tab, and it is the preview card when the page is shared.

Past roughly three hundred lines of script, ask whether this is still the right shape. The answer is often yes, but it should be a decision rather than a default.

The source of a single file app, showing the style block, the markup and the script block in order.
The source of a single file app, showing the style block, the markup and the script block in order.

Loading a library without a build step

Most well known libraries publish a browser build. One script tag is enough:

<script src="https://cdn.example.com/chart/dist/chart.umd.js"></script>

That keeps the file small, but it also means the page needs a network connection and that address has to keep working. For something meant to survive offline, paste the library source into the file instead, and accept the size.

Two related warnings. If your page is on https and the library address is http, the browser blocks it as mixed content. And a content security policy on the host can block inline scripts entirely.

Single file against a project

Single file A project with a build
Time to first working version Minutes Hours
Install needed to run it None Node and dependencies
Multiple screens and routes Awkward Designed for it
Tests and code review Possible, unusual Normal
Handing it to a colleague Send a link Send a repository and instructions
Lifespan without maintenance Years Until a dependency breaks

The last row is underrated. A single file written three years ago still opens. A project of the same age often needs an afternoon before it will run at all.

Getting it in front of people

This is where single file apps usually fail, and it has nothing to do with the code.

Sending the .html file has three separate failure modes, and any one of them is enough.

Mail gateways strip HTML attachments, because a file with a form and a script looks exactly like a phishing page. On a desktop it may open in a code editor instead of a browser. On a phone it cannot really be opened at all.

Paste the file into a NOS document instead. It renders and runs as written, scripts included, at an address of its own. Then Share, Share link, Create link, and send one line.

A single file app running from a shared link on a phone browser.
A single file app running from a shared link on a phone browser.

The address does not move when the content does, so fixing a rate in the calculator next month does not mean resending anything. Turning HTML into a link is that step alone, and static host against a document compares it with uploading the file somewhere.

Before you call it done

  • Does it open in a window that has never seen your folder? Test in the HTML file opener.
  • Are images embedded rather than sitting in a sibling folder? Self-contained HTML covers this.
  • Is there any credential in the source? Remove it, and rotate it.
  • Is there a viewport meta tag, since most readers will be on a phone?
  • Does the state belong to one person, and is that what you intended?

Questions people ask

What is a single HTML file app?

An application where the markup, the styles and the script all live inside one .html file. There is no build step and no folder of assets. You open it by double-clicking, and you move it by copying one file.

What can a single file app not do?

Three things. It cannot keep a secret, because anyone can read the source. It cannot share state between people without a server somewhere. And it cannot use an npm package that expects a bundler, though most libraries ship a browser build you can load directly.

How big can a single HTML file get before it is a problem?

The practical limit is readability rather than bytes. Past a few hundred lines of script it becomes hard to hold in your head, and embedded images inflate the file quickly since base64 adds about a third. If you are scrolling to find things, split it.

How do I let other people use a single file app?

Send an address, not the file. Paste the HTML into a NOS document and share the link. Emailed .html files get filtered, open in the wrong program on a desktop, and are effectively unopenable on a phone.

Keep reading