The launch issue carried "The Age of Install-less Apps". It drew the chain of what happens between a ten-minute edit and that edit reaching a user's screen — build, review, distribute, and then waiting for the user to press update.
The next issue carried "Why We Gave Up Compiling". It re-read the first link of that chain as a material process. The sentence compiling is the act of freezing every decision of that moment into one solid block was the best compression of an idea this magazine wrote in six months.
The two pieces were the front and back of one ridge. One asked what changes when the chain disappears, the other why it was there at all. So they each built the lineage, the three workarounds and the rebuttal exchanges — twice. We merge them here.
And merging leaves one more thing to fix. Both pieces talked about numbers without numbers.
"A screen definition is small. Not a heavy code bundle but a light specification — one button, one piece of text."
It said small without measuring how many bytes. It said "three days on one side and ten seconds on the other" without timing the ten seconds. There was nothing to measure back then. Now there is.
The ice — what compiling does
What to keep first. The passage reading compiling as a material process goes through untouched.
Making an app meant freezing every decision of that moment into one block. Where the button sits, what colour it is, what happens when it is pressed — those decisions set inside the device through compilation. Once set, not one character can change. To change it you freeze again, get reviewed again, distribute again, and wait for the user to accept it.
The pain of distribution was not laziness or old tooling. It was the necessity of a structure in which the decision called "the screen" is frozen inside the device.
A question stands up here — the one the original formalised. Can the capability and the ice really not be separated? Must you freeze in order to use native capability, or can you thaw only the screen layer and leave the capability layer frozen?
We spent six months actually building that. The answer first. They can be separated. And more has to stay frozen than we expected.
How small is a definition — measured
We start by paying back the original's weakest sentence. "A definition is small" had no number.
Now it can actually be measured. Everything below is a size taken from something running.
| What | Size |
|---|---|
ui://app handed over by an STM32H723 board (one page) | 656 B |
ui://app handed over by an ESP32 (an application with routes) | 158 B |
That application's first screen, ui://page/main | 1,894 B |
| A shop server's kiosk screen | 1,241 B |
| The same server's POS screen | 1,170 B |
| The same server's kitchen screen | 1,144 B |
| The whole unmanned-store bundle (4 JSON files) | about 6 KB |
One screen is one to two kilobytes. "Small" was right. It was just written without knowing whether it was, and now we know.
Once there are numbers, one thing the original could not say attaches. The shop server hands out three screens and the three together are 3,555 bytes. In the old way that is where you would have built a tablet app, a POS app and a kitchen app, had each reviewed, and distributed each. It is not that three apps were replaced by 3.5 kilobytes — it is that the reason for three apps went away.
(Measurements from: Attach It to One Chip and the Device Becomes a Terminal · Boards Hand Over Their Screens · A Folder of JSON Is the App)
How long does a ten-minute edit take — measured
The other end of the chain the original drew. If you do not freeze, does it really arrive immediately?
We edited the screen JSON of the unmanned-store app and ran it again. The log.
[+ 1415ms] edited ui/pages/main.json — 2940 B -> 2934 B, no compiler ran
[+ 1419ms] route "/" -> ui://pages/main ("Unmanned Store")
[+ 1498ms] captured 04_edited_json.png
Eighty-three milliseconds from edit to the screen showing it, and the compiler never ran. A route change was four milliseconds. Switching screens is a file lookup.
Where "ten seconds" was written, a real number now goes. And here something the original missed comes out — 83 milliseconds is not because there is no build, it is because there is no distribution. Even if the build dropped to a tenth of a second, with review and distribution and the user's acceptance still there, the chain is unchanged. What thaws is not compilation but the whole chain.
What still has to stay frozen
This is the best section of the two pieces, from "Why We Gave Up Compiling", and building it showed the section was right. Only, the original wrote that as prose too.
Real-time loops stay frozen. In the LCD panel sample the temperature control loop lives inside the C firmware.
/* First-order thermal: dT/dt = k·(target − T). Converges to target
* with a little sensor noise. */
static void thermal_update(void) {
/* ... */
double alpha = 1.0 - exp(-k * dt);
g_temp += (g_target - g_temp) * alpha;
}
This cannot come down into a screen definition. Something that turns on a millisecond cadence must not sit across a network.
Safety envelopes stay frozen too. And this one is stronger — whatever it is told from above, the hardware does not exceed itself.
/* The relay clamps its own range. Whatever the rule upstream
* decided, the hardware still refuses to exceed itself. */
if (v < 0) v = 0;
if (v > 100) v = 100;
The original wrote "real-time, drivers and security frozen; only the screen layer liquid". Building it, one line had to be added to that list. The thing that keeps a limit on itself. A rule being liquid means a rule can be wrong, and what catches it last has to be the frozen side.
The payment authorisation path stays frozen. The card terminal's secure area is not opened. Not because it cannot be, but because it is better not to, and that reason is written separately in What You Do Not Expose Protects the App.
(Firmware boundary from An LCD Maker Builds an HMI in 30 Minutes, relay clamp from Swap the Sensor, the Control Stays)
The protocol's name — what neither piece called it
Both pieces left the protocol unnamed to the end. "An agreed language", "an open common language". When a piece arguing that openness is essential blurs what the protocol refers to, the reader has nowhere to go and check.
The name is MCP (Model Context Protocol). And every sample in this series speaks it. The actual bytes look like this.
=> {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18", ...}}
<= {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-03-26",
"capabilities":{"tools":{},"resources":{}},
"serverInfo":{"name":"WeAct H723 MCP Node","version":"0.1.0"}}}
That is a line a real STM32 board answered over USB serial. And the claim of openness now has a basis — the same client code attached to an STM32 (UART) and an ESP32 (Wi-Fi TCP). The two boards do not know about each other, they are chips from different companies, and the transports differ. They still worked, because they speak the same protocol.
The original's sentence — "exactly the principle by which a browser renders HTML from any company's server" — is now not a metaphor but two boards' logs.
Answering the rebuttals again — with numbers this time
The two pieces set up five exchanges each and four overlapped. We set them up once, and rewrite the answers where we can now answer.
"Isn't it slow if every screen comes from the server?" — A screen definition is 1–2 KB (table above). And the round trip depends on the link. In one run, tool round trips were 1–11 ms over UART and 21–69 ms over Wi-Fi TCP, and connect-to-first-screen was 46 ms versus 189 ms. So the accurate answer is this — not "it is not slow", but the order of magnitude differs by link, and that difference splits UI design. On the single-digit side you can expect "press and it is there"; on the tens-of-milliseconds side you have to draw a waiting state. The original did not know about this split.
One thing to add here. Time values do not reproduce. Sizes are files and measure the same every time, but latency moved from run to run, and in one run the Wi-Fi side exceeded double the numbers above. So this piece claims orders of magnitude, not exact milliseconds.
"What about offline?" — This one is still unpaid. The original wrote "definitions are cached", and no sample in this series tested caching or offline behaviour. Reconnection was not measured either. It stays marked unverified.
"What about security?" — The original answer, that the runtime distrusts the definition and permits only fixed combinations, holds. To that we add what building it taught. There are three boundaries, not one (the receiving runtime, the exposing design, and hardware that keeps its own limit), and a capability not in the tool list cannot be reached by a person pressing or a model choosing. The evidence is in a separate piece. But "therefore it is safe" is not what this series proved — authentication, authorisation and transport security are all outside.
"What about app store policy?" — We keep the original answer (the line is whether you plant arbitrary native code). And we keep the caveat the original attached to itself — this is policy interpretation, not legal advice. One thing added: neither piece cited a single line of guideline. An interpretation with no citation is a guess, not an interpretation, so this item is marked unresolved until a citation is attached.
"What about server cost?" — Original answer kept. Except every server this series built was a local process, so we were never in a position to measure running cost.
What this sample did not do
The honesty sections of both originals stand. Compiling does not disappear, it moves; existing systems do not transform overnight; the labour called design remains. Building it, all three held.
To that we add what we learned.
Both pieces' thought experiments were thought experiments. The shop-device scene and the launch issue's scene both begin with "suppose that", and both were drawn so specifically that they read as observations. Everything this piece quotes is an execution log or a measurement, with a link to which piece it came from. We do not set imagination and observation in the same typeface.
The measurement is narrow. The numbers above come from one Mac, one router, one room, mostly measured once each. Small sample, one environment. Sizes are deterministic (the file is that big) but latency values change from run to run — even while writing this, latency figures quoted earlier shifted on a rerun, and we corrected them once to match the published log. A piece that quotes time ages together with its log.
Three things are still unpaid. Offline and cache behaviour, a citation for the app store policy, and running cost. There is still no measurement where the originals gave an answer.
So, doubt it again
The original closed that way. Doubt it, and the pieces that follow will show you the real thing.
Six months have passed and those pieces exist. Every number this piece quotes came from them, and each carries a build log, an execution log and a headless capture of the screen. If you want to reproduce it, take the folder and run it.
And we leave the places still worth doubting. Offline was never measured, the policy carries no citation, and cost was never in a position to be measured. Those three are exactly where they were.
The screen layer thawed. That can now be said as 656 bytes and 83 milliseconds. We also learned what has to stay frozen, and that list was longer than we first thought. What remains is what has not been measured, and that gets written after it is.
makemind.dev "Horizon" — Numbers written then without measuring have been replaced with measurements.