We shipped 19 releases in February — playlists, engagement heatmaps, system audio, custom player controls, and more. Here's what we built, what we learned, and where SendRec is heading.
SendRec started as a simple idea: an open-source, EU-hosted alternative to Loom. Record your screen, share a link, see who watched. Four weeks into February 2026, we've shipped 19 releases (v1.48.0 through v1.64.0) and the product looks very different from where it started.
Here's a recap of what shipped, and where we're going next.
What shipped in February
The month started with billing (Creem integration for Pro subscriptions) and ended with faster end-to-end tests and a refined deployment pipeline. In between:
Video playlists. Share an ordered set of videos as a single link. Password protection, email gates, auto-advance, watched badges. Playlists get their own embed page with a sidebar.
Custom player controls. We replaced the native <video controls> with a custom UI — seek bar with chapter segments and comment markers, speed controls, picture-in-picture, volume slider, fullscreen. Auto-hide after 3 seconds, touch support for mobile.
Viewer engagement heatmap. The analytics page now shows a 50-segment bar that visualizes where viewers pay attention and where they drop off. Each segment covers 2% of the video timeline. Bright means high engagement, faint means drop-off.
System audio recording. Chrome's systemAudio and suppressLocalAudioPlayback constraints let us capture tab and system audio during screen recording, with an Audio On/Off toggle in the recorder UI.
MP4 recording. Chrome 130+ and Safari record MP4 natively. No more server-side transcoding for most recordings. Firefox falls back to WebM with a VP8/VP9 chain.
iOS compatibility. Custom player controls break on iOS, so we detect it and fall back to native controls. ffmpeg flags were tuned for iOS playback compatibility (-profile:v high -level:v 5.1 -r 60). Videos that aren't iOS-compatible get re-encoded automatically.
Playlist embeds. /embed/playlist/{shareToken} renders a sidebar with video list and auto-advancing player — designed for embedding in documentation, wikis, or internal tools.
Docker Hub publishing. Every tagged release now pushes to Docker Hub (alexneamtu/sendrec) and GHCR automatically. Plus an Unraid community app template for one-click installation.
Structured logging. Migrated ~130 log calls from log.Printf to Go's log/slog with structured key-value fields. Custom HTTP middleware that skips health check noise.
Playwright e2e tests. 15 end-to-end tests covering auth, upload, library, settings, and watch pages. Run against a full Docker Compose stack with ephemeral volumes. Then we made them 12x faster — from 90 seconds to 7 seconds — by replacing UI-based login with API calls, adding connection pooling, and tuning health check timings.
OpenAPI documentation. All 95 API endpoints documented with Scalar UI at /api/docs.
And a handful of smaller things: configurable AI timeout for self-hosters running Ollama on slower hardware, webhook idempotency for billing events, comparison pages on the landing site, data-driven free tier limits.
What we learned
Browser APIs are surprisingly accommodating. The getDisplayMedia API silently ignores unknown constraints instead of throwing errors. This meant we could add Chrome-specific system audio constraints and ship them to all browsers without feature detection. Firefox and Safari just skip what they don't understand. More APIs should work this way.
50 segments is enough. When planning the engagement heatmap, we considered 100 or even per-second tracking. 50 segments (2% each) gives useful resolution — you can clearly see intro drop-off, mid-video engagement dips, and whether viewers reach your call-to-action. More segments would mean more data with no real improvement in actionable insight.
Server-side compositing was the right call. Canvas-based webcam overlay compositing breaks when the tab goes to the background (browser throttling kills requestAnimationFrame). Recording two separate streams and compositing with ffmpeg on the server is more work upfront but works reliably regardless of what the user does with their browser.
iOS is its own platform. Every video feature needs an iOS code path. Custom player controls, specific ffmpeg encoding flags, WebM-to-MP4 normalization, Safari-specific warnings. The investment is worth it — mobile viewing is a significant share of watch page traffic.
The obvious Playwright solution didn't work. Playwright's storageState is the standard way to share authentication across tests. It didn't work for us because our app stores access tokens in memory (not localStorage) and uses refresh token rotation. Each test context loaded the same saved token, the first test rotated it, and every subsequent test got an invalid token. The fix was simpler: skip the browser, POST to the login API directly.
Where we're heading
With the core product solid — recording, sharing, analytics, transcription, AI summaries, billing — the focus shifts.
Distribution. The product does what it needs to do. Now more people need to find it. LinkedIn (founder-led content about EU data sovereignty and building in public), Product Hunt (saving for a coordinated launch), and getting listed on european-alternatives.eu and awesome-selfhosted.
Team features. SendRec is currently single-user. The next major product milestone is team workspaces — shared video libraries, roles and permissions, team-level branding. This is what turns SendRec from a personal tool into something a company deploys.
Self-hosting improvements. Every release should make self-hosting easier. The Unraid template was a start. Better documentation, one-command deploys, and reducing the number of environment variables needed to get started.
The numbers
As of today: 465 unit tests, 15 e2e tests, 95 documented API endpoints, 45 blog posts, 64 releases. The codebase is Go + React + TypeScript + PostgreSQL + S3, licensed AGPL-3.0, and runs on a single Hetzner CX33 server in Helsinki.
Try it
SendRec is open source and self-hostable. Try it at app.sendrec.eu, pull the image from Docker Hub, or check the source code on GitHub.
Top comments (0)