EM — Accra, GH
Work2026

Monterosa / Fanatics · Feb – May 2026

A live match, rebuilt as geometry

A real-time 3D visualisation of live football, rendered in the browser while the match is still being played. The feed arrives as a stream of loosely-related messages from Sportradar; the screen has to show a coherent pitch, a ball with plausible physics, and a camera that knows what it should be looking at.

Role
Frontend Engineer
Stack
React 18 · TypeScript · Three.js · React Three Fiber · Redux Toolkit · Vite

The shape of it

MONTEROSA CONNECT SDKREDUX TOOLKITclockgameHealthincidentincidentHistoryplayersummaryteamNORM7 → 7app01event02game03project04reactions05scaffold06votes07
01

The feed does not match the model

Seven message handlers — clock, game health, incident, incident history, player, summary, team — feed seven Redux slices: app, event, game, project, reactions, scaffold, votes. They deliberately do not map one to one. The normalising boundary between them is the interesting part of the architecture, because it is where a vendor's idea of a football match is translated into one the renderer can draw.

02

Two camera worlds, one pitch

Sportradar publishes normalised 0–100 coordinates. Those are mapped into Three.js scene space so pitch geometry survives any aspect ratio. The complication is bird's-eye view, which rolls the camera frame on its side and shifts the pitch model along X — angles authored against the side view stop meaning what they meant.

03

A shootout that outlives its own incident

A penalty shootout is not one event, it is an indefinite run of them. A sticky Redux flag holds a camera override across that run and clears only on five specific field-clearing incident types. Because the override contradicts bird's-eye view, three separate guards keep the two from fighting: camera-up short-circuits to world up, orbit limits fall through to the side-view configuration, and the imperative re-lookAt stands down while the declarative spring path has control.

04

Delivery

Vite and Rollup code-splitting behind a dual-build pipeline — a standalone app and an embeddable FanKit library from one source — deployed to S3 and CloudFront. TypeScript strict mode, ESLint and Prettier, and Husky pre-commit hooks held the boundary.

29

incident types

7 → 7

handlers to slices

4

studio projects

0–100

coordinate space

Next

Two hundred and fifty ways to constrain a portfolio