A streaming experience, from the creator’s upload to the viewer’s next play.
PerseusTV+ is a streaming product with several connected surfaces: a viewer app, creator tools, an operations dashboard, backend services, and a public download website. My freelance work spans these surfaces, especially the boundaries between the player, content access, media delivery, and publishing workflows.
Public store snapshot · . Downloads are not active users.
Engagement
Freelance development
Focus
Cross-platform product engineering
Case-study basis
Implementation and test-source review · September 2026
The problem behind the screens
A working video screen is only one part of a streaming product. Content has to finish processing before it can be watched; access rules must agree across the app and server; interrupted playback needs a recovery path; and creators need to understand what happened to an upload. Older app versions also need a compatible view of a changing catalogue.
My role
My contribution spans Flutter client development, React administration interfaces, Node.js API integration and services, media-delivery integration, and the download website. This is a description of my engineering scope, not a claim that I single-handedly created every dependency or service in the system.
One product, different responsibilities
The viewer, creator, and operator need different interfaces. The shared backend coordinates the rules and data between them.
Viewer application
Flutter · Riverpod · Dio · media_kit
Content browsing, playback-session integration, player recovery, watch progress, and version-compatible media responses.
Creator workspace
React · TypeScript · TanStack Query
Video upload and processing feedback, posts, playlists, comments, and channel-management workflows.
Operations dashboard
React · TypeScript · role-aware interfaces
Separate operational interfaces for managing channels, content, and review workflows.
Application services
Node.js · Express · MongoDB
Content metadata, publication and access checks, playback sessions, and compatibility rules for different app generations.
Media delivery
HLS · object storage · signed delivery
Railway-backed media storage and an authorized delivery path. CDN-backed delivery is configuration-dependent, not a claim that every environment uses the same route.
Public download website
React · Vite · Tailwind CSS · Express · Railway
I built download.perseus-tv.app, including the app-download experience, same-origin API proxy, share-page metadata, and mobile app-link association support.
From upload to playback
A simplified engineering flow. Storage and CDN routing depend on the deployed configuration.
01
Prepare the content
A creator uploads through the web workspace. Multipart transfer and media processing are separate states; completing an upload does not mean the video is ready to watch.
02
Request playback
The Flutter app asks the API for a playback session. The backend checks identity, content readiness, publication, channel availability, and the applicable viewing entitlement.
03
Return a scoped session
An authorized request receives an expiring session and manifest information. The client resolves the media source before handing it to the player.
04
Deliver and recover
The player loads HLS media through the authorized delivery path. In the configured CDN path, media bytes are delivered outside the application server; playback failures use a bounded recovery policy.
05
Remember progress
Playback position is saved locally, with cloud synchronization when enabled. Ordered writes keep a late progress update from overtaking a completion update.
The engineering decisions
Five examples of the constraints and implementation choices behind the product.
Recover the player without an endless restart loop
Challenge
An error before playback begins is different from a transient failure after the video has already advanced. Treating both as an immediate restart can fight the native player’s own recovery.
Implementation
The retry policy distinguishes startup from recovered playback, caps startup attempts, and allows a recovery grace period after progress. Recovery is determined by an advancing playback position, not just a successful player initialization.
Trade-off
Bounded retries may still end in a visible error on a poor connection. The aim is predictable failure and recovery, not a promise of uninterrupted playback on every network.
Keep watch progress responsive and ordered
Challenge
Saving every player event remotely adds unnecessary writes. Concurrent updates can also leave an older position arriving after a newer or completed state.
Implementation
A local progress store provides a resume point. Cloud writes are throttled and serialized, with increasing sequence values and session information. Completed local entries restart from the beginning rather than resuming at the end.
Trade-off
Local and cloud state are not instantly identical. This favours a useful local experience while explicitly managing synchronization and session conflicts.
Make upload progress mean something
Challenge
Large video uploads can fail partway through, and successful transfer is not the same as successful processing. A single “uploading” spinner hides both problems.
Implementation
The creator uploader separates initialization, part transfer, completion, processing, readiness, failure, and cancellation. It uses bounded concurrency, part retries, progress reporting, and processing-status polling.
Trade-off
The interface has more states to explain, but creators can distinguish a transfer problem from a processing problem. Part-level retries are not presented as guaranteed resume after closing the browser.
Keep access decisions on the server
Challenge
Hiding a video in the interface is not an access-control boundary. A playable item also needs consistent readiness, publication, channel, and subscription checks.
Implementation
The backend evaluates those rules before issuing a scoped, expiring playback session. The client handles the resulting playback or access state rather than deciding entitlement from UI flags alone.
Trade-off
Session expiry and authorization failures become part of the player experience. Signed delivery limits access; it is not a claim that content is impossible to copy or that a DRM rollout has been verified.
Evolve the catalogue without assuming every client has updated
Challenge
New content types and channel behaviour can reach the backend before older mobile clients understand them.
Implementation
Version-aware visibility rules distinguish app generations and restrict newer content where needed. Compatibility tests cover missing version information, older clients, and newer-client access to the expanded catalogue.
Trade-off
Supporting old clients adds backend branching and test cases. I treat compatibility as an explicit contract instead of relying on everyone upgrading immediately.
Evidence & verification
Playback behaviour
Existing tests exercise bounded retries, recovery based on actual position progress, HLS session parsing, and media-model compatibility.
Progress consistency
Existing tracker tests cover completed-item resume behaviour and ordered cloud updates with increasing sequences.
Client compatibility
Backend tests exercise generation detection and catalogue visibility rules for old and new clients.
Public-facing work
The download website is a public example of my web contribution. Internal dashboards and customer data are intentionally not reproduced here.
Scope of this review
This account is grounded in reviewed implementation and existing test source. It is not a fresh end-to-end production audit or a report that those tests were rerun for this page. Device playback, network behaviour, and CDN configuration need separate live verification. Public store listings, download milestones, and ratings were checked separately on 23 September 2026 and are linked above. Downloads do not measure active users. No uptime, revenue, crash-free rate, or performance-improvement metrics are claimed.
What this work demonstrates
The strongest part of this work is not the number of screens. It is connecting the viewer experience to the operational system: a creator can see processing state, the server makes access decisions, the player has a bounded recovery path, and watch progress has an explicit synchronization model.
I can discuss the client, API, and delivery trade-offs in an interview without exposing private source code or customer data.