Lab · Data sonification · Web Audio API + NYISO live data · Nov 2026

Listening to the grid

New York’s grid publishes its fuel mix every five minutes. I turned it into one minute of music a day: each power source is an instrument, the clean share sets the key and demand sets the tempo. Then I built the system that keeps it playing: a live view, a calendar of every day, and an archive that grows on its own.

A music-player card for New York in 2026: one waveform bar per day, coloured from gas-heavy red to clean blue, with the playhead on 17 October at 64% clean in a major key. Beside it, 46% clean power, played as music.

The 30-second version

7 min read

Role

Designer and engineer, end to end

Prototype

grid-symphony.vercel.app

Built with

Web Audio API, Vercel, GitHub Actions, Python

Data

NYISO fuel mix and zonal load, every 5 minutes

Grid dashboards answer “how much” and lose people at “so what”. I treated the grid as a score instead: each fuel is an instrument, the clean share picks the key and demand sets the tempo, so a strained evening sounds different before you read a number. Every sound is backed by the same data drawn on screen, and the whole thing runs on static files and a browser synth.

5 min

between readings, from NYISO’s live feed

373 days

in the archive, saved every morning by a scheduled job

0

audio files stored; every minute is synthesized in the browser

Live prototype: grid-symphony.vercel.app · Source and raw data on GitHub

The question

A grid you can feel, not just read

New York publishes its fuel mix every five minutes. The data is public, precise and almost entirely ignored, because a stacked chart of megawatts asks a lot of someone who doesn’t already know what a good hour looks like. I wanted the opposite entry point: something you notice first and read second.

So the brief was: make the state of the grid legible in one minute, to someone with no energy background, without bending the numbers.

The mapping

Each power source plays an instrument

Sonification lives or dies on its mapping. I picked sounds whose character matches how each source behaves on the grid, so the metaphor teaches something true instead of just decorating the data.

Input

Sound

Why it fits

Nuclear

Low drone

Steady baseload that barely moves, like the plants

Hydro

Flowing pad

Slow swells; louder when Niagara and St. Lawrence run high

Wind

Breath and bells

Airy and variable; bells ring more often as output rises

Solar and other renewables

Plucked melody

Intermittent; more output, more notes

Gas and dual fuel

Buzzing saws, brass stabs

Harsher, with a clashing note, as the clean share drops

Clean share

Key

Major above ~54%, Dorian in the middle, Phrygian below ~46%

Statewide demand

Tempo

A soft heartbeat from about 60 to 135 bpm

Two variables carry the story

The instruments add texture, but key and tempo do the explaining. A listener doesn’t have to pick out seven voices to hear a day move from open and bright to tense and fast. It’s the same rule I’d apply to a dashboard: one or two primary encodings, and everything else is detail on demand.

The system

Four zoom levels, one colour scale

The views step out in time: Today (live, through the latest reading), Trends (the last 30 days, plus the month compressed into one minute), Year (every day and every hour) and All time. Each answers a different question, and every one lets you click into a day and hear it.

Clean share of in-state generation by month, 2026
Jan
44%
Feb
42%
Mar
47%
Apr
50%
May
55%
Jun
47%
Jul
40%
Aug
40%
Sep
44%
Oct
54%
Nov (so far)
56%
Plays in a major keyDorianPhrygian

The Year view is where the piece became more than a toy. Laid out as a calendar, the seasons appear on their own: a clean spring and autumn when hydro is strong and demand is low, and a red summer when air conditioning pushes the grid onto gas. 2026 so far: 46% clean across 312 saved days. The cleanest day was 17 October at 64%; peak demand hit 31,221 MW at 7 PM on 2 July.

The colour scale is the key signature

The heatmap runs from strained red (under 40%) through a neutral sand (45–50%) to clean blue (55% or more). I set those bins against the same thresholds the music uses, so what you see on the calendar and what you hear when you click it agree. Blue days sound bright. Red days sound tense.

Hard calls

Four trade-offs I made on purpose

Synthesize, don’t record

Every minute is generated in the browser with the Web Audio API from that day’s readings. Nothing is stored, so a year of music costs nothing to host, and changing the mapping re-scores the whole archive at once.

Static files over a database

Three rollups, each sized to the view that reads it: every 5-minute reading per day, hourly clean share per year, one summary row per day. The only server code is one function that proxies today’s NYISO feed, which browsers can’t fetch directly.

Never sound alone

Sound is never the only channel. The key, the tempo and the clean share are always on screen as colour, a number and a label, so the piece works muted, for people who can’t hear it, and for anyone checking the music against the data.

Show the gaps

Days that weren’t saved appear as empty “Not saved” cells instead of borrowed colour. The daily job re-fetches the day before in case NYISO revises it, and git history is the change log. A chart that quietly fills holes stops being trustworthy.
Design engineering

The pipeline is part of the design

A live data piece is only as good as its freshness. A scheduled GitHub Actions job runs every morning: it saves yesterday, re-fetches the day before, rebuilds the rollups and commits. Vercel redeploys on each commit. The scripts use nothing beyond the Python standard library, so the archive keeps growing without anyone tending it.

Layer

Choice

Why

Data

NYISO real-time fuel mix and zonal load

Public, every 5 minutes, across 11 zones

Storage

JSON files in the repo

Versioned, diffable, free to serve

Updates

Daily scheduled job

Fresh by morning and self-correcting

Live view

One serverless function

Gets around the browser’s cross-origin limit

Sound

Web Audio API

No stored audio; a new mapping re-scores everything

Limits

What it can’t tell you

  • In-state only. Clean share counts New York’s own generation. Imports show as the gap between generation and demand, not as clean or dirty.

  • “Clean” is a definition. Nuclear, hydro, wind and solar count as clean. That’s a choice, and a different definition would change the colours.

  • The music is interpretive. The key and tempo thresholds are mine. They’re fixed and documented, but another mapping would tell the same story with different emphasis.

  • 2026 is a partial year. Figures run through early November.

Reflection

Make the data noticeable before you make it readable

Most data products start from the chart and hope people care. This one starts from a feeling, a day that sounds tense, and lets the chart explain it.

The principle I’m taking into product work: pick the one or two encodings that carry the story, make every other channel agree with them, and never let the delightful layer drift from the data.

Try it

Hear two days

Open the Year view and click a day in late July, then one in mid-October. Same state, same instruments, a different grid.

Play Grid Symphony →

Method notes
Data: NYISO real-time fuel mix (rtfuelmix) and zonal load (pal), 5-minute readings, Eastern time. 2026 figures are from the prototype’s Year view on 9 Nov 2026 and cover in-state generation only.
Jacqueline Yeung · Lab note · Prototype: grid-symphony.vercel.app