Case study

A 4K streaming player for Samsung and LG televisions

A media player built for televisions rather than ported to them: one codebase across Samsung Tizen and LG webOS, running on hardware a decade old, with navigation designed for a remote control and a backend that can change the application's behaviour after it has shipped.

Stack

Built with

  • TypeScript
  • Preact
  • Vite
  • Tizen (Samsung)
  • webOS (LG)
  • AVPlay
  • Shaka Player
  • IndexedDB
  • Java 21
  • Spring Boot
  • PostgreSQL
  • Docker

A browser engine from 2015, in a living room today

Samsung and LG televisions run web applications, which sounds like familiar ground until you look at what they run them on. A set sold in 2018 is still in service, and its engine is roughly Chromium 47. It has a fraction of the memory a phone has and a CPU to match, and it is being asked to decode 4K video at the same time as it renders your interface.

The application draws onto a fixed 1920 by 1080 canvas that the television scales to its own panel, so a 4K set changes sharpness and nothing else. That one decision removed an entire class of layout bug before it could exist, and made every measurement we took comparable across very different hardware.

  • No flexbox gap: spacing is a margin on the child, every time.
  • No CSS grid: every layout is flexbox or absolute positioning.
  • No blur and no heavy shadows: they cost frames the video decoder needs.
  • Only transform and opacity are ever animated, because everything else triggers layout.

Constraints this hard are clarifying. There is exactly one way to build most of the interface, and it is the fast way.

Lists that stay smooth on a television processor

Channel lists run to thousands of entries. Rendering them all is out of the question, and ordinary virtualisation still re-renders on every focus move, which on this hardware is enough to drop frames.

Instead the visible window is a fixed set of row elements that never unmount. Moving the focus writes new text and new state directly into those rows, bypassing the framework's render path completely. On a real television the profiler we built into the application reported zero component renders per second while the viewer scrolled: the work had left the render cycle entirely.

Profiling on the device, because the laptop lies

Everything felt instant in a desktop browser and sluggish on an actual set. That gap is the normal state of affairs on this platform and the reason so many television applications ship slow. Retail televisions have no usable developer tools, so we built a performance overlay into the application itself and read it from the sofa.

It redirected the work immediately. Frame times during navigation sat around 165 to 265 milliseconds with the video preview disabled, and between 0.5 and 1.3 seconds with it running. The bottleneck was never the interface. It was the decoder competing for the same silicon, and no amount of further component optimisation would have bought a thing.

Measuring first is not a process preference on hardware like this. It is the difference between a week of real improvement and a month spent tuning the wrong layer.

The backend a fleet of devices needs

Behind the application sits a Spring Boot service on Java: a device registry, licensing and activation, per-device configuration, and a settings pipeline that lets an operator change behaviour on televisions already in living rooms without shipping a new build.

A device identifies itself once at start-up and receives everything it needs in a single response: feature flags, limits, pricing, the lot. The application caches that in IndexedDB and keeps working when the network does not. Settings are scoped by platform, so a flag can apply to Samsung sets and not to others, and the panel that edits them is the same one the support team uses daily. That is backend work in service of a product decision: being able to change your mind after the firmware is out of your hands.

Getting through store review

Submitting to Samsung's store is a project of its own. It wants icons and screenshots at exact dimensions, a description that survives review, an age rating that matches what the application actually does, and legal terms that state plainly what the software is for and what it is not.

We generate every store asset from one set of vector masters through a build script, so a brand change regenerates the entire pack byte for byte instead of being redrawn by hand. That matters more than it sounds. The second submission is where most teams lose a fortnight.

Outcome

What shipped

  • 01

    Runs on hardware from 2015

    One codebase across Samsung Tizen and LG webOS, targeting an engine roughly equivalent to Chromium 47, without drowning in polyfills.

  • 02

    Navigation that never surprises

    An explicit index-based focus model, throttled key repeat, one move per animation frame, geometric search only as a fallback.

  • 03

    Thousands of rows, zero re-renders

    A fixed window of recycled rows updated imperatively, measured on a real set at zero component renders per second while scrolling.

  • 04

    Changeable after it ships

    Feature flags, limits and pricing delivered in the start-up payload and cached offline, so behaviour changes without a store resubmission.

  • 05

    Twenty interface languages

    Including full right-to-left layout, with translation completeness enforced by the build rather than checked by hand.

FAQ

Frequently asked questions

Can one codebase really cover both Samsung and LG?

Yes, with care. Tizen and webOS both run web applications and the shared surface is large, so the application logic, layout and navigation are identical on both. What differs is playback: Samsung sets use the native AVPlay interface, LG uses a standard media element driven by Shaka Player. Isolate that behind a single interface and the rest of the application never needs to know which television it is running on.

Why a web application rather than a native toolkit?

Because no native toolkit covers both. Tizen and webOS are web-first platforms, and their native paths diverge sharply and are thinly documented. A web application with a disciplined rendering strategy is both the shortest route to shipping on both platforms and the easiest thing to keep alive on hardware that will still be in service in five years.

How do you test on televisions you do not own?

You buy the oldest set you can find, because it is the one that will fail first. A current model hides every performance problem you have. Beyond that: vendor emulators for functional work, a throttled desktop browser for layout, and an in-application performance overlay for anything to do with speed, since retail sets expose no developer tools at all.

How long does Samsung store review take?

Plan in weeks rather than days, and plan for at least one rejection. Most rejections concern store assets, the age rating or the wording of the description rather than the software itself. Generating the asset pack from vector masters and writing the store copy before you submit removes most of that risk.

Have a project in mind?

Let's build something exceptional.

Tell us where you are and where you want to go. We'll reply within one business day with honest next steps, even if that means pointing you elsewhere.