Case Study

News Aggregation Platform

A multi-market news aggregation platform — React Native mobile app, Next.js backend-for-frontend, and shared component library.

Role Sole Engineer
Duration 9 months and counting
Platforms iOS, Android, Web
Markets US, Canada, Germany

The Challenge

The client had an existing PHP-based news aggregation platform serving multiple markets across North America and Europe. They needed a cross-platform mobile app that could integrate with their existing backend while progressively migrating to native experiences.

The app had to support three markets (US, Canada, Germany) with full localization, maintain backward compatibility with the PHP backend during migration, and ship reliably as a solo engineer without dedicated QA.

The core tension: move fast enough to deliver value, but build foundations that wouldn't need to be thrown away.

Architecture

A monorepo with three packages: the React Native mobile app, a Next.js backend-for-frontend, and a shared UI library. The mobile app uses a hybrid approach — WebView for existing PHP content, native screens for new features — with feature flags controlling the rollout.

Mobile AppReact Native / ExpoNative ScreensWebViewtRPC ClientDirect APIHTMLType-safeContent APIREST endpointsNext.js BFFtRPC + ZodPHP BackendPHP Backend (legacy)

Key Engineering Decisions

Incremental Migration

Problem

The existing PHP backend served all content through server-rendered HTML. A full rewrite would take too long and risk breaking the live product.

Approach

Started with a WebView wrapper that loaded the PHP site, then progressively replaced screens with native React Native components behind feature flags. Each screen could be toggled individually — old WebView or new native — with zero downtime.

Result

Shipped native articles, posts, and podcasts screens without a single breaking change. Users on older builds stayed on WebView; new builds got native. Rollback was a config change, not a release.

Session Management with XState

Problem

The PHP backend used PHPSESSID cookies and token-based auth with 30-minute expiry. The mobile app needed to extract, store, and refresh these across WebView ↔ native boundaries.

Approach

Modeled the entire session lifecycle as an XState state machine: initializing → extracting token from WebView → active → expiring → refreshing. Added a React Context bridge so native components could access session state without knowing about XState.

Result

Session management became deterministic and testable. Edge cases like token expiry during navigation, failed extractions, and race conditions between WebView and native were handled declaratively in the machine definition.

End-to-End Type Safety

Problem

The mobile app and BFF were separate packages. Keeping API contracts in sync manually would lead to drift, especially with one engineer shipping both sides.

Approach

Used tRPC to connect the React Native app to the Next.js BFF with full TypeScript inference. Zod schemas validated inputs at runtime. The mobile app imported types directly from the BFF package — no codegen, no OpenAPI specs, no manual sync.

Result

A schema change in the BFF immediately surfaced type errors in the mobile app at compile time. API contracts never drifted. New endpoints were type-safe from minute one.

Feature Flag System

Problem

Needed to ship incomplete features to testers without affecting production users, and toggle behavior per environment without rebuilding.

Approach

Built a four-tier priority system: base defaults (all false) → Firebase Remote Config (shared source of truth) → .env.local overrides (per-developer) → runtime toggles (Settings screen). Added a splash gate to prevent flag-flash on app launch.

Result

New screens shipped behind flags weeks before they were production-ready. Beta testers could toggle features on their device. Firebase gave server-side control without app updates. Developers could override locally without affecting CI.

Tech Stack

React Native 0.79

Cross-platform mobile framework

Expo 53

Managed workflow, EAS builds, OTA updates

TypeScript

Strict-mode across entire monorepo

Next.js

Backend-for-frontend, tRPC server

tRPC 11

End-to-end type-safe API layer

Zod

Runtime schema validation

XState 5

State machines for session and app state

React Query

Data fetching, caching, optimistic updates

Expo Router

File-based navigation for mobile

Firebase Remote Config

Server-side feature flag management

Turborepo

Monorepo build orchestration

Jest + Detox

Unit tests and end-to-end mobile testing

Results

9+

Months

3

Markets

2

Platforms

1

Engineer

The app is live on both iOS and Android via EAS Build, currently in soft launch. Three markets — US, Canada, and Germany — each with localized content and market-specific configuration.

Native screens are replacing WebView screens incrementally, controlled by feature flags, with zero downtime and instant rollback capability. The monorepo structure keeps shared types and components in sync across the mobile app and BFF.

Reflections

Building a full product solo forces you to make deliberate trade-offs. There's no team to absorb complexity — every abstraction, every dependency, every architectural decision is yours to maintain. That constraint is clarifying. It pushes you toward simpler designs and incremental approaches.

The biggest lesson: invest in the migration path, not the end state. Feature flags, backward-compatible context bridges, and hybrid rendering let me ship value continuously while the architecture evolves underneath. The product is never “in transition” — every commit is a working, deployable build.

Let's build something

I'm available for new projects. If you're a startup or scale-up looking for a product engineer, let's talk.