Product design and engineering · client project, name withheld
Streaming Platform
A subscription streaming service with more than 500 active users. I designed and built all of it: the viewer app, the design system, the payment and access logic, and the admin panel the client runs it from.
Top 10 this week
Featured
The client and its catalogue are confidential. Every interface on this page is a mock that follows the real layout, with placeholder titles and values withheld.
- 500+
- active users today
- 1
- person: design, front end, API and admin
- 29
- components documented in Storybook
- 5
- areas in the admin panel
When
2026 – present
Problem
Subscribers pay at an external checkout, so the product has to turn a payment into working access before they come back, and answer correctly every time someone presses play.
My role
Sole designer and developer: user flows, access rules, interface, design system, serverless back end and the admin panel.
Result
In production with more than 500 active users, run day to day by a non-technical client from the admin I designed.
The hard part is the minute between paying and watching
The client sells weekly and monthly plans to people who arrive on a phone, often from an ad. They pay at an external checkout, which means the moment of highest intent happens on someone else's page. If access is not ready when they come back, the product fails at the exact moment it was just paid for.
So the design problem was never the catalogue grid. It was everything around it: getting someone from payment to the first play without an account-creation form, deciding what each person sees when they press play, and giving the client a way to run the service day to day without a developer.
Everything, on purpose
I was the only designer and the only developer. That shaped the decisions: every flow I drew was a flow I would also have to build and keep running, so I designed for fewer moving parts. Sign-in is a phone number and a password, because that is what this audience already has in hand. There is no email verification step to lose people in.
Product and flows
Subscription, access rules, cancellation and renewal, mapped before screens.
Interface
Landing page, catalogue, player, profile and billing, mobile first and installable as an app.
Design system
Semantic colour tokens, 47 base components, documented in Storybook.
Engineering
React front end, serverless API, Postgres, payment events, signed video links.
From an ad to the first play in eight steps
I mapped the path as one line and marked which steps the viewer performs and which the system performs for them. Two of the eight have no screen at all, and those two decide whether the experience feels instant or broken.
- 01 · Viewer
Lands on the public page
- 02 · Viewer
Picks a plan
- 03 · Viewer
Pays at the external checkout
- 04 · System
Payment event arrives and access is activated
- 05 · Viewer
Signs in with a phone number
- 06 · Viewer
Browses the catalogue
- 07 · Viewer
Presses play
- 08 · System
Plan is checked and a signed link is issued
Step four is the fragile one. The payment provider reports the purchase to the product, and the product turns that into access. I treated it as a designed step: each event is processed once even if it is sent twice, failures are recorded instead of swallowed, and the admin dashboard shows the health of those events so the client notices a problem before a customer does. A second payment provider is wired in as a fallback.
One play button, six possible answers
Pressing play looks like one action and is really a question: who is this person, what did they pay for, and is it still valid? I wrote the answers as a table first and designed a screen for each one, so that no combination ends in a spinner or a generic error.
This title is part of another plan
See plansYour plan ended
Renew to keep watching.
Renew| The viewer is… | The product… |
|---|---|
| Not signed in | Asked to sign in. |
| Signed in, plan covers the title | The video plays. The link is signed and stops working after three hours, so it cannot be passed around. |
| Signed in, title belongs to another plan | A paywall over the title, with one action: see plans. |
| Plan has expired | A dedicated page that says so plainly and offers renewal. |
| Cancellation requested | Access continues to the end of the paid period; the admin sees it as a pending cancellation. |
| Payment refunded or disputed | Access ends immediately. |
The check runs on the server every time, not in the interface. Hiding a button is a courtesy to the viewer; the rule that protects the client's content lives where it cannot be bypassed.
Making it feel instant on a mid-range phone
Most viewers are on mobile data. Waiting for a video to start is where a streaming product loses people, so I spent the effort on perceived speed. The product starts preparing the video the moment a finger touches a title, before the tap is finished. The catalogue is cached on the device, so returning viewers see it immediately while fresh data loads behind it. It installs as an app and updates in the background without signing anyone out.
The visual decisions serve the same goal. The interface is dark and quiet so the artwork carries it, and the one primary action on the featured title is white on dark: there is never a question about what to press. The red brand colour is reserved for subscription and sign-in.
A panel the client runs without me
The second user of this product is the client. They add titles, answer customers and watch revenue. I designed the admin as five plain areas, each named after the question it answers.
Admin
- Dashboard
- Titles
- Tags
- Users
- Charges
Dashboard
Search users—
Total users
500+
Active subscriptions
—
No active subscription
—
Pending cancellations
—
New users, 7 days
—
New users, 30 days
—
Titles in catalogue
—
Payment events, 30 days
Active plans
Manage users
Search, edit plans, revoke access
Manage titles
Sync from the video CDN, edit the catalogue
- Dashboard
- How is the business today? Users, active subscriptions, pending cancellations, new sign-ups and the health of payment events.
- Titles
- What is in the catalogue? Sync from the video host, edit details, preview as a viewer, choose what appears on the public page and order the Top 10.
- Tags
- How is it organised? The categories viewers browse by.
- Users
- Who is this customer? Search, see and edit the plan, revoke access.
- Charges
- What was paid? Payment history and totals, without opening the payment provider.
The admin deliberately does not use the viewer's dark theme. It is a work tool made of tables and numbers, so it is light, dense and plain.
Small, semantic and documented
The system has two layers. Raw colour values are defined once, and every component refers to them by role (primary, card, muted, destructive) and never by a literal colour. Changing the brand red is one line. Each plan tier, success and warning has its own token, so a state never borrows a colour that means something else.
Components are organised from small to large and documented in Storybook with their variants, including the ones that are awkward to reach in the live product: the paywall, the player, the expired state. Accessibility rules are written into the system and not left to each screen: visible focus on every control, form fields sized so phones do not zoom on tap, safe areas respected on notched screens, and motion that switches off for people who ask for less of it.
- 47
- base components
- 29
- documented in Storybook
- 2
- token layers: value and role
- 13
- test files on access, payment and login
The stack, briefly
- Front end
- React 19, TanStack Start and Router, Tailwind CSS 4, shadcn/ui
- Back end
- Serverless functions, Postgres (Neon)
- Sign-in
- Phone and password, session in an HttpOnly cookie, login rate limiting
- Video
- CDN streaming with links signed per viewer
- Payments
- Two providers through payment events, with failure tracking
- Quality
- Vitest on the access, payment and login paths; Storybook for the interface
In production since mid-2026, with more than 500 active users and one person maintaining it.
A whole product, from one person
This is the kind of work I do best: owning the flow, the interface and the code behind it, including the parts nobody sees. If you need that range on your team, let's talk.