Inspiration

EyeOnian comes out of a working life spent in two places at once.

One life as an instrumentalist, composer, music director and educator, another in product work on the data handling emerging navigation systems features, including the manufacturing processes and standards which stabilized enormous, interdependent spatial data into something a person can act on in a second. The latter is where the approach comes from: the space of musical possibility is far past holding — larger than could be written down anywhere — yet a process which has the capacity to reach any point in it is small enough to sit on a tablet.

The harmonic relationships a musician might reasonably want to explore are combinatorially enormous — large enough that holding them all isn't a design tradeoff so much as a non-option. So we built for the other side of that lesson: give musicians access to the whole space anyway, and make it visualizable, navigable, manageable, sharable, all in a footprint small enough to sit on a tablet, and work with no network at all.

What it does

EyeOnian is an interactive tool for exploring and visualizing harmony and scales — a single place to see how music theory fits together and to make it your own.

Browse a complete, comprehensive library of modes and the constructive harmony each one is built from. Feed in your own harmonic ideas and watch EyeOnian analyze them in real time. See everything rendered in notation across many instruments — then save, share, and recall any visualization you create.

How we built it

Shared Rust core. One engine compiled for native targets and for a Cloudflare Worker serving the web build — the same logic behind every platform rather than three reimplementations.

FFI boundary via uniffi. The Rust/Swift and Rust/Kotlin seam is generated from a single .udl, not hand-written. Release builds are stripped so the shipped libraries expose only the 141-symbol uniffi surface — verified 0 engine symbols across all three Android ABIs and on linked macOS and iOS binaries.

Monetization on RevenueCat. Access is a subscription — monthly or annual — on all four platforms, with a free demo that needs no purchase. RevenueCat owns purchase and restore across iPadOS, macOS, Android and web, with a per-platform entitlement model — a subscription on one platform does not unlock another, by design. On Apple, StoreKit 2 remains the source of truth for whether a subscription is active; RevenueCat handles the transaction and keeps the record.

Entitlement resolves on-device on Apple. StoreKit 2 decides whether a subscription is active with no network call at all; RevenueCat is consulted for the purchase itself and for reporting. Android resolves through RevenueCat and caches locally, so the app works offline afterwards. No native app calls Music Solutions servers — when RevenueCat notifies our Worker of a purchase, that notification comes from RevenueCat's systems, not from the device.

Test and CI posture. 134 Rust core tests green behind a CI gate. A further 23 Kotlin tests run locally — 6 unit, 17 instrumented, including a first-run EULA gate exercised with the network disabled. Eleven CI checks guard the bundled documents: that each vendored copy matches the published page.

Challenges we ran into

EyeOnian crossed platforms before its commerce did. A visualization built on an iPad opens on a Mac, and a share hands off to whoever receives it — but purchasing ran through three separate paths with no shared view of who owned what. Bringing the native apps onto RevenueCat was the commerce layer catching up to how the product already behaved. The hard part is that entitlements are per-platform by design — a purchase on one store doesn't unlock another — so one system has to recognise someone across platforms while refusing to let their purchase travel with them.

Recognizing someone across platforms also runs against the fact that the native apps generate an anonymous identifier per installation — they have no accounts, and we would rather keep it that way. Our approach is to verify a store order number rather than linking identities, and whether that extends from crossgrades to recurring offers is a question we haven't answered.

Accomplishments that we're proud of

Built solo, end to end. Concept, design, engine, three native interfaces, monetization, legal and launch. No handoff between the person who decided something and the person who then had to build it.

One Rust core, three genuinely native interfaces. Swift on iPadOS and macOS, Kotlin on Android, the same engine underneath. Nothing flattened to a lowest common denominator to make the sharing work.

Nothing is generated or guessed. Every result is derived, and deterministic — the same input always produces the same output. Nothing is approximated or invented to fill a gap, and there is no model producing something plausible in place of something correct.

What we learned

Without a comparable implementation to reference, the work of defining the product overtakes the work of designing the experience. Normally there's something to point at — a competitor, a prior version, a convention — and the definition can be shorthand. With nothing to point at, every decision has to be argued from the ground up, and the definitional work expands to fill the space where a comparison would otherwise sit. The specification starts to determine what the experience is, instead of describing it.

What's next for EyeOnian

Pursuing paths for B2B integration and providing users cross-platform offers: someone subscribed on one platform getting a verified discount on another, without linking accounts or moving a purchase between stores.

Built With

Share this project:

Updates

Submission history