Why We Built for iOS and Android from the First Day

By Baseline Maps Team · Engineering ·

Quick answer

Native development on two platforms would have cost us two engineers and shipped half the surface. A cross-platform codebase let us ship every feature to every user on the same day. The compromise is roughly five percent of the most demanding map interactions feel slightly less native than a pure-native build — a price we accepted because every Founder we had was split half on iPhone, half on Android.

Most indie outdoor apps launch on iOS first, ride the early reviews, and promise Android in a year. We didn’t have that year, and our community wasn’t standing on one side of the line. Baseline Maps — the engine under Driftline for fishing and Ridgeline for hunting — shipped to both stores on the same day, and we want to write down the actual reasoning while it’s still fresh, before the easy story gets told for us. What follows is the honest accounting of why we did it, what it cost, and where the seams still show. We’re not interested in selling the decision as obvious in hindsight. It wasn’t obvious. It was a tradeoff, and most of the interesting work of building an outdoor app on a small team is learning which tradeoffs are worth making out loud.

The split-community problem

When we counted our earliest Founders, the device split landed almost exactly down the middle. Half were on iPhone, half were on Android, and the Android half skewed toward the people who spent the most days a year in the field — the guides, the public-land hunters, the river regulars whose feedback was the most useful in the room. Launching iOS-only would have meant telling half the community to wait twelve months while we built for the other half. That wasn’t a launch strategy. That was a quiet way of telling the most committed users that their phones were the wrong phones, and we couldn’t think of a single defensible reason to do that.

What native would have cost

Building two pure-native apps with one small team means doubling every screen, every gesture, every data model, and every release. We modeled it carefully. The honest number was two additional engineers we didn’t have, a slower iteration loop on every change, and a roadmap that would have shipped roughly half the surface area in the same window. A cross-platform codebase let one feature land on both stores on the same afternoon, every time, for the cost of about a week of platform-specific polish per release. Stated plainly, the choice wasn’t between a better app and a worse one. It was between one app on both platforms and a more polished app on one platform only, with the other half of the community waiting in line. We never seriously considered the second option once we said it out loud.

The five-percent gestures

There’s a small set of interactions — fast pinch-and-rotate on the map, certain inertia behaviors during pan, a few edge cases in the bottom-sheet drag — where a pure-native build would feel a hair tighter than ours does. We measured it on real devices, side by side, with the same test routes. It’s roughly five percent of the most demanding map moments, and most users never notice. Power users sometimes feel it on Android specifically, where the gesture system is less forgiving and the timing budget is tighter. We are not pretending the gap is zero. We are saying the gap was worth paying, because the gap on the other path was an entire missing app for half our users. That’s a different category of compromise, and once we framed it that way, the choice stopped being interesting to argue about. The remaining work is closing the five percent, one gesture at a time, and we ship most of those fixes without writing release notes about them.

Where Android is harder

Android punishes shortcuts. The map’s pinch-zoom gesture conflicts with the framework’s higher-level gesture handler unless you yield correctly — get it wrong and the map freezes mid-pinch in a way that’s almost impossible to reproduce on a desk. Background GPS has a lifecycle that resets in places iOS doesn’t, so battery-aware tracking takes more careful state management to keep your trip log from quietly going dark in your pocket. Permission flows route through a system activity that can fire app-state events you didn’t ask for, which means naive code re-prompts the user in a loop until they uninstall the app and write you an angry review. Map image rendering has a separate set of caching quirks that don’t exist on the other platform, and asset names collide across folders in ways that produce silent empty renders rather than helpful errors. None of this is exotic. It’s just real work that doesn’t go away, and most of our hardest debugging hours have lived here.

Where iOS is harder

iOS is friendlier day to day, but it punishes you in different places. The renderer has aggressive opinions about how layered transparent surfaces composite, and the wrong combination of shadow, clipping, and bitmap layers can stall the main thread in ways that don’t reproduce on Android at all. Modal presentation has subtle gotchas that, mishandled, leave a transparent window swallowing every touch the user makes afterward, which looks indistinguishable from a frozen map and is exactly as alarming. The store review process is slower, more conservative, and more opinionated about edge cases like login flows and subscription copy. iOS gives you a beautiful default and then quietly fails closed when you stray from it — the cost is hidden until you trip a wire, and then the cost is large. We’ve spent more hours chasing a single iOS rasterization bug than we have on most full Android features, and we don’t think that ratio is unusual on a small team.

What we wouldn’t do again

We wouldn’t try to share every single screen between platforms. There are places — settings, certain map controls, anything involving system-level affordances like sheets and pickers — where matching the platform convention exactly is worth the duplicated work, because the muscle memory of the device wins every argument with the muscle memory of the designer. We learned this the slow way, by shipping a few screens that felt right on one platform and slightly wrong on the other, and then quietly rewriting them. The lesson, written down so we remember it: a cross-platform stack is a tool, not a religion. Use platform-specific code where the platform earns it, and stop apologizing for the duplication when it makes the product feel correct in the hand.

What we’d do again

We’d make the same call about launching on both stores on day one. We’d build the design system first, before the screens, so platform conventions get enforced once and inherited everywhere instead of relitigated on every new feature. We’d invest earlier in the device farm and in real-world Android testing with mid-tier phones, because the cheap Android device is the one that finds the bugs the flagship phone hides, and the flagship is the one you’re tempted to test on. And we’d be honest with ourselves about the seams from the start. Pretending they don’t exist is how you stop fixing them. Naming them in a post like this is how you keep yourself accountable to the next round of polish. We’d also keep writing things down — decisions, dead ends, the reason a screen got rewritten — because the most expensive bug on a small team is the one you fix twice because nobody remembered why you fixed it the first time.

The version of Baseline Maps you’re using today — Driftline for fishing, Ridgeline for hunting — is the result of those decisions, and the ones we’re still making. We keep a working list of everything we know we still want to fix and ship, and you can see it inside the app under Development Queue. It’s the same list we work from on Monday morning, and it’s been the single most useful artifact for keeping the build honest. If you’ve found one of those five-percent seams, or you’ve got an idea for what should be on it next, we’d rather hear from you than guess.

FAQ

Common questions.

Why not launch iOS first and add Android later?
Because our beta users were half and half. Picking iOS first meant losing half the early Founders, who were the people whose feedback we needed most. We picked the harder path because the easier path was the wrong path.
Does the app feel less native because of the choice?
On a small set of map gestures, yes — the differences are measurable but most users never notice them. On everything else, the app feels identical to a native build because the design system enforces platform conventions.
What's harder on Android?
Map image rendering, background GPS lifecycle, and permission flows. Each of these required platform-specific work that wouldn't have existed on iOS alone.
Would you make the same call again?
Yes. The cost was real but the alternative — leaving half our community without an app for a year — was unthinkable.

Built together

Have an idea or a correction?

Open the in-app feedback box (Settings → Feedback). Pick Feature Request or Bug Report. We read every one.