Recorder
Recorder: native mobile apps for Romania's most-trusted independent newsroom
Two native apps (iOS + Android), a WordPress-backed REST API, and a full payments stack — engineered to last and ship investigative journalism into millions of pockets.
Outcomes
- Two native apps shipped and continuously maintained on the App Store and Google Play
- Full Braintree → Stripe payments migration, zero downtime, zero lost subscribers
- ANAF Form 230 (Romanian tax-deduction) flow integrated end-to-end inside the apps
- Live in production through a complete WordPress backend rewrite of the donations stack
Stack
The client
Recorder is the leading independent investigative journalism outlet in Romania. Funded almost entirely by reader donations, it produces long-form video investigations that have repeatedly shaped the public debate. It is — by every reasonable metric — one of the most consequential newsrooms in the country.
A platform like that doesn't get to crash on Sunday morning. The apps and the donations stack have to just work.
The challenge
When the partnership started, the mobile experience was a gap. Readers came in through the website, but the most loyal audience — the people who watch every investigation, who donate monthly, who refer friends — wanted a real app. Not a webview. Not a wrapper. Something that loads instantly, plays video flawlessly, lets them donate in two taps, and respects their data.
On top of that, the payments stack was on Braintree (PayPal). Stripe had become the better fit — better Romanian-language UX, better recurring billing, better fraud protection, better developer ergonomics — but moving thousands of active monthly subscribers from one processor to another, without losing a single one, is the kind of project that companies usually botch.
What we built
Two truly native apps
- iOS — Swift + SwiftUI, MVVM with Combine, Swinject for DI, Alamofire for networking, Firebase for auth and push
- Android — Kotlin + Jetpack Compose, single-module Gradle with
dev/prodflavors pointing at the test and production WordPress backends
Both apps share the same product surface: home feed, daily news, video player, search, account, donations history, FAQ, support, onboarding. They consume the same mobile-api/v1 REST contract, so a feature shipped on one platform lands on the other within days.
A REST API on top of WordPress
The Recorder editorial team lives in WordPress. Asking them to migrate to a headless CMS just so the apps can have a clean API is the wrong trade-off — it taxes the people who actually produce the journalism every day.
Instead, we shipped a WordPress mu-plugin that exposes a clean mobile-api/v1 namespace: authentication, articles, dashboard, menu, FAQ, donations, profile management — all on top of the existing editorial workflow. Firebase verifies the ID token; the server issues a JWT with a 240-day expiry; every authenticated request additionally carries an x-recorder-auth header. ACF handles the metadata that the apps need but the website doesn't surface.
The Braintree → Stripe migration
The most stressful part. We built a transactional migration system:
- Export & normalize — pull every active subscription from Braintree into a CSV with a stable mapping to Stripe customer IDs
- Stripe import with duplicate prevention — recreate every subscription in Stripe, idempotently
- Braintree cancellation, only on Stripe success — for every successful Stripe import, cancel the corresponding Braintree subscription in the same transaction
- CSV reporting — every success and every failure is recorded; nothing is silently lost
Result: thousands of donors moved cleanly between processors, zero billing complaints, zero lost recurring revenue.
ANAF Form 230 — Romanian tax-deduction in mobile
In Romania, individuals can redirect 3.5% of their income tax to a non-profit by submitting Form 230 to ANAF (the national tax authority). Most NGOs collect it via paper or PDF. We built it into the apps: the user fills the form once, the system generates a compliant PDF, accumulates submissions, and produces signed borderouri (batch declarations) ready to file with ANAF. Boring on the surface; high-leverage in practice — every batch that lands at ANAF unlocks real funding for the newsroom.
Engineering practices we brought
- Two production environments, one codebase —
devflavor →test.recorder.ro,prodflavor →recorder.ro. Every change is QA'd on dev before it touches production - Single source of truth for the API contract — when the WordPress plugin changes, both apps are aligned in the same PR cycle
- Cursor Cloud-friendly repos — every project has an
AGENTS.mdso AI agents (and new humans) can ramp up in minutes - Zero-downtime releases — backwards-compatible API changes, feature flags, staged rollouts on the stores
Outcomes
- Two native apps live and maintained on iOS and Android, with feature parity and shared API
- Complete Braintree → Stripe migration with zero lost subscribers — the system is open-sourceable IP that can be reused for any subscription business doing the same move
- Form 230 integrated and operational, generating compliant ANAF deliverables on demand
- A multi-year partnership that survives editorial sprints, payment-processor migrations, OS updates, and a long product roadmap
Real journalism deserves real engineering. We're proud this one is in our portfolio.
