Case Study
Self-initiated · iOS field kit
An offline-first iPhone app for planning radio communications on trips where the phone network is gone — primary, alternate and emergency channels, a rotating codebook, and a field mode you can read in direct sun or by red light. Its central design decision is a refusal: the app never lets "your radio can tune this" pass for "you are allowed to transmit here."
Role
Design & Build (solo)
Timeline
Sep 2026
Team
1
Client
Self-initiated · iOS field kit

Outcomes
0
Accounts for core tools
Plans, Field Mode, frequency lookup, codebook and references all run with no sign-in and no network
66
Frequency records on device
FRS, GMRS, repeater pairs, MURS, NOAA and amateur simplex — each with its rule, citation and review date
47
Automated tests
Including the authorization engine and an offline repository test that blocks the network outright
01 — Problem
Handheld radios are what a group falls back on when there is no cell signal — a hunting party, an overlanding convoy, a family spread across a trailhead, a neighbourhood team after a storm. The radios themselves are cheap and capable. The planning around them is not. Which channel are we on, which one if that fails, what tone, when do we check in, who is calling — that information usually lives on an index card, in someone's head, or in a group chat that stops loading the moment it matters.
Radio apps exist, and most of them are frequency databases: long lists of channels with a green indicator next to anything your radio can reach. That indicator is the problem. A modern multiband handheld can be programmed onto frequencies its owner is not licensed for, with hardware that is not certified for that service. "Your radio can do this" and "you may do this" are different questions with different answers, and a single green light answers the wrong one with confidence. In radio, the consequence of a confident wrong answer is an FCC violation, or interfering with someone who is trying to call for help.
So COMMSIX had two jobs that pull against each other. Be the fast, readable comms card a group actually uses in the field — and be scrupulous, sometimes inconveniently so, about what it does not know.
02 — Research & Discovery
This one started as a document rather than a study. Before any code existed I wrote the product down: who it is for, six destinations, the shape of a comms plan, and — the section that ended up governing everything — five questions every frequency record has to answer separately. Can this radio receive it? Can it technically be configured to transmit it? Is the radio certified for this radio service? Is the user licensed? What power, bandwidth or operating limits apply?
Most of the discovery after that was in primary sources. Part 95 for FRS, GMRS and MURS. Part 97 for amateur radio. The NOAA Weather Radio channel list. The manufacturer manual for the Baofeng 5RM, the radio I was planning around. The useful finding was how often the sources disagree with what people assume: FRS and GMRS share frequencies but not rules; GMRS repeater pairs say nothing about whether a repeater exists near you; the ARRL band plan is a voluntary convention, not law; and the radio's documented transmit ranges — 144–148 and 420–450 MHz — do not include the FRS, GMRS or MURS channels it is so often programmed onto.
The second input was the conditions. Field use means bright sun or full dark, gloves, one hand, a low battery, and no signal at all. That set the hard requirements before any screen was drawn: nothing in a core flow may wait on the network, nothing in the field view may need more than a glance, and the app has to stay legible in three very different kinds of light.
What set the constraints
03 — Design Process
Project phases — select one
Specification. The product written down before anything was built: six destinations, PACE plans, the five-question authorization model, and an Airplane Mode acceptance test that blocks release.
The architecture follows the spec's priorities. The authorization rules, frequency data, radio profiles and plan validation are plain TypeScript packages with no React Native in them, so they can be tested directly and reused by a future planning site. SQLite on the device is the source of truth and is seeded atomically from the bundle on first launch. Frequencies are integer hertz, because comparing 462.5625 as a float is how you get a channel that is almost but not quite in range, and supported ranges include their lower bound and exclude their upper one so the app never implies operation at the next allocation's edge. The automated tests include an offline repository test that blocks fetch outright.
The first build on September 28 was a reasonable dark mobile app: a green accent, rounded cards, a big Enter Field Mode button. It worked and it looked like a lot of other apps. The redesign on September 30 went the other way, toward an instrument panel — near-black surfaces, pale white-green readouts, monospaced labels, a tick-marked ruler under every frequency, and a FIELD CONTROL masthead over a point-cloud terrain. The aesthetic is a deliberate signal that this is a reference tool, and it came with rules attached: the terrain and the grid are decorative, hidden from assistive technology, and switched off in Daylight and Reduce Transparency, so nothing ornamental can be mistaken for measured data.
The motion pass held to the same discipline. Buttons compress to 96% in 85 milliseconds and spring back; the active tab's marker expands in 200. The terrain drifts on a 9.2-second cycle, moving at most three points, and it stops when the screen is out of focus. The system Reduce Motion setting is observed live, and animation stays off until its value is known, so there is no opening flicker for someone who has turned it off. Readouts never animate. A frequency is either on screen or it isn't.
The last round of changes came from using the build. A screenshot from my own iPhone showed a gap between the screen title and a floating toolbar of display controls. Rather than nudge the spacing, I removed the toolbar: Settings became a sixth tab, every screen now shares one fixed 56-point header, and the MAP placeholder — a tab promising offline maps that did not exist yet — became CODEBOOK, a feature that did.
The same home screen across three days. Each version was a working build, and each change came from using the one before it — click any of them to look closer:
Three builds · Sep 28 – 30
First build, instrument pass, and the version after reviewing it on my own phone. The masthead shrank so the primary frequency and Field Mode sit above the fold, a placeholder MAP tab gave way to a CODEBOOK that existed, and Settings moved out of a floating toolbar into the tab bar.
04 — Solution & Outcome
COMMSIX has six destinations: COMMS, CODEBOOK, RADIO, TOOLS, LIBRARY and SETTINGS. COMMS holds the active plan — its primary channel, the PACE fallbacks behind it, and one large button into Field Mode. Field Mode keeps only what is needed under pressure: the channel number at the size of a headline, the frequency and tone beneath it, the next check-in time, and the alternate. Where location is unavailable it says so rather than showing a stale or estimated position.
Every frequency screen carries the same assessment block, and that is where the core decision shows. Receive support, transmit hardware and authorization are three badges, not one. RX SUPPORTED can be green. TX CAPABLE is amber — never green — because hardware capability is exactly the thing people mistake for permission. The only green transmit state, TX AUTHORIZED, requires a manufacturer-documented radio profile, a matching valid license, a confirmed radio variant, and verified equipment and operating conditions. A saved call sign does not count as a license, and Settings says so beside the field where you enter one. Plan channels the radio is not documented to transmit on are labelled MONITORING REFERENCE throughout.
The wording was the hard part. Internally, a frequency outside the profile's documented transmit range returns DO_NOT_TRANSMIT. On screen it reads CHECK BEFORE TRANSMITTING, followed by one sentence explaining why and the specific requirements that apply. The engine is reporting on what the documentation shows, not on what the physical radio might do, and the label says what the user should do next instead of overstating what the app knows.
The codebook comes from Blackline, a web app I built earlier in the year, rebuilt as a native tab: 32 phrases and 20 code sets that rotate daily at a configurable UTC hour, worked out from the device clock with no server and no background job. Private groups are the one feature that uses an account, and sign-in is only requested when you create or join a group. Behind it are Firebase Authentication and a Cloudflare Worker with a D1 database, picked over Supabase on running cost. Invitations are four-use links and QR codes, and removing a member rotates the group's key.
Key design decisions
The engine behind every frequency screen, running here on the app's own rules and radio profiles. Pick a channel, a radio and a license, and watch which gate decides:
462.6000
This frequency is outside the selected profile’s documented transmit range. Check the radio, service and operating requirements before transmitting.
47 CFR §§95.1705, 95.1751, 95.1761–95.1773 · data 2026.09.28
The shipped build, screen by screen:
Capability ≠ authorization
Three separate answers for one channel. The radio can hear GMRS 17; its documented transmit ranges stop short of it; so the app asks you to check rather than implying you're clear. The radio profile shows its own provenance and asks you to match your unit's manual.
Three lights
Field Mode in Dark, Daylight and Red light. Daylight is opaque, with no glass or grid behind the numerals, because translucency washes out in direct sun. Red light preserves night vision. The layout stays identical across all three, so muscle memory carries over.
Codebook
A rotating brevity codebook that needs no server. The day's code set comes from the device's UTC clock and a configurable rotation hour, so two phones agree without talking to each other. The code word is set large and the meaning small, because the code is what you say over the air.
Saying what it isn't
The emergency template opens by stating its limits: it prepares words to read and does not call anyone or transmit. Settings puts the same kind of note beside the call-sign field — saving an identifier does not verify a license and grants nothing.
05 — Team & Collaboration
The team
1
Solo and agent-paired, the same way I built DataOrbit. I wrote the product specification first — the capability and authorization model, the offline requirements, and a release-blocking Airplane Mode test — and the agent built against it. My time went into the parts a spec cannot settle on its own: the exact words on each status badge, what Field Mode leaves out, and reviewing the build on my own iPhone, which is where the last round of changes came from.
06 — Reflection
The most consequential design work here was vocabulary. "TX not documented" instead of "can't transmit." "Monitoring reference" instead of a channel that looks ready to use. "Check before transmitting" instead of either a green light or a red one. Each phrase had to be true for every radio and every user the label could appear in front of, and that is a harder test than whether it fits on a badge. The instrument-panel look helps people trust the app; the wording is what makes that trust deserved.
Writing the specification before the code changed what the agent produced. With the five authorization questions and the Airplane Mode test defined up front, offline-first had a pass/fail meaning rather than being an aspiration, and the agent built toward a test instead of toward a demo. When a build is cheap the spec is where the actual decisions get made, and almost every change I asked for afterwards was the spec catching something the build had glossed over.
Physical acceptance is the next step. The release gate in the spec — Airplane Mode, force-quit and reopen on a real device — along with VoiceOver, maximum Dynamic Type and an afternoon outdoors in real glare, has to run on hardware, and all four are listed as pending device checks in the repository. Android source is in place and has not been verified. Offline map tiles, the feature the old MAP tab promised, are deliberately left for after those checks.
Tools Used
Working on something like this?