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.

Some mail filters hold or remove HTML attachments. On a desktop it may open in a code editor instead of a browser. On a phone it may open only as a basic preview.

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 share 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 many 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 can get filtered, open in the wrong program on a desktop, and may show only as a basic preview on a phone.

Keep reading

Build a simple HTML todo listA working todo list in one HTML file: add, complete, delete and keep items after a reload. FA free HTML clock widget you can paste anywhereCopy-paste code for a live clock, a timezone board and a countdown. No account, no third-parSelf-contained HTML file: one file that works anywhereA self-contained HTML file carries its styles, scripts and small images inside itself and poCool things to do with HTMLTwelve things plain HTML does without a framework, from native dialogs and collapsible sectiHTML nested collapsible sectionsBuild nested collapsible sections with details and summary, keep deep links working, and stoHTML open in new tabtarget="_blank" opens a link in a new tab. Why rel="noopener noreferrer" belongs with it, whHow to share a novel as a linkShare a novel as a link so beta readers reach a chapter directly and remember where they stoSvelteKit 3 and single HTML filesSvelteKit 3 is still a prerelease, and SvelteKit needs a build either way. What does run in Streamlit and HTML: from a Python app to one file you can shareStreamlit apps need a running Python server. Two ways to get one HTML file instead, live exahtmx in a single HTML filehtmx adds requests and page updates to HTML through attributes. A working single-file examplPWA in HTML: from one file to an installable appWhat a PWA is, what one HTML file can and cannot do, and the manifest and service worker youVue in a single HTML fileRun Vue 3 from a single HTML file with one script tag and no build step. A live example to eAlpine.js in a single HTML fileAlpine.js adds state and behaviour to plain HTML with attributes like x-data and @click. A wPreact in one HTML file: a score keeper you can shareBuild a Preact score counter and leaderboard in a single HTML file with no build step: imporTauri and HTML: one file, a browser, then a desktop appTauri turns a folder of HTML, CSS and JavaScript into a desktop app. Build the page as one HCodeSandbox HTML: put the whole project in one fileTurn a CodeSandbox HTML project into one file that runs anywhere: the smallest working exampHow to use Ionic in a single HTML fileUse Ionic Framework in a plain HTML file with two CDN tags and no build step. Live examples,Capacitor with a single HTML fileWhat Capacitor does with an HTML file, a working single-file page you can try here, the comm