All projects
Mobile app

Sage

An AI companion you talk to — brought from the web to iOS and Android as a real native app, not a wrapped website.

Sage — screenshot
Client
Inner Sage (UK)
Role
Sole mobile developer
Platform
iOS + Android (React Native, Expo)
Type
Native rebuild of an existing web product
Status
Built, in store submission
// overview

Sage is an AI companion people talk to — by typing or by voice — for reflection, perspective and gentle accountability. The web product already existed; this project brought it to iOS and Android as a genuinely native app rather than a wrapped website.

The brief was to match the web product exactly — same screens, same behaviour, same design language — while being a real native app. Nothing was wrapped in a webview.

The existing Supabase backend, database and AI services were reused as-is, so users move between web and mobile with one account and one subscription. Where mobile genuinely needed something the web did not, the backend was extended rather than duplicated: push notifications, for example, had to learn to reach phones alongside browsers without changing anything the web relied on.

Delivered in milestones, each one ending in a build the client installed and tested on their own device before the next began.

Scale
2
Platforms, natively
0
Webviews
1
Backend shared with the web app
2
Billing systems, one entitlement
6
External services integrated
3
Themes and text sizes
// what it does

Key features

Conversation

  • Conversational AI chat with streaming replies
  • Saved conversation history
  • Voice-to-voice mode — speak to Sage, hear her reply, hands free
  • Dictation for speaking a single message into the composer before sending

Reflection & wisdom

  • Journey events — log what is coming up, and Sage checks in before and after
  • Daily wisdom and weekly insights, with a browsable archive
  • Shareable cards that turn a piece of wisdom into a branded image

Platform integration

  • Push notifications across both platforms
  • Subscriptions via in-app purchase, alongside the web’s existing billing
  • Universal Links and App Links so email links open the app when installed

Personalisation & admin

  • Three themes and three text sizes, matching the web product
  • Nickname and profile settings
  • Granular notification controls
  • Admin dashboard for the client
// engineering

The hard parts

The problems that shaped the architecture, and how each one was solved.

01

Streaming AI replies on a platform that buffers them

React Native’s fetch buffers a response rather than exposing a readable stream, which makes server-sent events arrive all at once. Using the WinterCG fetch shipped with Expo gave a real ReadableStream, so replies type out as they are generated, exactly as on the web.

02

Voice conversation without a Web Audio API

The web detects when someone has stopped speaking using RMS amplitude from an AnalyserNode. React Native has no equivalent, so the same behaviour was rebuilt on the microphone’s dBFS metering — converting the web’s thresholds rather than re-inventing them, then calibrating to the room’s noise floor at the start of every call so it works in a quiet bedroom and a noisy café alike.

03

A platform-specific audio strategy

Speech is synthesised sentence by sentence to keep latency low. On Android each player instance holds a hardware media decoder from a small pool, and creating one per sentence exhausted it — after which the app’s audio was dead until the process was killed. On iOS the opposite was true: reusing one player introduced stuttering, because swapping its source is asynchronous there. The fix was to let each platform do what suits it, and to say so plainly in the code.

04

Encrypted sessions on a store with a size limit

The iOS keychain caps individual values well below the size of a session token. Sessions are encrypted with AES-256 whose key lives in the secure store and whose ciphertext lives in ordinary storage — a fresh key per write, so the same key is never reused.

05

One subscription, two payment systems

Neither app store permits Stripe for a subscription used inside an app, but the web product runs on Stripe and its existing subscribers had to keep working. Both now write to the same record and the backend grants access from that alone — so a subscription bought on the website unlocks the app, and one bought in the app unlocks the website, with neither system aware of the other.

06

Email links that open the app, not the browser

Verification and password-reset emails point at the website. Claiming those URLs through Universal Links and App Links means they open the app when it is installed, and the site when it is not — without changing a single email template.

// stack

Built with

App

React Native 0.86Expo SDK 57TypeScriptExpo Router (file-based, typed)ZustandReanimated

Backend

Supabase Postgres (existing, extended)Supabase AuthRow Level SecurityEdge Functions (Deno)

AI & voice

Claude API (conversation)ElevenLabs (speech synthesis)ElevenLabs (transcription)

Payments & push

RevenueCatStoreKitGoogle Play BillingStripe (existing web billing)Firebase Cloud MessagingAPNs

Tooling

EAS BuildGradleXcode toolchain
// screens

Inside the app

Tap any screenshot to open it full size.

Three of Sage’s screens: the conversation, the weekly reflection, and the theme picker.
Replies stream in as they are generated, with the week’s insight pinned above the conversation.
Weekly reflections, with an archive and a share action.
Daily wisdom arrives as a push notification and stays in a browsable list.
Log what is coming up and choose when Sage checks in — before and after.
Three themes and three text sizes, matching the web product exactly.
Granular push controls, alongside the client’s admin dashboard entry point.
Available for hire

Ready to bring your
idea to life?

Let's discuss your project and build something exceptional together. Get in touch via Fiverr, WhatsApp, or send me a message.

> haseeb_

Full Stack Developer specializing in MERN, React Native, Supabase & Firebase. Turning ideas into production-ready applications.

Quick Links

Connect

© 2026 Haseeb Ansari. All rights reserved.

Built with React + TypeScript