Acasuso.
← All work

Live 3D editorial visualisation of an entire industrial sector

Stratas team project

Built a real-time 3D visualisation of every flagship producing asset on the Norwegian Continental Shelf – 15 wireframe platforms at true lat/lon, streaming per-second yield in three currencies from live FX + Brent, with a deterministic fallback so the piece is never dishonest even when its upstreams are.

Stratas team project

Delivered by the Stratas team and shown here as part of the wider Stratas portfolio.

MIDAS: wireframe offshore installations with value-yield labels.Open full-size image ↗
MIDAS: wireframe offshore installations with value-yield labels.

Situation

The Norwegian Continental Shelf (NCS) is one of the most transparently-documented industrial sectors in the world. Ownership, production baselines, tie-back topology, operator equity splits – all of it is public record via the Norwegian Petroleum Directorate. And yet the way this information is typically presented to investors, regulators, and interested public is a slide deck: a screenshot of a map, a table of operators, a bar chart of yield. The medium flattens the subject.

The pressure that shaped Midas was an editorial one: a live 3D piece has to earn its 3D-ness. Every additional axis has to carry information a slide could not. If the piece is going to render 15 offshore platforms in true geographic position with live commodity data streaming through them, it has to do so honestly – no random-number theatre, no failed-fetch collapsing to a blank canvas, no fake precision. Otherwise a slide would have been more honest.

Task

Decide whether an editorial 3D visualisation of the NCS is buildable to a shippable standard by one person in a short sprint – and if so, own the decision that separates "impressive-looking" from "actually honest under real-world upstream failure."

The load-bearing decision: what does the piece do when Frankfurter is rate-limiting, EIA is 502-ing, and the NPD baseline hasn't been imported yet? A fake number in an investor-facing 3D scene is worse than no scene at all. The design has to answer this at the architecture level, not paper over it in the UX.

Action

System workflow

Upstreams
Frankfurter (FX) and EIA (Brent spot) fetched in parallel with a 4-second per-call timeout. Free and keyless.
/api/market
Next.js API route. Cache-Control public s-maxage=900 stale-while-revalidate=3600. Warm cache in front of both upstreams.
Zustand store
Per-second update cadence too fast for React context re-renders. State lives in Zustand, atom-scoped.
Fiscal engine
src/lib/engine/fiscal.ts. BOE / m³ / kg conversions per asset baseline. Yield in USD, NOK, and EUR simultaneously.
3D scene
Three.js plus React Three Fiber. 15 wireframe assets rendered per archetype (Condeep, steel jacket, FPSO, semisub, subsea template). True lat/lon via equirectangular projection. Per-vertex waterline colouring.
Views
Flagships (8 curated top producers) and Shelf (15 modelled plus procedural 79-field-point layer). Compass-rose birdseye toggle to 360° atlas.
Fallback chain
Frankfurter fails → hardcoded baseline. EIA fails → hardcoded baseline. Baseline fails → Box-Muller Gaussian random walk from last known good print.

Architecture

Next.js 16 App Router + React 19 + Three.js + React Three Fiber + Zustand. The frontend is a single 3D canvas with a UI HUD overlaid; state lives in Zustand rather than React context because the update cadence (per-second yield ticks driving revenue calculations) is too fast for context re-renders to be free.

Fifteen offshore assets rendered per archetype. Five archetypes – Condeep, steel jacket, FPSO, semisub, subsea template – each modelled as its own wireframe geometry. Assets sit at true lat/lon via equirectangular projection; per-vertex colouring splits the geometry across the waterline so above-water and below-water read distinctly at any camera angle.

Multi-view editorial framing. Two curated views: "Flagships" (eight top producers) and "Shelf" (the same 15 modelled assets plus a procedural 79-field-point layer covering the balance of NCS coverage). A birdseye compass-rose button flips to a top-down 360° camera language that reads as an atlas rather than a first-person walk.

Deterministic fallback everywhere, at the data layer. The /api/market route fans out to Frankfurter (FX) and EIA (Brent spot) in parallel with a 4-second per-call timeout. If either fails, hardcoded baseline constants take over. If the entire market route is unreachable, the client engine (src/lib/engine/pipeline.ts) runs a Box-Muller Gaussian random walk seeded from the last known good print, so the visualisation still shows plausible movement rather than a frozen scene. Cache-Control: public, s-maxage=900, stale-while-revalidate=3600 keeps a warm cache in front of both upstreams.

Alternatives considered and rejected:

  • Static map with a tabular equity breakdown. This is what everyone already ships. The pitch was specifically to argue that 3D + live data reads more honestly than a slide – a static map defeats the argument.
  • Deck.gl / Mapbox 3D. Great for cartographic 3D. Wrong for editorial 3D. Deck-based approaches make it easy to render everything and hard to render specifically the archetype geometry and camera language that carry the piece's meaning. Direct Three.js was the right layer to work in.
  • Real production data from paid sources at v1. Deferred deliberately. The NPD monthly production baseline is the honest source; wiring it stabilises after the visual language is set. Shipping v1 on the free Frankfurter + EIA path with an explicit TODO.md blockers list was the discipline that made a nine-day sprint possible.

Implementation

  • 15 wireframe assets modelled per archetype in Three.js primitive geometries (src/components/scene/Rig.tsx), each with position at true lat/lon and equirectangular projection.
  • Fiscal engine (src/lib/engine/fiscal.ts) handles BOE / m³ / kg conversions per-asset baseline so the revenue tick math is honest to how the sector actually measures itself.
  • Live per-second yield streaming in USD / NOK / EUR simultaneously – one visualisation, three fiscal frames.
  • Ownership breakdown surfaced as a coloured equity square in the inspector when an asset is selected. Operators are read from public records; the square is the visual language.
  • Subsea tie-back annotation on assets that carry satellite fields – the tie-back names appear as pills in the inspector, so a viewer sees the network topology, not just the surface asset.
  • Mobile peek-drawer inspector + one-row TopHUD as its own concurrent feature branch (mobile-drawer-hud). Editorial 3D on a phone is a specific UX problem and it deserves separate work from the desktop scene.
  • Camera smoothing on its own branch (camera-smoothness-*) – the piece reads as either premium or amateurish based entirely on how the camera moves, so this iteration is not incidental.

Verification

  • 13 concurrent feature branches, each narrowly scoped, so any regression can be bisected to a specific concern (camera / firstpaint / mobile HUD / production-readiness).
  • TODO.md in the open – ship-blockers named explicitly: real NPD monthly production baseline, TTF gas + EUA carbon upstream wiring, error reporting, cross-browser and mobile verification. Anyone reading the repo knows what the piece does not yet do.
  • HANDOFF.md documents each session's decisions and the reasoning behind them so subsequent work does not have to re-derive it.
  • Vercel Web Analytics enabled from v1 for Core Web Vitals – a 3D scene lives or dies on first-paint and interaction latency.

Result

MIDAS: selected installation with throughput, yield, and ownership details.Open full-size image ↗
MIDAS: selected installation with throughput, yield, and ownership details.
  • Working 3D scene with 15 modelled offshore assets in true geographic position, plus the procedural NCS field-point layer.
  • Working live data flow – Frankfurter FX, EIA Brent, per-second yield in three currencies, cache warmed by 15-minute revalidate window.
  • Deterministic fallback path proven end-to-end – under simulated upstream failure the visualisation continues to render honestly rather than blanking or lying.
  • Multi-view editorial framing shipping in one interface – Flagships and Shelf, plus birdseye 360° camera.
  • 23 commits over nine days, 13 active concurrent feature branches, ship-blockers publicly tracked.

Second-order effects: the "deterministic fallback everywhere" rule graduated from Midas into a fleet default for any real-time visualisation Stratas ships. The HANDOFF.md per-session-decisions document is being adopted by the other pre-production products where a single-person iteration cadence makes context easy to lose.

What we would do differently: wire the NPD baseline in parallel with the visual work rather than as a ship-blocker. The visual language is far enough along that adding data plumbing on the same days would have stopped the two tracks from serialising.

Skills evidenced

  1. Editorial 3D as a distinct discipline from cartographic 3D – Three.js + React Three Fiber worked at the primitive level, archetype geometry over base-map layering, deliberate camera language.
  2. Real-time data plumbing with honest fallback – parallel fetch with per-call timeout, deterministic baseline, Gaussian random walk as last-resort seed, cache-warmed API route.
  3. Editorial UX at investor-facing polish – multi-view framing, coloured equity square, subsea tie-back annotations, mobile peek-drawer inspector.
  4. Multi-currency fiscal modelling – three-currency revenue calculation with sector-honest unit conversions.
  5. Ship-in-a-sprint discipline – nine-day cadence, 13 concurrent branches, TODO.md blockers named openly rather than hidden.

Portable lessons

  1. A blank canvas is a bug; a stale baseline is a promise. Any real-time visualisation has to have a deterministic fallback that reads honestly under upstream failure, or the piece becomes a liability the first time its data source hiccups.
  2. Editorial 3D is not cartographic 3D. Camera language and archetype geometry carry the meaning. Reaching for a mapping library when the piece wants to be an atlas ships the wrong medium.
  3. Ship the blockers list openly. TODO.md naming what does not yet work is the discipline that keeps a live piece honest as it grows. A pre-production scene is only dishonest when it hides what is missing.

Want to discuss the decisions behind it?

Over fifteen years of consulting and growth, and hands-on AI delivery from discovery to daily operations. I can share my CV and talk through how I connect business outcomes with systems that run.

Available for a chat. In person in Stavanger, or remotely worldwide.