CASE STUDY / MOBILE MEDIA
MusicFy
Prototype complete
From bare React Native to a complete music playback path
A full-stack mobile music app built without Expo. MusicFy uses React Native, React Navigation, Redux and React Query for the mobile experience, while React Native Track Player and RNFS handle cross-screen playback, queues and local audio files.
01 / MOBILE PRODUCT SCOPE
Why design the mobile product around playback?
MusicFy was not just about putting a list of songs on a phone. Starting with a bare React Native setup meant defining boundaries between the player, navigation, authentication, user-generated content and the device file system. The product needed registration, email verification, uploads, playlists, favourites, listening history and follows while keeping playback alive as users moved between screens.
- Integrate native React Native modules without relying on Expo
- Keep the player, queue, mini player and system media controls working across screens
- Separate Redux global state, React Query server state and device file caching
- Cover authentication, uploads, playlists, favourites, history and follows in one mobile product
02 / PLAYBACK FLOW
How a track moves from the content API to the device
- 01
Authenticate
The app restores a token from AsyncStorage, calls /auth/is-auth to validate the session, and lets the auth slice select the auth or tab navigator.
- 02
Discover
Home uses React Query to fetch latest uploads, recommendations, playlists and recently played tracks without coupling server data to navigation state.
- 03
Cache
Before playback, useAudioController checks the RNFS cache directory. On a miss it starts a background download from the API audio URL before handing the file to the player.
- 04
Queue
AudioData is mapped into a Track Player queue that owns the current track, previous and next actions, playback rate, progress and artwork.
- 05
Control
MiniAudioPlayer, AudioPlayer and playbackService share the same Track Player, so screen controls and Android media controls operate on one playback path.
- 06
History
The playback service listens for progress events and sends audio, progress and date to /history, bringing recently played and listening history back to the server.
03 / ENGINEERING DECISIONS
Mobile decisions visible in the code
- 01
Create a continuous playback boundary with Track Player
ImplementationInitPlayer configures Track Player capabilities and Android media notifications. useAudioController manages queues and playback operations, while playbackService handles remote play, pause and skip events.
ValuePlayback no longer belongs to one screen: users can move between Home, Profile and content views while the same playback path continues.
- 02
Separate two kinds of state with Redux and React Query
ImplementationAuth, player and playlist modal state live in Redux. Latest uploads, recommendations, favourites, history, public profiles and follows are fetched through React Query hooks.
ValueCross-screen state such as the active track and authentication has a stable home, while server data that changes over time is not copied into the global store.
- 03
Keep device caching in the file system, not a state container
ImplementationRNFS derives a cache path from the public ID, checks for an existing file and downloads the remote audio on a miss. AsyncStorage is used for the authentication token rather than audio binaries.
ValueAudio data does not enter Redux or AsyncStorage, reducing memory and serialisation pressure while leaving a clear local boundary for replay.
- 04
Use nested navigators to express the mobile information hierarchy
ImplementationAuth, Home, Profile and upload flows are composed through AuthNavigator, HomeNavigator, ProfileNavigator and TabNavigator. AppView renders the shared player outside individual screens.
ValueNavigation follows product areas and the common player is implemented once instead of being rebuilt by each screen.
- 05
Connect user-generated content into a complete product loop
ImplementationAudioForm combines Yup, native document/image pickers and multipart upload. The Express backend uses Formidable, Cloudinary and MongoDB for audio, artwork, playlists and user relationships.
ValueThe project is more than a player demo: authentication, creation, media publishing, favourites, history and social relationships form an operable product flow.
- 06
Start recommendations with explainable rules
ImplementationThe backend extracts categories from a user’s recent history, filters matching audio and uses a scheduled task to generate automatic playlists. The frontend consumes the result through React Query.
ValueWithout introducing a machine-learning stack, the project establishes an understandable recommendation entry point that can be evaluated with real usage data.
04 / CURRENT BOUNDARIES
A complete prototype still has engineering edges to close
The mobile playback and content flows form a working product skeleton. Download timing, token lifecycle, history writes and backend constraints are the most valuable next improvements.
- High priority
The download helper does not fully await completion
downLoadFile starts RNFS.downloadFile but does not return or await its promise, while onAudioPress continues into the playback flow. On a cold start or weak network the file may not be ready when Track Player receives it; await, failure fallback and duplicate-download control should be added.
- High priority
JWT lifecycle and mobile storage need strengthening
The token is stored in AsyncStorage and the server signing path does not visibly define expiry, rotation or bounded device-token cleanup. This is suitable for prototype validation, but not a complete production session-security story.
- Medium priority
Playback writes and the history model need to converge
playbackService writes /history from progress events, while the history document maintains both last and an embedded all array. Event frequency, idempotency, array growth and offline compensation need a deliberate design before the catalogue grows.
- Medium priority
Media uploads and relationship writes need stronger server constraints
Formidable file limits, cross-document consistency between favourites and audio likes, transaction boundaries for follows, and access checks for private playlists all have room to converge.
- Medium priority
Localisation, testing and observability are not complete capabilities yet
The current code does not show an integrated react-i18next layer, Redis/CDN, push notifications or a full test suite. Recommendations are history-and-category rules, not a machine-learning recommendation system.
05 / NEXT ITERATION
What to improve next
- 01
Make audio downloads awaitable, cancellable and retryable, with cache cleanup and concurrent-request deduplication
- 02
Add short-lived JWTs, refresh rotation, revocation and device limits, then evaluate safer credential storage
- 03
Batch or throttle history writes, cap document growth and design offline event compensation
- 04
Add upload limits, unique constraints and MongoDB transactions, with one authorization rule for private content
- 05
Add unit and integration coverage for playback, uploads, auth and recommendations before evaluating Redis, a CDN or push notifications