DEV Community

SYMBiEX
SYMBiEX Subscriber

Posted on

Building the AI Fallback Ladder Behind LOCK TF IN (an app that roasts you into working out)

I just shipped my first solo iOS app: LOCK TF IN — a fitness accountability app where an AI drill sergeant roasts you when you skip a workout. Log a session and it leaves you alone. Ghost it, and it goes off on you by name.

The bit is simple. The engineering behind making that bit reliable for every user, on every device, on every network condition, was not.

The problem: the AI is the product

Most apps can gracefully degrade when a network call fails — show a spinner, retry, fall back to cached data. LOCK TF IN doesn't have that luxury. If the AI coach doesn't respond, there's no app. The roast is the entire value proposition.

So I built what I've been calling the fallback ladder: three tiers, each one a full replacement for the one above it, not just an error state.

Tier 1: On-device Apple Intelligence

When the device supports it, the roast is generated entirely on-device using Apple's local models. No network round trip, no server cost, works offline, and — genuinely important for a satire app — no risk of a cloud provider's safety filter neutering the joke into something toothless.

Tier 2: Cloudflare Worker proxying a cloud model

Free users on older devices, or anyone without on-device AI available, still need a real AI coach — not a worse, static experience. A Cloudflare Worker proxies requests to a cloud model, funded by Pro subscriptions rather than gated behind them. The free tier isn't a stripped demo; it's the same bit, just server-generated instead of on-device.

Tier 3: Hand-written roast library

If both AI paths are unreachable — rate limited, offline with no on-device support, cold start — the app falls back to a library of hand-written roasts. This was the part I underestimated hardest. Writing "good enough to not break the illusion" fallback copy took nearly as long as the onboarding flow, because a bad fallback doesn't just feel worse, it breaks character in a product where character is the whole pitch.

What I'd do differently

I built the fallback ladder after the UI, treating it as a hardening pass. In hindsight it should have been the first thing designed, because it drove real architecture decisions (how state is cached, how retries are timed, what "loading" even means when tier 1 is instant and tier 3 needs a network call) that I ended up retrofitting.


LOCK TF IN is live on the App Store: locktf.com

Built solo with SwiftUI. Happy to go deeper on any part of this — the on-device/cloud detection logic, the Worker setup, or the roast-writing process — in the comments.

Top comments (0)