> product // zoomtrail // the making of
ZoomTrail
how it was made.
ZoomTrail is a native screen recorder that records your screen, webcam and audio, then automatically zooms and pans to follow your cursor so a raw take comes out looking edited. The hard part was never the zoom. It was capturing the screen cleanly on three different operating systems, each with its own permissions, its own capture API and its own way to break. The whole thing went from a plan file to a live download at zoomtrail.app in five days.
The short version
On 4 June 2026 it was a plan: a Focusee-class recorder for Linux and macOS. By the end of that same day there was a working capture backend on Mac in Swift, a Linux backend in Rust over PipeWire, a Tauri and React desktop app to drive them, an auto-zoom track generator, an audio mix panel, an export menu, and a tagged v0.1.0-alpha. Windows, which started the day out of scope, got its full capture backend that same evening.
From there it was four more days of relentless, mostly unglamorous work: a GPU renderer with a spring-damped camera, webcam capture on all three platforms, instant share links, screenshots with annotation, macOS signing and notarisation, a self-update channel, and a content suite that turns a recording into an article, captions and social posts. The app shell was rebuilt twice in two days as real dogfooding showed where the layout fought the user. By 8 June it was a five-tab master-detail app at v0.9.2-alpha, live and downloadable on Mac, Linux and Windows.
// the build log · mined from the commit history, nothing dramatised
Capture on Mac, Linux and Windows
The plan called for Linux and macOS. The Mac backend (Swift, ScreenCaptureKit) passed its hardware gate first, the Linux backend (Rust over xdg-portal and PipeWire) captured frames in a container, and the Tauri v2 plus React 19 GUI came up to drive them. Auto-zoom (the zoomgen track generator), a per-recording audio mix panel, area capture and a full export menu all landed before the day was out. v0.1.0-alpha packaged as AppImage and deb. Then, same evening, Windows was promoted from out-of-scope to a full capture backend with its own CI installer.
A GPU renderer and everything around the recording
A second track, zt-render, brought a GPU pipeline with a critically damped spring camera, GPU cursor, click ripples, a padded gradient canvas with rounded corners and shadow, and reusable watermarks. Alongside it: Scratch-Take (voice-marked mistake removal), pause-and-resume takes stitched into one recording, chapter markers, and a BYO-key content suite that generates a publishable article, captions and social posts from a recording's audio. webcam capture went in across all three platforms, share links went live, screenshots got a global hotkey, and macOS builds got the full sign-and-notarise ritual plus a self-update channel.
One button to make it look great
Magic Cut shipped: one press to cut filler and pauses, apply auto-zoom and polish, composing via the style.json cuts contract rather than chaining mp4 files. The same day ran a deep brains-trust, a four-model product panel across four lenses plus six code-review agents, then fixed every cross-validated Critical and high-priority finding before tagging v0.7.1-alpha.
From a single component to a tabbed app
Live dogfooding showed the layout fighting the user. App.tsx was carved up with a strangler refactor into a six-tab shell with a context bar, each tab extracted as a module while state stayed put, then reshaped again the same day into a five-tab master-detail layout where Publish dissolves into the Library detail view. Underneath, lib.rs was split into domain modules (3,667 lines down to 1,240) and system curl was dropped for in-process HTTP. The repo also moved to the JezwebTeam org to clear a billing blocker.
Windows blockers and the daytime batch
Windows took the brunt of the bug list: recording dead on renumbered displays, hotkey defaults, blank-white floating HUD controls, a hung finalize that could strand the UI. The library learned to drag a recording out as a real file and to search by name across recordings and screenshots. Each tag passed a brains-trust panel first. v0.9.2-alpha shipped that afternoon, live on all three platforms.
Make failure recoverable, never silent
A long thread of fixes runs under issue #9 and #82 and #83: monotonic event clamps, fsync durable completion markers, a bounded stop that escalates from grace to TERM to KILL, mux failure that degrades to video-only instead of vanishing, and stream death that salvages the take rather than voiding it. Unglamorous, repeated, and the reason a recording you trusted does not disappear.
git log: “fix(reliability): stream death salvages the take instead of voiding it”
The quiet heart of the project: a recording you trusted should survive when something underneath it breaks.
// the roads not taken
Tried, measured, set aside: the judgement lives here as much as in what shipped.
More buttons for power users
A 'Magic, not buttons' plan filtered an incoming feature request for non-technical users, choosing one-press Magic Cut over another row of controls. The instinct to expose every knob was deliberately resisted.
The visible dev jump-to-view menu
A 'jump to view' menu was added to the header for development convenience, then reverted the same day as clutter. The deep-link route stayed; the visible menu did not.
The whole app shell, twice
One big recorder component became a six-tab shell, then a five-tab master-detail layout, across two days. Real dogfooding kept showing the information architecture was wrong, so it kept getting rebuilt rather than patched around.
Crash-safe recordings
Rather than trust the happy path, the bundle got durable completion markers and the capture pipeline learned to salvage takes through mux failures and stream death. The reliability work is invisible when it works, which is the point.
Want something built like this?
This is how we work: in the open, measured, honest about the dead ends.