← ProjectsTRAIL
All systems operational

TRAIL

Hit a bug, hit Record. TRAIL captures every click, console error and failed request and turns it into a replay you can watch and a GitHub issue you can actually file. No SDK, no account, nothing leaves your browser until you say so.

Next.js
React
TypeScript
Tailwind CSS
GSAP
+3 more
TRAIL demo preview

Why I Built This

WhyIBuiltThis

Most bug reports are useless because the evidence is gone before the report is written. Nobody remembers the exact clicks. Nobody saved the console output. Network errors vanish on refresh. So maintainers ask for a reproduction and the issue sits open for months while everyone guesses.

I have been on both sides of that thread. Screen recordings miss the steps. Copy pasted logs miss the context. SDKs only work if the site owner installed them months ago. For open source, where anyone can file, there was no way to get a complete replayable report without asking the reporter to become a debugger.

My Approach

MyApproach

TRAIL is a Chrome extension I built with WXT and React to fix that. The hard part is capture. A normal content script runs in an isolated world, so patching console or fetch there patches a copy the page never uses. TRAIL splits the job. A tiny script runs in the page's own world at document_start and patches the real functions. It forwards everything over postMessage to a relay in the isolated world, which batches to a background worker once a second. The worker does almost nothing except write to IndexedDB. That is deliberate. Chrome will kill the worker mid recording, and when it does you keep what you already captured. A draggable overlay shows live counts so you know it is working.

When you stop, TRAIL opens a review tab. Replay on the left, timeline on the right. Navigated to checkout, typed in Email, clicked Submit, console error, POST failed with 500. You name the target repo and TRAIL pulls its real GitHub issue templates, then fits the report to those fields. It builds a prefilled issues/new URL but keeps it under 7600 characters so GitHub does not return a 414. If it has to cut, it cuts low priority sections first and tells you what was trimmed. The full Markdown is always on your clipboard and available as a .md download. If the replay server has keys set, a redaction safe digest goes to OpenRouter for the report draft and Groq for the title, cached by session hash and merged in. No keys, the deterministic report still ships. Sharing uploads to Vercel Blob in prod or the local file store in dev and gives you a https://trail-bug.vercel.app/r/<id> link that renders the same review UI for anyone.

Key Features

KeyFeatures

  • One click capture. Clicks, typing, console errors, failed requests and a full rrweb replay on any site with no SDK
  • Privacy first. Passwords, emails and card numbers are masked at capture time and never written to disk
  • A real report, not a dump. Deterministic Markdown plus a prefilled GitHub issue URL that maps to the repo's actual templates
  • Optional AI help. The replay server proxies to OpenRouter and Groq for title, summary and steps. No key, no problem, the report still builds
  • Shareable links. Every session gets a /r/<id> page anyone can open. If they have the extension it hands off with a short countdown and imports to history
  • History that actually works. Everything lives in IndexedDB. Reopen any report and you get the replay, timeline and exports back exactly as you left them

How the System Works

HowtheSystemWorks

Record the bug where it happens, check the replay and timeline, then ship a GitHub ready report or a link anyone can open.

  1. Open the TRAIL popup and press Begin Recording. Auto redact is on by default and Start Report stays visible
  2. The page world recorder patches real console, fetch and XHR and starts rrweb. Events flow over postMessage to the relay and batch to IndexedDB about once a second
  3. Reproduce the bug normally. The overlay shows live counts for clicks, errors and failed requests. Press Stop and the review tab opens
  4. The review UI rebuilds the timeline and plays the rrweb session alongside it. A second redact toggle is there if anything sensitive slipped through
  5. Enter the target repo. TRAIL fetches its GitHub templates and, when configured, sends a redaction safe digest to the replay server for an AI title and summary
  6. TRAIL merges any AI draft into the deterministic Markdown, mints a GitHub new issue URL inside the character budget, copies the full report to clipboard, offers a .md download and saves to history
  7. Press Share to upload the payload under a random UUID. Re sharing the same content reuses the link because the payload is hashed locally. The Next.js viewer at /r/<id> fetches it and renders inline, or hands off to the extension with a ten second countdown if it is installed

Engineering Challenges & Lessons Learned

EngineeringChallenges&LessonsLearned

Patching in the wrong world does nothing. An isolated content script patches a copy of console and fetch the page never calls. I fixed it by splitting recorder and relay. recorder.content.ts runs in MAIN world where the real functions live and forwards events, relay.content.ts runs isolated and batches them to the background worker

The service worker will die while you are recording. Chrome guarantees it. I kept the worker stateless and wrote every batch straight to IndexedDB. Only counters live in chrome.storage.session. If the worker restarts you lose nothing you already captured

rrweb ships a literal U+FFFE character that Chrome content script loader rejects as invalid UTF 8. I added a WXT Vite plugin called escapeNonAscii in wxt.config.ts that escapes every non ASCII byte to \uXXXX at build time. Same runtime, pure ASCII output, Chrome loads it

GitHub will return a 414 if the new issue URL is too long, usually around 8 KB. lib/github.ts enforces a 7600 character budget and trims sections in priority order, appending a short note when it cuts. The full report always goes to the clipboard so nothing is actually lost

What I’d Improve Next

WhatI’dImproveNext

  • Duplicate detection. Embed the digest and warn when a similar open issue already exists
  • Direct GitHub API submission for authenticated users and exporters for Linear and Jira
  • Cross origin iframe recording, a proper Firefox build and better handling for very large sessions beyond the current 30 MB limit

YOU MADE IT THIS FAR

Let’s build something exceptional together.

Tell me about your project and I’ll help you shape it into a polished, high-performing experience.