Case study
Whimsy
Free audio walking tours, written by a model, fact-checked against real sources, and narrated by a small open-weights voice running on a Mac in the house.
- Platform
- iOS · watchOS
- Stack
- SwiftUI · Python · MLX Kokoro · nginx
- Status
- TestFlight, build 2
- Scale
- 2,300 lines Swift · 900 watch · 2,500 lines of tour script
The problem
Paid audio-tour apps are expensive per city, thin outside the famous places, and written as a list of facts rather than as a walk. A self-guided tour that actually works has to be paced for someone moving between points — it has to say “walk toward the facade and climb the stairs, about three minutes” and then stop talking.
The bet
Scripts written by a model, fact-checked by a second pass against real sources, narrated by a small open-weights TTS model on hardware already sitting in the house. That combination puts the marginal cost of a tour close to zero, which is what makes fifty places free and plausible.
The quality bar is a hand-written reference tour of St. Peter’s: ten stops, 1,650 words, about twelve minutes of narration, every stop ending with directions to the next.
Decisions
-
Three depths from one script
The same walk is offered as Highlights, Essentials and Full, compiled from a single Markdown file with
+++markers. A tourist with twenty minutes and one with a whole afternoon want the same route and different amounts of talking — and maintaining three scripts per place would have killed the catalog. Identical depths collapse, so a short tour never offers the same walk three times. -
Logistics are fact-checked as carefully as dates
Entrances, one-way flows, timed-entry order, stairs, security lines. A wrong year is an embarrassment; a wrong turn strands someone in a foreign city.
-
Units follow the place, not the reader
A tour of Kyoto is in metres, because that is what the signs say.
-
No GPS triggering in v1
Indoor GPS fails in precisely the buildings the tours care about. The player pauses after directions and waits for “I’ve arrived” — or a headphone next-track press — with auto-continue available for people who prefer a short gap.
-
Per-stop audio files
Skip, scrub, “start at stop 7” and resumable downloads all become trivial, and re-synthesising one edited stop touches one file.
-
Map snapshots as cover art
No photo licensing problem, and every tour gets art the day it is written.
The look
The design system is the product’s personality, and it is deliberate rather than decorative. One file holds all of it: a yellow page, pink display type in Baloo 2, and saturated card tints cycled through a list so a catalog reads as a set of toys rather than a table of rows. Text colour is chosen per tint by a function, so the lime card gets ink and the rest get white — legibility is enforced by the type system rather than by remembering.
Nine mascot poses are wired to app states, so the character reacts to what you are doing rather than sitting in a corner. The watch keeps the same shapes at smaller numbers, from the same file, through one platform guard on the geometry constants. One design system, two platforms, no fork.
The engineering story
-
The pipeline is the product
Compile, synthesise, publish — with a per-chunk content-hash cache. Editing a sentence re-renders that sentence’s chunk and nothing else; changing the voice re-renders the catalog. That property is what makes iterating on fifty tours affordable.
-
The catalog is the authority, not the app
A tour is available only when its JSON and every audio file exist on disk. The app cannot advertise something it cannot play, because it is not the thing deciding.
-
QA is automated because listening does not scale
The pipeline transcribes the rendered audio and diffs it against the source script. It is how a swallowed paragraph gets caught without anyone sitting through twenty-five minutes of narration.
-
Assets are code
Every mascot pose and the app icon regenerate from source art by script. The matting flood-fills inward from the border rather than colour-keying, because a colour key ate the character’s teal body against a blue plate and its red headphones against a coral one.
Where it stands
Ten of the fifty tours are written, fact-checked and rendered: Indianapolis, Grand Central, Westminster, Notre-Dame and the Île de la Cité, the Roman Forum, St. Peter’s, the Acropolis, the Old City of Jerusalem, Fushimi Inari and Sensō-ji. Build 2 is on TestFlight with the watch app included. The remaining forty places are catalogued and marked coming soon, which the app renders honestly.
Screens