$ cat ./work/context.mdx

Context

2026 · Shipper · sortcontext.com

Context is a session-replay and activity tracking tool for small teams. Live at sortcontext.com. You drop a script tag into your app and every click, scroll, input, and navigation becomes a replayable session — the kind of visibility Logrocket and Hotjar sell to enterprises, built for teams that can't stomach the per-seat bill.

## Problem

You ship a feature. A user hits a bug. You ask "what did they do?" and get three sentences. The tools that answer that question well (Logrocket, FullStory, Hotjar) are priced for companies with revenue to justify them. The ones priced for the rest either don't capture enough or drown you in dashboards.

Context is the smallest version of that tool that still earns its keep — recording, replay, activity timelines, lightweight analytics. Nothing else.

## The non-obvious call — split storage

Session recordings are huge and read rarely. Session metadata is small and read constantly. Putting both in Postgres was the obvious move, and the wrong one.

Cloudflare R2 for session blobs — S3-compatible, zero egress, scales by object count. Writes are append-only NDJSON. → Supabase / Postgres for everything queryable — users, workspaces, session index, activity events.

The result: listing sessions stays fast, replay-click stays cheap, and adding a new customer costs a few cents of storage, not a shard migration.

## rrweb as the substrate

rrweb captures the DOM as a full snapshot plus a stream of incremental mutations. Replay is deterministic — given the events, you get the page back. Fetch the NDJSON, parse events, hand them to rrweb-player, sandbox the iframe so the replay can't phone home.

Building on rrweb instead of rolling our own was a dependency call I kept second-guessing for a week. In hindsight it freed a month of work; the hard problems are in storage, privacy, and the dashboard, not the recorder.

## What the product captures

Each session gets an automatic thumbnail — the landing page at the moment of capture — so the session list reads like a wall of visited screens, not a list of UUIDs. Thumbnails are generated by a background Puppeteer worker, uploaded to R2, and referenced by the Postgres row. The user never waits on it.

## What's next

Stitched journeys across sessions — so "the user who signed up yesterday, bounced today" is one timeline, not three. Privacy-first: no fingerprinting, no cross-site, opt-in for any PII capture. Enterprise features only when they don't compromise that.

## Close

The bet is simple. Session replay should be commodity, not a line item. A small team should be able to see what their users do without a sales call, without a rewrite, without a log aggregator pipeline. Context is that, as small as I could make it and still be useful.

Live at sortcontext.com.

$
? keys · ⌘K palette · esc back