barts.work
Bloom — app screenshot
Work in progress ios

Bloom

A cozy idle-garden iOS game: tap, plant, prestige — the garden keeps growing while you're away.

Bloom is a cozy idle-garden game for iOS: tap to earn Petals, buy plants that auto-produce while you’re away, and eventually compost the season into a “New Season” prestige for permanent multipliers. About 50 achievements, a plant ladder, a Spring Seed upgrade tree. Monetization is StoreKit 2 IAP (Sunbeam packs) that’s deliberately accelerative only — it speeds you up, never gates content. No accounts, no analytics, no ads, saves are local-only.

Status

The app is feature-complete and parked. The full loop — tap, buy, prestige, achievements, IAP grants, offline earnings — works end to end, the engine test suite is green (hundreds of tests across Swift Testing and XCTest), and the app compiles clean. What’s left is human paperwork: Apple Developer enrollment, the App Store Connect record, the eight IAP entries, a real app icon (it currently ships a placeholder gradient with a 🌸), and a sandbox purchase pass on a physical device before I hit submit. It also queues behind the same two gates as everything else I ship solo right now: VAT-UE registration, and the fact that my Mac lives on beta-everything while App Store submissions want a release-candidate Xcode.

How it was built

The interesting part isn’t the game, it’s the discipline underneath it. Bloom’s engine grew off an ordered task plan, executed one task at a time: write the failing test first, make it pass, then face a single green/red verification gate — verify.sh, which demands the engine suite green and the app compiling clean — before anything gets committed and crossed off. “Done” was never a feeling; it was an exit code. The rule I’d frame and hang on a wall: never go green by cheating — no deleted, skipped, or weakened tests; a clean red-blocked state beats a fake-green commit. The repo’s 120+ commits read like a metronome because of it.

Lessons learned

All that discipline didn’t prevent real bugs — it caught them. The lessons file I kept during the build reads like a diary: an icon-compile step that could never succeed on this Mac’s missing simulator runtime, a prestige currency that needed Fibonacci-shaped sinks or players would 100% the tree in one reset, and a genuinely nasty one — starting an empty AVAudioEngine graph threw an Obj-C exception try? couldn’t catch, crashing every launch until I learned to gate on “ready” instead of “started.” The design pass came only after the engine was trustworthy — custom Metal shaders, a “Night Garden” seed tree, procedural paper-cut flora. Lesson for me: process keeps the engine honest, but taste is a separate job, and it refuses to run on a schedule.