Team

Mobile Engineering

We build the iOS and Android apps people open to review a record, sign an approval and authorize a change. They have to load on a five-year-old phone over a flaky 3G connection, work offline when the network drops, and recover gracefully from a backgrounded session the user forgot they had open. A crash during a critical approval is not a metric; it is an incident.

<2s

Cold start to first action

99.4%

Crash-free sessions

iOS 15+ / Android 9+

Minimum OS supported

100%

Offline-capable critical flows

Why Mobile

The phone is where trust meets the thumb

The phone is the surface a customer opens at 2am to approve a release, to check whether their data survived the night, or to authorise a change they cannot undo. That moment is the trust test, and we engineer for it specifically: the app cannot lie about the network, cannot freeze mid-approval, cannot show a stale state when the user is about to sign. Every critical-path screen is built to survive a dropped connection mid-tap and recover to a consistent state — never a half-sent one. Biometrics are convenient, but the security boundary they protect has to be designed first; we treat Face ID as the lock, not the door.

We refuse the idea that mobile is "the website in a wrapper". Our apps are native where the cost of a millisecond matters — biometrics, secure enclave, background sync, push delivery — and shared everywhere else through a single TypeScript codebase. Accessibility is a release gate, not an afterthought: a VoiceOver user has to complete the same wire a sighted user does, in the same number of taps, with the same confirmation copy read aloud. And because a phone is the most personal device a person owns, we treat privacy as a feature: the app collects the telemetry it needs to fix crashes and nothing more, and the user can see and delete that data from inside the app.

What we build

From approval apps to operator consoles on tablets, here is what leaves our keyboards and ships to the App Store and Play Store.

Approval & Signing Apps

Native iOS and Android clients for record approvals, document signing and key ceremonies — biometric-gated, secure-enclave-backed, and offline-capable when the network drops mid-ceremony.

Operator Tablets

Internal compliance and finance tools running on managed tablets, with audit-grade input controls and a signed-action trail that maps every tap back to an operator and a device.

Push & Background Sync

Silent push and background-fetch that keep record states and approval queues fresh without draining the battery — and that survive iOS background-app-kill and Android Doze.

Shared TypeScript Core

Domain logic, validation, and domain primitives live in a single TypeScript module consumed by both platforms — written once, reviewed once, behaviourally tested once.

Offline-First Critical Flows

Critical flows queue locally on device, sync when the network returns, and never show a success state for a transaction that has not been confirmed by the backend.

Accessibility & VoiceOver

Every critical screen ships with VoiceOver and TalkBack labels, dynamic-type support, and a tap-by-tap test plan a screen-reader user can complete unaided.

How we work

Our loop is shared-core, native-shell. Here is one orbit, from keyboard to store.

1

Specify the shared core

Engineer pairs with backend and design on a written spec: shared validation, states, copy in two languages, accessibility labels, acceptance tests.

2

Implement the core in TypeScript

Shared logic — domain math, validation, state machines — is implemented once and behaviourally tested once, before any platform-specific shell is written.

3

Build native shells

iOS (Swift) and Android (Kotlin) shells consume the shared core; biometrics, secure enclave and push are implemented natively where millisecond cost matters.

4

Test on real devices

A real-device farm runs every PR on five-year-old hardware over a throttled 3G profile; a regression on a low-end device blocks the release.

5

Phased store rollout

Releases ship to 1% of users then 10% then 100% over 72 hours, with a kill-switch that reverts server-side without a new store submission.

6

Observe crashes, ship a fix

Crash telemetry feeds the next sprint; a regression that fires more than twice triggers a hot-fix release within 24 hours. We do not wait for the next scheduled release to fix a crash.

Definition of done

A mobile release ships only when all of this is true

Crash-free

Crash-free sessions ≥ 99.4% on the previous release; any new crash class blocks the rollout.

Accessible

VoiceOver and TalkBack labels merged, dynamic-type verified, screen-reader test plan completed unaided on every critical screen.

Offline-safe

Every critical flow survives a dropped connection mid-tap and recovers to a consistent state — never a half-sent one.

Low-end ready

Cold start under 2s on a five-year-old device over throttled 3G; memory under the budget on the lowest-supported hardware.

Revertible

A server-side kill-switch can disable the feature without a new store submission; a regression can be turned off within minutes, not the days a store review takes.

Tools & why we use them

Shared core, native shells. Each tool was chosen for its failure mode, not its demo.

Swift (iOS)

Native where milliseconds matter: biometrics, secure enclave, push delivery. Wraps the shared TypeScript core.

Kotlin (Android)

Same reason, other platform. Coroutines for background sync that survives Doze and background-app-kill.

Shared TypeScript core

Domain math, validation and state machines written once, reviewed once, behaviourally tested once — then consumed by both shells.

Firebase + Crashlytics

Crash telemetry that feeds the next sprint; a regression that fires more than twice triggers a hot-fix within 24 hours.

Firebase Test Lab + Maestro

Real-device farm on every PR; five-year-old hardware over throttled 3G; a regression on a low-end device blocks release.

Fastlane

Phased store rollout to 1% then 10% then 100% over 72 hours, with a server-side kill-switch independent of store review.

RevenueCat-style feature flags

Server-driven feature flags let us turn a feature off without a store submission; we can revert within minutes.

Axe DevTools Mobile

Accessibility lint on every PR; VoiceOver and TalkBack test plans completed unaided before a critical screen ships.

How we interface

Where mobile meets the rest of the company

Backend

Shared TypeScript core is co-owned; backend writes the server side of the contract, mobile writes the client side, and contract tests prove they agree on every PR.

QA

Maestro flows run on every PR on the real-device farm; QA owns the critical-path scenario matrix that runs against every release candidate before phased rollout begins.

DevOps

Phased store rollout is owned jointly; DevOps owns the kill-switch infrastructure, mobile owns the feature-flag gates. Either can turn a feature off within minutes.

Design

Designers spec states and accessibility labels jointly with engineers; a critical screen does not ship without a VoiceOver label spec merged first.

Questions we get asked

Why a shared TypeScript core and not full native?

Domain math, validation and state machines are the riskiest code we write; writing them twice in two languages doubles the bug surface. A single reviewed, behaviourally-tested core consumed by native shells gives us correctness once and native UX where it matters.

How do you handle a dropped connection mid-approval?

Every critical action is idempotent on the backend; the app queues the request locally, retries with the same idempotency key when the network returns, and never shows a success state until the backend has confirmed it.

Do you really test on five-year-old hardware?

Yes — on a real-device farm with throttled 3G. A regression on a low-end device blocks the release even if it is invisible on a flagship, because that is the phone most of our customers actually hold.

What happens if Face ID is bypassed?

Face ID unlocks a session; it does not authorise a change. Every critical action requires a second factor that survives a stolen unlocked phone — a server-side authorisation the user must approve from a trusted device.

Can you revert a release without waiting for the store?

Yes. Server-side feature flags let us turn a feature off within minutes, independent of store review. A new binary submission is the last resort, not the first.

Our mission

Build mobile apps that earn trust at 2am, on a five-year-old phone, over a flaky network, when the user is approving something they cannot undo. We treat the phone as the trust surface where the thumb meets the ledger — and we engineer accordingly.