An HTML mockup is the cheapest artifact you will ever get to change. Before any real application code exists, build one self-contained interactive HTML file — a device frame, working tab navigation, overlay screens, populated with realistic fake data, styled from your already-finalized brand assets — and walk through every screen with your principal before writing a single line of the actual app. The rule that makes this worth doing: a UI change in this HTML file costs minutes; the same change after it's built in real app code costs an order of magnitude more — rebuild, recompile, sometimes a fresh native build. The mockup is where you spend that cost cheaply, on purpose, before it gets expensive. It sits between the visual identity you settled in How to Make a Brandbook and the technical specification you'll write next.
Where this sits in the sequence
Four documents, four different questions, each independently readable:
| Document | Answers | Link |
|---|---|---|
| Brief | Why, for whom, what's the business case | How to Write a Brief |
| Brandbook | What does it look like (identity) | How to Make a Brandbook |
| Mockup | What does it look like assembled, and how does it flow | this lesson |
| Spec | How is it actually built (data, logic, architecture) | How to Write a Spec |
The mockup is the first time the brief and the brandbook meet a real screen. That collision is the point.
Why this step exists at all
It's tempting to jump straight from brief to real code — you already know what you're building, so why write throwaway HTML first? The answer is the cost curve, not taste. A brief tells you what and why. It does not tell you, concretely, what happens when a user opens a Messages tab with zero conversations, or how a filter bar behaves when nothing matches, or whether a two-line listing title wraps into a third line and breaks a card's layout. Those are UI decisions, and UI decisions are exactly the ones a written brief systematically under-specifies — not because briefs are bad, but because some things are genuinely easier to see than to describe.
[Assumption, ours] The exact multiplier between "change it in HTML" and "change it in built app code" varies by stack, but the direction never flips. Treat "much cheaper before code exists" as the operating rule, not a specific number.
Build it as one self-contained file
The mockup should open directly in a browser with zero build step — one HTML file, CSS and JS inline, no bundler, no dependencies, no server. This isn't a shortcut taken because the mockup is unimportant; it's deliberate, because the entire point is removing friction between "I want to try a different layout" and "I can see it." The moment a mockup needs a build step, people stop iterating on it freely, and the tool stops doing its job.
Frame it at the actual target viewport — a real phone size (e.g. 393×852 for a modern phone), not an arbitrary browser window — so spacing and text-wrap decisions transfer directly to the real screen instead of needing rework once you're building for the device.
Structurally, one file is enough to hold a whole app:
<div class="device-frame"> <!-- fixed to target viewport -->
<main>
<section id="tab-browse" class="tab active">…</section>
<section id="tab-post" class="tab">…</section>
<section id="tab-messages" class="tab">…</section>
<section id="tab-profile" class="tab">…</section>
</main>
<nav class="tabbar">…four buttons…</nav>