BoomerClip's pitch is short: record your screen in the browser, share a link, and the video is gone once the viewer closes the page. No install, no archive, no copies lingering on a server for years.
It didn't start out that way.
Version 0.1: live sharing
The first version, back in May 2025, was real-time screen sharing over WebRTC. Socket.io handled the signaling, browsers made peer connections, and a viewer watched your screen live.
Live sharing has a built-in constraint, though: both people have to be there at the same time. A lot of "let me show you my screen" moments, like "here's the bug" or "this is how you set it up", don't need a live call. They need a clip someone can watch when they get to it.
The pivot
So BoomerClip pivoted from live streaming to asynchronous recording. I deleted the WebRTC signaling, the live share and view screens, and their controllers and routes, and replaced peer connections with the browser's MediaRecorder API. You record, it uploads, you get a link.
The ephemeral part stayed, and got more interesting. Recordings live in Redis, not on disk in some bucket forever. When the viewer's page closes, the server hears about it over Socket.io and deletes the recording. The idea is that nothing sticks around by default.
One small thing I had to think about: if every recording deletes itself, how do you count them? The platform statistics would reset to zero every time someone finished watching. The total-recordings counter now lives in its own persistent Redis key, so the number survives the videos it counts.
Then the browsers weighed in
MediaRecorder is a standard. Video playback is a standard. In practice, every browser had its own opinion.
Safari refused to play recordings with MEDIA_ERR_SRC_NOT_SUPPORTED until the MIME type and codec were handled explicitly. Share links hit CORS errors, which turned out to be caused by a custom header I'd added to detect the browser. Uploads needed several fallback paths, including one through the Fetch API, and its strict autoplay rules meant play and pause needed their own event handling.
Firefox had codec errors mid-recording, needed its audio streams combined through the Web Audio API, and has strict rules about when getDisplayMedia can be called. It has to come directly from a user gesture. It could also get stuck in a screen-capture loop until I fixed the state handling. And system audio capture simply isn't available there, so the app now says so plainly and suggests another browser.
Edge played recordings without sound until it got the right streaming headers, and it had its own caching quirks.
Chrome was the most cooperative, and got VP9 for higher quality.
Beyond that, the duration display was wrong across every browser. Recordings made with MediaRecorder don't reliably say how long they are, so the fix took duration detection with several fallbacks, validation of every value, and time formatting that copes with the edge cases.
I thought that was the end of it. A year later I found recordings still being saved with a duration of "N/A": Chrome's WebM files have no duration header, so the probing tool answers with the string "N/A", and a non-empty string counts as a value. Fixed on the screen, not in the data. It's on the list.
Four players, then one component in pieces
The fastest way through all of that was a browser-specific video player for each engine, each with its own controls: a progress bar, volume, fullscreen, keyboard shortcuts, controls that hide themselves, and proper accessibility attributes.
It worked, but the viewing page had grown to 1,227 lines in a single component. Pulling the players out into their own components, with shared TypeScript interfaces and hooks, brought it down to 449. That's a 63% cut, and a file I could actually read again.
In hindsight, four players was a symptom, not a solution. The plan now is one video player with a small adapter per browser, so every browser shares the same behaviour and only the genuinely different parts are special-cased.
Then I put it down
By early June 2025 BoomerClip recorded, uploaded, played and deleted, with optional accounts and an admin panel on top. Then it sat untouched for over a year.
I didn't realize how overwhelming the pressure of what I was going thru at the time actually was. Picking it back up turned out to be its own adventure. That's the next post.
~ Jer