The Sign-In Page That Lives on Your Dish

Join the WiFi on one of our kits and a sign-in page appears. It is not hosted on our servers. It is a single file baked into the dish's own router, and it keeps working when everything else is unreachable. Here is what you see, and how it is built.

8 min readBy WiFi Without Walls Team
captive-portalhow-it-worksengineering

Every kit we rent hands out its own WiFi network. Join it, and your phone pops up a sign-in page: your rental, your data, your code. Most of the software we write is ordinary web work. This page is not, and the reason is worth explaining.

What you actually see

The WiFi is open. There is no password to type, no card taped to the dish with a passphrase on it. That is deliberate: the gate is not the WiFi, it is the sign-in page, and every device that joins lands there walled off until it checks in.

You do not have to go looking for it. Your phone, laptop, and tablet all quietly test their internet connection against a known address the moment they join a network, and those addresses are pinned at the router, so the test lands on our page instead of the internet. That is what makes the sheet appear by itself instead of leaving you wondering why nothing loads.

The WiFi Without Walls sign-in page, showing a four-digit code entry, a day pass option, and a panel listing messaging apps that stay reachable

Your code is the last four digits of the phone number on your reservation. If you booked without a phone number, the email on your reservation works instead. That is the whole credential. It is a shared secret you can say out loud across a campsite, which is the point: you hand it to the people you came with, and they each put it into their own device.

Look at the panel at the bottom of that screenshot, because it is the part we care most about:

Messaging always stays on. iMessage, RCS, WhatsApp, Signal, and text messaging all keep working before you have signed in to anything. If you are out of data, mid trip, or fumbling the code in the dark, you can still reach somebody, and somebody can still reach you. Emergency texting is not something you should have to get past a login screen to use.

Once you are in, the page turns into a dashboard for the rental itself.

The portal's online view showing 56GB of data left, 5 days of time left, and an option to extend the trip

Data left, time left, and a way to add more days, all from a page you reached without having internet first. Anything you buy here goes on the card already attached to your reservation. There is no top-up button in that screenshot because that rental is nowhere near its data cap: the page asks our server whether a top-up is genuinely available before it offers one, since a button that cannot work is worst at exactly the moment somebody needs data.

The campsite is your campsite

The artwork behind those two screenshots is not a stock photo. It is a live 3D scene, and it is rendering where your dish actually is.

Put a kit in the Nevada desert and you get cacti and dunes. Put the same kit in the pines and you get pines. The scene reads the dish's last known position and then resolves the real conditions there: the biome, the season, the time of day, and the current weather. Southern hemisphere flips the season, so a January rental in Patagonia is not rendered as winter. There are a few holidays hidden in there too.

Because the sign-in page is sealed off from the internet until you connect, it cannot go and ask a weather service anything itself. So it does not. The dish reports where it is, our server looks up the conditions there, and the page is handed the answer.

You do not have to take any of that on faith. The panel below is the scene itself, loaded from the same bundle the portal serves: pick a biome, a time of day, a season, the weather, or a holiday, and the terrain, sky, vegetation and fire rebuild in place. It opens on whatever the scene would resolve for a dish right now, and the dropdowns are filled from the scene's own tables, so the options are exactly what the scene can draw.

Loading the 3D scene…

Why it is built strangely

Here is the constraint that shapes everything above. A rental only exists because somebody drove somewhere without reliable internet. If our sign-in page needed our servers to be reachable, it would fail precisely where the product is supposed to work.

So the page is not hosted. It is one self-contained HTML file. Every style, every script, the logo, and the artwork are all inlined into that single file. There are no font downloads, no script tags pointing at a CDN, and no image URLs. The icons are hand-drawn shapes inside the file rather than an icon font, for the same reason.

That file gets baked into the dish's own router, and the router serves it locally to anything that joins. Nothing in that path touches our servers. You can confirm the shape of it from outside: the address the router serves the page on does not exist in public DNS at all. Ask the internet for it and you get nothing back. The only thing that answers for it is the router sitting behind your dish. We do also serve the very same file from our own domain, as a fallback for a device that somehow reaches us instead, but the copy that matters is the one on the hardware in your hands.

The pipeline is deliberately boring. One function renders the page to a string. A script minifies it and writes it to a file, which we commit to the repository. Our infrastructure config uploads that committed file to the dish's router configuration. Minification is in there because a router's captive portal configuration has a hard size ceiling, so the copy that ships to hardware has to be small.

Committing a generated file is usually a smell. Here it is the feature: it means a change to the sign-in page shows up in code review as the exact bytes headed for the dishes, not as a promise that a deploy will produce them. That only works if the file cannot quietly go stale, so the page renderer is a pure function with no imports and no clock reads, which makes rendering it twice produce identical bytes. Our build re-renders it on every change and fails if the result differs from the committed file. A second check does the same for the 3D scene bundle. If either drifts, nobody merges.

The 3D scene is the one exception to the no-external-resources rule, and it is a deliberate one. The scene is a large bundle, far too big to bake into a size-capped router configuration. So the file baked into the router carries only a small placeholder and a loader, and the scene itself downloads separately from our main domain, which is on the router's allow list. The still artwork you saw is the fallback: it is what renders on a device with no 3D support, and it is what you see before the scene arrives.

The script inside the page is written in an older, plainer dialect of JavaScript than we would use anywhere else in our software, on purpose. It has to run on whatever phone just joined a WiFi network in a field, including the old one in somebody's glovebox.

And every network call the page makes is allowed to fail. Read the rental, check the dish, load the scene: if any of it does not answer, the sign-in form is still standing and the code still works. A question we cannot ask correctly is a question we drop, because you paid for internet, not for our diagnostics.

The dish tells us you have it

One more thing this page does that has nothing to do with pixels.

If you pick your kit up in person or we drop it off locally, there is no carrier tracking number to tell us the handover happened. Something has to move your rental from "ready" to "out with the customer". A scheduled job does that, but only on a timer and only once it can prove possession, which can be hours after the kit is actually in your hands.

So the dish does it. When you power the kit on and connect, that is the handover: the rental advances the moment your dish asks who it belongs to, with your code as the proof. A dish that is powered on, in your hands, and asking about its own rental is better evidence than anything a schedule can infer.

The honest caveat about these screenshots

These are real screenshots of the real page, rendered from the same code that ships to the dishes, showing a real rental. Two disclosures, because the alternative is implying more than we did. They were taken from the fallback copy served off our own domain rather than off a dish in the desert. And where the page needs the dish's own router to tell it which device is asking, we stood that one answer in locally, because only real hardware can give it. Everything else on screen, the rental, the data, the days, the prices, the campsite, came from the running software.

If you have a rental with us, you have already seen this page. If you have not, browse the kits or get a quote, and the next time you are somewhere with no cell service, this is the screen that gets your whole group online.

Keep reading