Behind the app

One developer. One codebase. Android and iOS.

Rosewood is built in Kotlin with Compose Multiplatform: the UI, the domain logic and the tests are written once and ship to both stores. Product research, PRDs, the design system, store copy and manual test plans are produced through agentic workflows and live in the repository next to the code they describe. The agents plan and execute; I gate releases and fix what breaks.

2
platforms from one Kotlin codebase, Android and iOS
30
releases shipped to both stores in six months
4.7★
rating on Google Play, with no paid marketing
24
languages in the app, 26 store localisations
Figures as of September 2026.
Architecture
Compose Multiplatform · Clean Architecture · MVVM

A single module. Everything new goes into commonMain; platform APIs sit behind expect/actual seams only where they must: Play Billing and StoreKit, notification scheduling, the audio device, DataStore. The domain layer knows nothing about either platform, which is why most of the tests live there.

Agentic pipeline
PRD → plan → ledger

An architect agent writes each feature as a PRD and an execution plan. An executor works the plan task by task on a feature branch, appending to an append-only ledger after every task; the ledger is the only status. Compile is a hard gate, tests a soft one, two fix attempts maximum. Market research, the monetization PRD, the analytics metric dictionary, store copy in 26 locales and the manual test plans came out of the same flows. Tooling: Claude Code, Gemini CLI, custom agents, Fastlane, an own analytics backend and crash reporting.

In the code
90+ test classes · 24 languages

The note you hear is synthesised, not sampled: a plucked-string model rendered per note in a few milliseconds, one voice, the same sound on a hit and a miss. The board's light tracks a ten-answer window with hysteresis, so one miss never takes back a level you earned. Contrast tests fail the build when an ink drops under its floor. Fret spacing follows 1 − 2−n/12.

Shipping iOS from an Android background

Compose Multiplatform carries the UI and the logic; StoreKit, notifications and the audio device sit behind expect/actual. The parts that were new to me, Xcode, App Store Connect, the review process, were a matter of asking the right questions of the agents. For a team building the same product for two platforms, I think this is the right bet.

What went wrong

One release shipped with no Next button in landscape. A customer email found it before I did, and the fix went out the same day, but retention took the hit. The rule that came out of it is now the second line of the repository's instructions: a change to landscape is not done until portrait is checked, and the reverse.

Asi Mugrabi
Mobile team lead · Kotlin & Compose Multiplatform · built alongside a full-time job
Email me LinkedIn