← all posts

A Redesign, a Paywall Diet, and a Golden Retriever Made of Triangles

2026-09-14

This was a wide week. Three apps got attention — a ground-up redesign for Speakit, a round of onboarding and sound work for Mind Journeys, and a paywall cleanup on Uncaption ahead of 1.8.0 — and somewhere around Saturday night I started something completely new: a small Unity game where the main character is a low-poly Golden Retriever. The common thread, looking back, is that almost every piece of work was about making a screen show something instead of describe it.

Speakit Gets a New Face

The Speakit redesign landed as a stack of commits that go in the order you'd hope: tokens first, then components, then screens. The new token layer isn't just new hex values — it changes the grammar. A warm cream canvas instead of a cool near-white, cards that separate from the background by value and a soft shadow instead of a 1px keyline, six pastels with fixed meanings, and a serif (Newsreader) carrying display type.

To avoid the app going dark while ~380 call sites still used the old names, I added a temporary compatibility shim that mapped old colours onto the nearest new tone. Two commits later, every screen was ported and the shim was deleted. That's the part I'm proudest of: the temporary thing was actually temporary.

The most useful addition was a design gallery. Speakit's screens sit behind a login, so there was no easy way to visually check a port. The gallery renders every component — and now whole static screens — behind a launch argument in debug builds, with no network and no auth. The first time I looked at it, it caught three mistakes the design CSS had told me about and I'd missed: buttons that should use a tone gradient rather than a flat fill, ragged stat tiles, and a corner glyph that vanished against its most common background.

One lesson worth writing down: font names lie quietly. Newsreader's default instance is named after its optical size, so asking for Newsreader-Regular silently fell back to the system serif. No error — just the wrong font. Resolving by family instead fixed it, and the gallery header now states which serif is live, because it's not something you can spot by eye.

On the product side, the Learn tab is gone. The tabs are now Speak · Journal · Profile, and the course path moved behind a "coming soon" screen — demoted, not deleted. Haptics also went from twenty ad-hoc calls with no shared meaning to a single vocabulary of named moments (.correct, .recordStart, .celebrate). Bonus discovery: iOS silences haptics while the mic is live, so every record-start haptic firing after the recorder started had never played at all.

Mind Journeys Learns to Make Noise

Ten onboarding screens explained what binaural beats are. None of them let you hear one. Now there's a step where you drag a frequency strip under a playhead and the beat follows your finger from delta through gamma. The mapping is logarithmic — a linear one gives almost all the travel to beta and gamma and squeezes delta and theta, the bands this app is actually about, into a few points.

Two other onboarding screens drew choices they didn't offer: a band table and a grid of ambience scenes that looked tappable and weren't. Both respond to taps now, and the scene tiles cross-fade a preview bed in.

I also added six meditative ambience beds — pads, drones, bowls — generated with ElevenLabs' music model. That model fades in, fades out, and swells mid-take, so no take is usable whole. Each gets trimmed to its longest steady stretch, crossfaded, folded tail-into-head so the loop point disappears, and level-matched. Later in the week I stretched three of them to three-minute loops by building takes from a composition plan of constant-volume chunks instead of a prompt. The other three will have to wait: their long takes came out too dark or had a gong every 22 seconds, and I ran out of credits before the redo.

Uncaption's Paywall Goes on a Diet

Uncaption 1.8.0 is nearly ready, and the paywall was the last thing standing in the way. It had become a scroll of everything: a statistic, an animated marketing block, plan buttons, an emoji feature list, a comparison grid, the same plan buttons again, then the terms.

It's one column now: what this is, what you get, what it costs, the terms. Before simplifying, I'd rebuilt the comparison table as native views — it had been a PDF with the copy baked in, so non-English users saw English, and it still advertised a minutes-based economy that no longer exists. Then I removed the grid entirely, since nothing on the page is sold as "Basic" anymore. Sometimes you fix a thing properly and then realise it shouldn't exist.

The account screen got the same treatment: a subscriber used to see a lonely expiry date overlapping the delete button. It's now a card with three clear states, and the subscription state is an enum, so "RevenueCat hasn't answered yet" no longer flashes "No active subscription" at paying users.

Something New: Puppy Pats

The fun one. Puppy Pats is a Unity game about walking around as a dog, and this week was mostly about the dog. The model started as an image-to-3D mesh, then got converted to a poly-art style — decimated from 23k to a few thousand flat-shaded triangles with a 28-colour palette texture. Sphere eyes kept poking through the sockets, so they became painted facets on the body mesh. Then a 32-bone quadruped rig, animation clips, and editor automation that syncs walk and run playback to movement speed so the paws don't slide.

I wired Unity up to Claude Code via an MCP package, which made iterating on editor setup a lot less clicky. By Sunday it had portrait touch controls for iPhone — a stick, a Run button, and a Pet button that shows up near things you can interact with — and a camera tuned so the dog sits in the lower third of the screen.

That's the week. Next up: get Uncaption 1.8.0 through review, collect first reactions to Speakit's new look, and make the dog do something more interesting than walk.

#ios#swiftui#design-systems#unity#monetization