
Cross-platform mobile app with personalized programs, admin dashboards, and AI-ready backend.
Param Life brings together a holistic approach to wellbeing across practices such as positive psychology, yoga, Ayurveda and meditation. The challenge wasn't simply to build an app — it was to turn that methodology into a product system: personalized programs, habit formation, guided content and a growing media library, all manageable by the Param team without depending on us for every content change.
We treated Param as a product platform rather than a single app. That meant separating the consumer experience from content operations: a fast cross-platform Flutter client purely for consuming content, a dedicated React web admin portal where the Param team uploads and manages every type of content independently, and asynchronous infrastructure so heavy media processing never blocks the API.
Client
Cross-platform consumer app for iOS and Android — a pure content consumption surface with no upload capability.
API
Core product and content services, plus event-driven status push over WebSockets.
Data
Structured, relational storage for users, programs, habits and content metadata.
Admin
Web portal where the Param team uploads and manages content of every type — video, audio, images and structured program data — independently of mobile releases.
Async infrastructure
Background job processing for media transcoding, notifications and status updates.
Wellness content is video-heavy, so upload, transcoding and delivery are fully decoupled from the request/response cycle — each stage hands off asynchronously to the next.
The React admin portal requests a short-lived presigned URL from the API and uploads the raw file — video, audio or image — straight to a private S3 bucket, whatever the content type. The Flutter app never uploads; it only consumes what's published.
The completed upload emits an event that enqueues a transcoding job in BullMQ, backed by Valkey, fully decoupling the upload from processing.
AWS MediaConvert picks up the job and transforms the source video into multiple HLS renditions plus preview thumbnails, sized for different network conditions.
On completion, the backend pushes a real-time status update over WebSockets straight to the admin portal, so the team sees content go live the moment it's ready — no polling, no refreshing.
Processed HLS streams and thumbnails are served through CloudFront, keeping playback fast for users regardless of location or device.
Problem 1
Large content uploads — video especially — would block API requests if handled synchronously, and transcoding time is unpredictable, so polling for status wastes requests and still feels slow.
Solution
We decoupled upload from processing entirely. The React admin portal gets a presigned URL and uploads directly to S3, bypassing our API completely. A finished-upload event enqueues a BullMQ job that drives AWS MediaConvert, generating HLS renditions and thumbnails. Completion is pushed back to the admin portal over a WebSocket instead of polled.
Impact: The API stays fast and available regardless of file size or transcoding load, and the content team sees an item go 'ready' the moment it actually is.
Problem 2
Every content update — a new program, a swapped meditation track, a reordered collection — would otherwise require a mobile release and app-store review cycle.
Solution
We built a dedicated React admin portal on top of the same Prisma-modeled PostgreSQL schema, with structured entities for programs, collections and content items rather than free-form blobs. The Param team edits and publishes directly; the mobile client just fetches current state.
Impact: Content velocity is fully decoupled from release cadence — new programs can ship the same day, with no engineering involvement.
Problem 3
The product needed to support personalization and AI-assisted recommendations down the line, without a future data-model rewrite.
Solution
Programs, habits, content and engagement are modeled as structured, queryable relations from day one — not opaque JSON blobs — with the events needed to drive recommendations already being captured.
Impact: Personalization becomes an additive layer on existing data rather than a migration, so the team can move directly into that work when ready.
A single Flutter codebase delivers the core mobile experience across iOS and Android.
A React admin portal handles content of every type — video, audio, images and program data — entirely separate from the consumer app, run independently by the Param team.
Video transcoding and related heavy lifting run as background workflows instead of blocking user-facing requests.
The product foundation leaves room for deeper recommendation and AI-assisted experiences as the platform grows.
Building something similar?
Let's Talk