Selected Work - Engineering

SentiKits - a guided emotional-wellness companion

A mobile emotional-wellness app: curated reflection "kits", a journaling system, a real-time community, an in-app shop, and a server-verified subscription layer - built as one React Native codebase for iOS and Android on a fully serverless Firebase backend.

Role

Founding Engineer

Stack

React Native · Firebase · Cloud Functions

Links

TestFlight (iOS beta) · GitHub

Timeline

2025 - present

01Overview

SentiKits helps people work through emotional moments from their phone: they move through curated kits (decks of reflection cards, journal prompts, and workbook content), journal their progress, connect in community groups, shop physical and digital products, and - soon - talk to an AI companion, SAM. As founding engineer I own the React Native client end-to-end and the Firebase backend - Firestore data modeling, the Cloud Functions layer, security rules, and the subscription / in-app-purchase system.

The app today spans 34 screen modules / ~45 named routes, a backend of 30 Cloud Functions, 20+ Firestore collections, and a 5-state entitlement model - shipping to both iOS and Android from a single codebase, currently in beta (iOS via TestFlight).

02What I built

  • Kits & reflection engine - curated kits made of reflection cards, "new normal" reframes, journal prompts, and workbook chapters, with per-card and per-kit progress tracking - each kit opening with a kit-specific breathing-intro meditation overlay (Reanimated + SVG).

  • Journaling - kit-linked and standalone entries with create/edit/filter, free-tier limits, and unlimited entries for subscribers.

  • Community - groups with posts (text + images), threaded comments, a weekly song feed with voting, direct messaging, user search, and an "Inner Circle" of accepted connections.

  • Shop - an in-app storefront backed by the Shopify Storefront GraphQL API, with a Firestore-cached catalog and a persisted cart.

  • Subscription & redeem-code layer - a 5-state entitlement model (free / trial / redeemer / paid / expired) with server-side Apple App Store receipt verification, plus physical-kit redeem codes generated and validated by admin Cloud Functions.

  • Notifications - an FCM push pipeline and an in-app inbox written only by server-side Firestore triggers (post/comment/like/message/connection events + scheduled broadcasts).

  • Guided onboarding - a 7-step spotlight tour over the core surfaces, reset on sign-out.

  • SAM (designed, coming soon) - a planned AI companion ("Self-Awareness Mediator") with a warm, non-clinical persona and a tiered safety-escalation framework - shipping as a waitlist today, conversational backend not yet live.

03Architecture

Mobile App

React Native 0.80 · TypeScript · iOS + Android

Firebase

serverless · no servers to manage

Auth

email · Google · Apple · phone

Firestore

20+ collections

Cloud Functions

TypeScript · Node 20 · 30 fns

Cloud Storage

user media · FCM push

External

Apple IAP · Shopify · OpenAI

A single React Native client talks to Firebase over the Firebase SDK and HTTPS - there are no servers to manage. Firebase provides Auth (email/password, Google, Apple, phone), Cloud Firestore for all app data, Cloud Functions (TypeScript on Node 20) for trusted server logic, FCM for push, and Cloud Storage for user media. Two external services are live behind the Functions and the client - the Apple App Store Server API for receipt verification and the Shopify Storefront API for the shop catalog - and a third, OpenAI (GPT-4 / Whisper / TTS), is designed for the SAM companion but not yet wired up.

04Technical challenges

Trustworthy subscription billing

Problem
client-reported entitlements can be spoofed, exposing paid features for free.
Approach
moved entitlement state server-side - iOS receipts are verified in a Cloud Function using Apple's official @apple/app-store-server-library, decoding and signature-verifying transactions across PRODUCTION and SANDBOX, then persisting to iap_events / iap_claims. Clients only ever read their entitlement.
Result
entitlements are provable from server state, with a one-subscription-per-account claim model rather than a value the client asserts.

Multi-state entitlement gating

Problem
access depends on a mix of trials, paid subscriptions, and physical-kit redeem codes - each with its own clock - and must stay correct as they start and lapse.
Approach
a 5-state model (free / trial 30d / redeemer 12mo / paid / expired) with feature keys checked through a single useEntitlementGate hook, plus a daily scheduled function that expires lapsed trials/codes and re-checks paid renewals.
Result
consistent gating across the app and self-healing entitlement state.

Real-time community without a server

Problem
posts, comments, likes, and messages need to feel live across users.
Approach
Firestore onSnapshot listeners with disciplined unsubscribe cleanup in the MobX stores, and notification fan-out done entirely in Firestore triggers - the notifications collection is writable only by server-side functions, never the client.
Result
live updates and trustworthy notifications without operating any realtime infrastructure.

Moderation & safety

Problem
a social surface needs block/report and admin moderation to be store-compliant and abuse-resistant.
Approach
block/report write to server-only collections; admin-gated Cloud Functions list and resolve reports and delete offending content (with nested comments), and maintenance scripts take a mandatory backup before any destructive deletion.
Result
a closed moderation loop that the client cannot tamper with.

Performance & UX

Smooth lists and imagery on mid-range phones

Problem
community feeds and avatars can render many remote images and long lists.
Approach
a memoized OptimizedImage component (avatar normalization, loading/error states, a 1.5s fallback so a stalled fetch never blocks the UI), an AppFlatList wrapper with debounced load-more and pull-to-refresh, and MobX observer() scoping so only the components that read a given piece of state re-render.
Result
steady scrolling and predictable re-renders without bespoke list tuning per screen.

Calming entry into emotionally heavy content

Problem
opening a kit on a hard topic shouldn't feel abrupt.
Approach
per-kit breathing-intro overlays - full-screen Reanimated + SVG animations on a timed breathe-in/breathe-out cycle, skippable by tap.
Result
a deliberate, on-brand transition into each kit.
Reflection cards
Journal
Community feed

05Stack & why

React Native + TypeScript to ship one codebase to iOS and Android. MobX for shared, observable client state and React Query for server state - each used where it fits rather than forcing one model everywhere. Firebase to stand up a complete backend - auth, database, server logic, push, storage - without running or scaling servers, which suits a founding-engineer pace. Apple In-App Purchase (verified server-side) plus physical-kit redeem codes for monetisation, and the Shopify Storefront API (client-side, never Admin) for commerce. OpenAI (GPT-4 / Whisper / TTS) is the chosen stack for the SAM companion - designed and queued, not yet wired up.

React NativeTypeScriptMobXReact QueryNativeWindReanimatedFirebaseCloud FirestoreCloud FunctionsFCMApple IAPShopifyOpenAI (planned)Fastlane

06Outcomes

In beta

iOS via TestFlight · Android from the same React Native codebase

34 / ~45

Screen modules / named routes

30

Cloud Functions · callable · triggers · scheduled

20+

Firestore collections

5

Entitlement states · free · trial · redeemer · paid · expired

Server-verified

Apple IAP receipts (App Store Server API)