Today’s issue: Using AI to compile 22-year-old code, meditating on supply chain attacks, and becoming the Cloudflare Captain.
Welcome to #426.
Me 10,000 words deep in the FFmpeg docs just trying to rotate a video
Working with media in the browser has always been a nightmare – you either ship a bloated FFmpeg + Wasm build that takes forever to spin up, or you punt everything to the backend and pay the latency + infrastructure tax.
But everything changed a few weeks ago when a German developer named Vanilagy launched Mediabunny, after months of grinding on the project at his local McDonald’s (like all the great minds of our time).
Mediabunny is a TypeScript-first media toolkit for reading, writing, and converting video and audio files in the browser. And at the risk of being cyberbullied by the FFmpeg team, I must say it looks pretty clean.
Here are a few cool highlights:
Efficient reading & writing – Extract metadata, frames, and tracks from huge media files. Programmatically generate new MP4/WebM files with multiple audio/video streams directly on the client.
Conversion API – A simple, async API that lets you transmux, transcode, resize, rotate, trim, and resample media.
Universal I/O & codec support – Read/write files from memory, disk, or the network and inject media data from canvas, webcam, mic, or screen. Full support for major container formats and 25+ codecs.
Built for the web – Pure TypeScript, zero deps, with a highly tree-shakable API.
Blazingest performance – ~60x faster than ffmpeg.wasm
in benchmarks thanks to progressive reading/writing, pipelined design, and hardware-accelerated encoding/decoding.
So, will this replace FFmpeg now? Not really. FFmpeg still rules with hundreds of codecs, weird legacy formats, and decades of battle-testing — but all that power makes it heavy and clunky in the browser. Mediabunny keeps its scope smaller on purpose, which makes it a great fit for web apps like editors, converters, and streamers.
Bottom Line: McDonald’s Diet Coke remains undefeated.
![]() ![]() ![]() ![]() |
Me seeing bugs in prod after the team spent 6 weeks writing tests
…with zero effort from your team.
That’s what QA Wolf did for Brilliant – helping them detect 8-10 bugs per month, while reducing their QA cycles from 24 hours to under 5 minutes (watch case study).
And they can do it for your team too. Here’s how:
Get a personalized demo for your team – and see why Napster’s Engineering Director said, “It would take 4 people to build this much coverage, and they’d never do it this quickly.”
Their new Seer AI agent pulls in all of Sentry’s logs, traces, and other context to automatically debug the root cause of an issue and open a PR with a fix.
function p1() {
return new Promise((resolve, reject) => {
setTimeout(() => reject("Error in p1"), 1000);
}).catch((error) => {
console.error(error);
})
}
function p2() {
return new Promise((resolve) => {
setTimeout(() => resolve("p2 resolved"), 1000);
});
}
function pAll() {
Promise.all([p2(), p1()])
.then((results) => {
console.log("All data resolved:", results);
})
.catch((error) => {
console.error("Error resolving data:", error);
});
}
pAll();
Cloudflare just announced Cap’n Web, a new RPC system for browsers and web servers in pure TypeScript with no schemas. It doesn’t taste quite as sweet as Cap’n Crunch Oops All Berries, but at least it won’t cut up the roof of your mouth as much.
Dex Horthy wrote about getting AI to work in complex codebases, beyond just asking Claude to “make no mistakes this time.”
Jeff Escalante wrote this comprehensive guide to authentication security in web applications for the Clerk blog. It shows the top auth vulnerabilities being exposed by attackers and how to fix them in your app before something bad happens. [sponsored]
Piotr Grabowski created CompileBench to see if AI can compile 22-year-old code.
Tane Piper wrote this meditation on NPM supply chain attacks. But we’re gonna need you to meditate a little harder, Tane, because we are getting absolutely rekt out here.
CodeRabbit just launched CodeRabbit CLI, which gives you senior-level code reviews in your terminal and acts as a quality gate for all the code that Claude, Codex, and Gemini write for you. [sponsored]
Chander Ramesh wrote about how and why his team at Motion are moving off of TypeScript and starting a blood feud with Anders Hejlsberg (jk).
Simona Cotin wrote about how Angular is embracing AI for next-gen apps
Datadog’s Front-end Developer Kit gives you instant access to their best practices guide for testing and monitoring, a solutions brief on how to catch issues earlier, and lots more resources. [sponsored]
Ghostty creator, Mitchell Hashimoto wrote about how Nosferatu libghostty is coming.
Addy Osmani wrote this deep dive on how modern browsers work
Speaking of which, Safari 26.0 just came out with 75 new features, 3 deprecations, and 171 other improvements. Your move, Arc Browser Jira Browser.
function p1() {
return new Promise((resolve, reject) => {
setTimeout(() => reject("Error in p1"), 1000);
}).catch((error) => {
console.error(error);
})
}
function p2() {
return new Promise((resolve) => {
setTimeout(() => resolve("p2 resolved"), 1000);
});
}
function pAll() {
Promise.all([p2(), p1()])
.then((results) => {
console.log("All data resolved:", results);
})
.catch((error) => {
console.error("Error resolving data:", error);
});
}
pAll();
First, Error in p1
is logged, then [ 'p2 resolved', undefined ]
is logged. Since p1 catches the rejection, it doesn’t propagate to the Promise.all
catch handler allowing p2
to resolve. But, since p1
doesn’t return anything, its result is undefined
.