Case study // 12
EVC
A two-sided music and video streaming app, designed first and then built in Flutter.
- Role
- Designer & engineer
- Year
- 2026
- Category
- Mobile
- Status
- Live
// CONTEXT
The problem
EVC began as 39 exported Adobe XD screens at 375×812 — a near-monochrome burgundy streaming app, fully drawn and entirely static. The brief was to turn a picture of an app into a running one: both sides of a two-sided marketplace, where listeners stream, own, rent and gift titles while creators publish and monetise their own work, from a single Flutter codebase that holds up on a phone and in a browser.
// CONSTRAINTS
What made it hard
- The design came first and was finished. The implementation had to match 39 comps rather than reinterpret them, which makes visual drift a correctness problem instead of a matter of taste.
- Two audiences share one app. A listener browsing a catalogue and a creator reading their earnings are different products wearing the same navigation.
- No backend and no payment provider, yet every flow — including owning, renting and gifting — had to be demonstrable end to end.
- One codebase targeting Android, iOS and web, where the same layout has to survive both a 393pt handset and a 2560px desktop window.
// DECISIONS
What I chose, and what I didn't
- 01
Extract a token file and twenty shared components from the design set before building a single screen, with a /gallery route that renders every component in its real states.
WhyThirty-nine screens that share type, spacing and colour will drift apart if each is built independently. One token file means a colour changes in one place, and the gallery makes drift visible immediately rather than three screens later.
Instead ofBuilding screens one at a time straight from the PNGs, which is faster for the first five and unmaintainable by the twentieth.
- 02
Put every catalogue read behind a MediaRepository interface, implemented over mock data.
WhyNo backend existed, but the shape of the data was already knowable from the designs. Screens depend on the interface alone, so swapping the mock for HTTP or Firestore touches no screen code.
Instead ofReading mock lists directly inside the widgets, which demos identically today and has to be unpicked from 26 screens the day a real API arrives.
- 03
Golden-render all 26 screens in the test suite, and load the real font files into the test binding.
WhyWidget tests ship without font assets, so text renders as placeholder boxes and a golden proves nothing about type — which is most of what this design is. Loading the bundled faces turns the goldens into an actual visual record, and they double as the screenshot set in the README.
Instead ofManual review, on a project whose entire value proposition is that it matches the comps.
- 04
Audit the screens against Flutter's WCAG guidelines and change the design where it failed, then enforce the result in tests.
WhyThe audit found three real defects in the original comps: muted text below the contrast threshold, list rows that clipped a third meta line, and controls under the 48dp Android minimum. Fixing them in the token file and the shared components rather than screen by screen means the fix is structural, and the accessibility suite stops it regressing.
Instead ofImplementing the comps exactly as drawn. Fidelity to a design is the goal right up to the point where the design is wrong.
- 05
Letterbox the app into a phone-sized frame above 700px wide instead of making it responsive.
WhyEVC is a phone app. Stretched across a desktop window the layouts stayed technically valid but read as broken — rails running into empty space, a tab bar spanning the whole window. The frame hands its subtree a MediaQuery reporting phone dimensions, so every screen lays out exactly as it does on hardware, and real phones are untouched.
Instead ofBuilding desktop breakpoints for a product that has no desktop design, which is a second design job nobody commissioned.
// OUTCOME
What came of it
- 26 screens across both sides of the marketplace, running from one codebase on Android and on the web.
- 59 tests passing: a golden render of every screen, behaviour coverage of the state layer, and a WCAG audit across ten screens.
- Three accessibility defects found in the original design and fixed in the tokens and shared components, then locked down by tests.
- 6,600 lines of Dart across 47 files, with the catalogue behind a repository interface that no screen depends on.
// REFLECTION
What I'd do differently
The placeholder artwork came straight from the design comps, which made the prototype quick to assemble and impossible to publish — those images are copyrighted, so a public build needs every one replaced first. Sourcing licensed or generated art when the mock catalogue was written would have cost a day then and saved a rebuild now. The same gap runs through the ownership model: own, rent and gift all work against mocks, but the genuinely hard part, reconciling entitlements against real payments, is precisely what a mock cannot prove.
