The problem with putting video in a git repo
The repo kept getting heavier, sprint after sprint. We were committing big MP4s next to the code, builds were slowing down, and deploys with them. Case studies lead with video, so every new client made it worse. We needed the media to live somewhere else, and to turn up in a size that suited whatever screen it landed on.
But where? The CMS was out: most aren’t built for video, so the first byte takes too long and the bandwidth bills mount up. The repo was out too, and we knew the downsides first-hand: files the content team can’t touch without a commit, and a history that keeps growing. A proper video CDN would handle the delivery, but they’re a pain to set up and never really talk to the CMS. That’s the awkward thing about web video: there’s nowhere good to put it.
The authoring side
Writing a case study, you drop a short asset ID into the MDX, something like , and the pipeline takes it from there. No encoding flags to remember, no breakpoints to define, and nobody exporting poster frames by hand.
One ID in the markdown, six responsive sources on the page.
The point of all this is that the asset ID is the stable interface. Everything behind it was free to evolve, and it did, without a single case study needing an edit.
Under the hood
The video component looks at what it’s been handed and decides how to deliver it. A short asset ID turns into fully responsive video, several formats and breakpoints. A streaming URL goes to adaptive bitrate. A plain file just plays. None of that is the author’s call. The component works it out from whatever it’s given.
The same principle for images
Images work the same way. Five layout presets, each with its own responsive widths and loading behaviour, and AVIF output by default, built at compile time. You pick the layout you want, and the component sorts out the format, the sizes and how it loads.
The infrastructure underneath
It started small: the Air.inc API wired up so assets could be referenced by a short ID, first just in Labs. From there it grew. Full Air.inc integration, then HLS streaming, then that same delivery across every case study. Next came mobile, with streaming that adapts to the device it’s playing on. The last move put SpeedyClip into the delivery layer.
Through all of it, the people writing case studies carried on exactly as before, same markdown, while the rendering quietly improved at every step.
Air is still the asset library and source of truth. The team manages the files, versions and metadata there; the site references those assets by stable IDs. SpeedyClip takes over at the delivery point, turning the Air source into the responsive streams we serve on the site.
That means SpeedyClip handles every video embed on the site without replacing Air in the workflow. It serves optimised streams off the same kind of global edge network the big streaming services run on, the sort of setup you’d normally have to stitch together yourself on every project. All of it is built around load speed and time-to-first-byte. The clever part is how it starts. It streams over HLS, but the opening segment is only two or three seconds long, so the video starts playing almost as soon as the poster appears, instead of waiting for a bigger file to land. Not many people bother going that far.
There’s a lot more to say about SpeedyClip, what it actually is and why a studio ends up this deep in video delivery. That’s a post of its own.
On the visitor’s end
A poster image holds the layout while the video loads, so nothing jumps around as it arrives. The video fades in instead of popping into place. On a slow connection the smaller breakpoint files turn up faster than one big high-res file would, so even on patchy mobile the page stays together.
The poster holds the space, the video fades in over it, and there’s no jump or empty box while it loads.
Twenty-eight case studies now open with video that doesn’t shift the layout, doesn’t drag a history of MP4s behind it, and adapts to whatever connection it loads on. None of which changed how a single case study gets written.