UK AI Talent Pipeline Visualiser
An interactive metro-map simulation of the UK's AI talent pipeline, showing how education, labour-market and immigration levers shift the national AI talent pool.
What it does
The tool models the UK’s AI talent pipeline end to end — from school through further and higher education into the AI labour market, plus international arrivals and departures — and renders the whole thing as a single interactive map, styled like a metro/Tube diagram rather than a conventional flow chart. Twenty-one policy variables, grouped by education, research, visas, labour market and infrastructure, can be moved on sliders to see the national AI talent pool respond immediately: which pipelines grow, which shrink, and where the flow gets displaced rather than added to. A second mode applies twenty curated real-world interventions (drawn from DSIT’s own AI talent intervention library) as one-click scenario presets, with a before/after diff highlighted directly on the map, and a comparison dashboard ranking all twenty by cost-effectiveness against whichever headline statistic matters most.
How it works
A pure, deterministic simulation engine (simulate()) runs a
topological forward pass over a config-driven graph of pipeline nodes
and edges — no backend, no database, safe to run in a Web Worker. A
separate layout engine turns the simulation’s output into pixel
coordinates: a D3 grid layout for node position, octilinear routing
(straight lines and 45° diagonals only, like a Tube map) for the flows
between them, and D3’s pie/arc generators for the sector-composition
rings drawn on top of labour-market nodes. Every UI value — slider
positions, flow widths, summary statistics — animates through a single
shared requestAnimationFrame loop rather than one animation per
component, and every value the app renders traces back to one central
Config object rather than anything hard-coded in a component.
The interesting problem
The engine’s headline number — the total AI-relevant talent pool — was
wrong for most of the build, and not in an obvious way. The bug:
relevanceFraction (the share of a stage’s population that’s
AI-relevant) was being applied at every node in the chain, so it
compounded downward through the education pipeline until the domestic
route collapsed to a handful of people by A-Level, and the pool ended
up driven almost entirely by exogenous immigration — moving an
education policy lever barely moved the total at all, which is exactly
backwards for a tool meant to show education policy mattering. The fix
was to change what actually propagates through the graph: flows now
carry the full head-count stock end to end, and ai_stock = stock × relevanceFraction is computed only once, at the point of measurement,
rather than being baked into the flow itself. Roughly twenty
postgraduate and labour-market-entry coefficients had to be
re-derived once that changed what “the pool” actually meant, and a
related sign bug — where raising T-Level uptake perversely reduced the
STEM route it was meant to feed — needed a new mechanism (an edge that
explicitly offsets against a policy lever) rather than a coefficient
tweak, since the two edges’ outcomes are genuinely coupled.
Stack and why
D3 does the layout and flow-path maths (linear/sqrt scales, pie/arc generators, an octilinear router), while React owns everything state-driven — the reducer holding policy overrides, memoised re-simulation on every change, and the component tree. Keeping the simulation engine and layout engine as plain, DOM-free TypeScript functions (not React hooks, not classes) was a deliberate constraint from the start, so either could later run inside a Web Worker without a rewrite if the simulation ever gets heavy enough to jank the main thread. Vitest’s per-file execution made it possible to keep a large, fast-growing test suite (165 tests) green even when the full suite hit sandbox performance limits.
What I would do differently
TODO (James) — short, in your own words.
Stack
- React 18 / TypeScript / Vite
- Application shell, build tooling and component layer
- D3.js
- Metro-map/Sankey layout, octilinear flow routing, zoom/pan, and the shared animation loop
- Tailwind CSS
- Styling, including a full brand/neutral/semantic colour palette pass
- Vitest
- Engine, layout, config and diff test suite
21
modelled policy variables
20
curated DSIT intervention presets
165/165
engine and layout tests passing
- Repository — private repository