What we build / Cross-platform

One codebase across four television runtimes

This is the technical argument for cross-platform TV app development, not the sales pitch. If you are the person who has to decide whether a shared codebase is real engineering or a story told to win a tender, it is written for you — including the parts that do not share.

The problem

An HbbTV terminal browser bound by ETSI TS 102 796. Tizen's Chromium-derived runtime. webOS. Titan OS. Whale OS. Different key codes, different media pipelines, different application lifecycles, different packaging, different review queues — and, usually, five teams who each learn one of them.

The default answer is separate builds. The default outcome is divergence: by the second year the five applications no longer agree on what a programme is, and every feature is scoped five times. The feature your editorial team asked for ships on two platforms, and nobody can say exactly why it did not ship on the other two.

The architecture

Targets

  • HbbTV browser runtime
    URL + Content-Type
    no store
  • Samsung Tizen Chromium runtime
    .wgt
    Seller Office
  • LG webOS Chromium runtime
    .ipk
    Content Store
  • Titan OS Chromium runtime
    hosted URL
    Titan OS store
  • Whale OS HTML5 browser runtime
    hosted URL
    Whale OS App Store

Adapters

  • HbbTV adapter: input · media · lifecycle · storage · packaging
  • Samsung Tizen adapter: input · media · lifecycle · storage · packaging
  • LG webOS adapter: input · media · lifecycle · storage · packaging
  • Titan OS adapter: input · media · lifecycle · storage · packaging
  • Whale OS adapter: input · media · lifecycle · storage · packaging

The only platform-specific code — about 10%

Shared

One React application — about 90% of the codebase

  • Screens & routing
  • Component library & design tokens
  • Domain model & state
  • API clients — REST + GraphQL

Backend

  • Headless Drupal
  • Elasticsearch
  • EPG ingest
  • VAST ad server
  • Livestream origins
Read it from the bottom. One application holds the screens, the component library, the domain model and the API clients. Above it sits a thin adapter per runtime. Above that, four televisions that each want something different.

Shared

What is genuinely shared

The data layer

API clients, caching, and the contract with the CMS. One place where a programme, a series and a stream are defined, so all five platforms agree on what they are showing.

Domain and state

Continue-watching, favourites, the rules about what may be played where. Business logic written once.

The component library

Every screen is built from the same React components and the same design tokens, so a change to a tile is a change to every tile on every set.

Routing and composition

The same navigation model everywhere. A viewer who knows your app on one television knows it on the next.

Not shared

What is not shared, and why not

Five seams. Anyone who tells you there are none has not shipped on five runtimes.

Close-up of a broadcast video patch panel with several patch cords connected
One signal, four destinations, and a short piece of dedicated wiring for each.
Input
On HbbTV a key press reaches your application only if five separate conditions hold — the keyset, two kinds of focus, Table 12, and the arrow-key priority of clause 10.2.2.1. Tizen wants registerKey. And webOS has the Magic Remote, which is a pointer, not a d-pad: that is an interaction-design problem, not a key-mapping one, and it is the seam that most often surprises people.
Media
video/broadcast and the A/V control object on HbbTV, AVPlay on Tizen, webOS media on webOS. Different DRM, different codec support, and different failure modes at the same bitrate.
Lifecycle
destroyApplication() against native suspend and resume, and four different answers to what the back button does on the first screen.
Packaging
Two of the five want a signed package: a .wgt through Samsung Seller Office, an .ipk through the LG Content Store. The other three want a URL — HbbTV with the right Content-Type and no review at all, Titan OS and Whale OS as a hosted application behind a submission. The asymmetry is not a detail: it decides your release calendar, and it is the reason a fix reaches three of the five the same afternoon and the other two when a queue says so.
Performance
The oldest set you still support sets the budget for every set, and it is a different device on each platform. This is the constraint that decides how much React you can actually afford.
The five conditions a key press must satisfy before an HbbTV application sees it A key press enters at the top and passes five gates before reaching the application: the key's group must be in the application's keyset; the application must have input focus; focus must not be inside a text-entry field; the key code must appear in Table 12 of the standard; and for the four arrow keys the application is offered the event before the terminal's own navigation uses it. The full text of each condition is written out below the drawing. A key press 1 The group is in the application's keyset OIPF DAE R2 Vol. 5 §7.2.5.1 · HbbTV Table 12 2 The application has input focus TS 102 796 §10.2.2.1, p. 138 — A13, A14 3 Focus is not inside a text-entry field TS 102 796 §10.2.2.1, pp. 138 f. — A16 4 The key code appears in Table 12 TS 102 796 §10.2.2.1, p. 137 — A2 5 Arrow keys: the application goes first TS 102 796 §10.2.2.1, p. 138 — A10 Your application
Five conditions, and the standard does not say in which order a terminal tests them — only that all five hold. Most “the red button does nothing” bug reports are one of these, and on a real set you cannot see which.
The same thing in words
  1. Keyset. A key is only delivered if its group is in the set the application asked for. setValue(v) yields v & maximumValue: the terminal grants at most what it supports, and it is explicitly allowed to deliver more than you asked for.
  2. Application focus. “An HbbTV® application that does not have focus shall not receive key events.” An application that is not visible does not have focus.
  3. Element focus. If focus sits in an <input> of a type that accepts text, or a <textarea>, the key belongs to the field. A checkbox is not such a type — the arrow key over it is yours.
  4. Table 12. “Key events which do not have a key code listed in Table 12 shall be handled by the implementation and not delivered to applications.”
  5. Arrow priority. On up, down, left and right, the terminal must offer the event to the application before using its own navigation. Enter and Back are in the same keyset group but are not in that list.

The bench

Four television sets side by side on a test bench, each showing an abstract field of light
Every release ships to five runtimes. Three take it the same afternoon; the other two when a review queue says so.

Costs

What it costs, and what it buys

A shared architecture costs more up front than one application for one platform, and less than two. The return is not in the first release. It is in every release after it, and it compounds: one release train, one QA pass, one feature request.

It also stops making sense somewhere, and we would rather say where. Below two platforms it is overhead you do not need. And if one platform's experience has to diverge fundamentally rather than cosmetically, forcing it into the shared model gets you the worst of both — a codebase with a branch in it that nobody wants to touch.

Tell us what you are building.

Christian answers these himself, usually within a working day.

Start a conversation