# Architecture Technical overview of how TraceBug works internally — the **file-by-file tour**. For the system-level overview (data flow, subsystems, design positions), start at the root [ARCHITECTURE.md](../ARCHITECTURE.md); for the *why* behind the big decisions, see the [ADRs](adr/README.md). ## Build System TraceBug uses [tsup](https://tsup.egoist.dev/) (powered by esbuild) to produce three outputs from a single build command: ```bash npm run build ``` | Output | Format | Location | Purpose | |--------|--------|----------|---------| | ESM | `dist/index.js` | npm package (import) | Modern bundlers (Vite, webpack 5+) | | CJS | `dist/index.cjs` | npm package (require) | Node.js, older bundlers | | IIFE | `tracebug-extension/tracebug-sdk.js` | Chrome Extension | `window.TraceBug` global | | CLI | `dist/bin.mjs` | `npx tracebug` | CLI tool for project setup | | DTS | `dist/index.d.ts` / `dist/index.d.cts` | TypeScript types | IDE autocompletion | The IIFE build includes a footer script that exposes `window.TraceBug` with a `__TRACEBUG_LOADED__` guard to prevent double loading. ### Build Scripts | Script | Command | Description | |--------|---------|-------------| | `npm run build` | `tsup` | Build all outputs (npm + extension) | | `npm run build:all` | `tsup` + status | Build + print output summary | | `npm run build:example` | `tsup` + example install | Build + update example app | | `npm run dev` | `tsup --watch` | Watch mode for development | | `npm run prepare` | `tsup` | Auto-build on `npm install` / `npm pack` | ### Configuration Build config is in `tsup.config.ts`: ```typescript export default defineConfig([ // npm package: CJS + ESM + TypeScript declarations { entry: ["src/index.ts"], format: ["cjs", "esm"], dts: true, clean: true, }, // CLI tool: ESM with shebang { entry: { bin: "cli/bin.ts" }, format: ["esm"], platform: "node", target: "node18", banner: { js: "#!/usr/bin/env node" }, }, // Chrome Extension: IIFE bundle { entry: { "tracebug-sdk": "src/index.ts" }, format: ["iife"], globalName: "TraceBugModule", outDir: "tracebug-extension", }, ]); ``` ## Source File Map ``` src/ ├── index.ts # Entry — TraceBugSDK class, public API, exports ├── types.ts # All TypeScript interfaces ├── collectors.ts # Event collectors + console/network/Performance backfill ├── storage.ts # localStorage persistence with batched writes ├── action-chips.ts # Verb + element-preview chips for the Actions tab ├── repro-generator.ts # Human-readable reproduction steps ├── dashboard.ts # Session panel UI orchestrator ├── compact-toolbar.ts # Configurable toolbar (position, drag, mobile FAB) ├── element-annotate.ts # Element-level annotation mode ├── draw-mode.ts # Rect / ellipse / redact drawing on the page ├── annotation-store.ts # In-memory annotation store ├── theme.ts # Design tokens (dark / light / auto) ├── onboarding.ts # First-run tour ├── plugin-system.ts # Plugin API + event hooks ├── environment.ts # Browser / OS / viewport detection ├── screenshot.ts # html2canvas + extension captureVisibleTab ├── video-recorder.ts # MediaRecorder lifecycle (in-page + offscreen transports) ├── voice-recorder.ts # Web Speech API ├── title-generator.ts # Auto bug title + flow summary ├── timeline-builder.ts # Event timeline ├── report-builder.ts # BugReport assembly ├── fingerprint.ts # Deterministic session/error fingerprints ├── dev-api.ts # Dev-mode API hooks ├── github-issue.ts # GitHub markdown generator ├── jira-issue.ts # Jira ticket generator ├── linear-issue.ts # Linear deeplink generator ├── slack-export.ts # Slack-flavored export ├── pdf-generator.ts # Print-optimized HTML report ├── rrweb-recorder.ts # Lazy rrweb DOM recorder (masked; .tb-block/.tb-mask) ├── ai/llm-client.ts # BYO-key LLM analysis (Anthropic / OpenAI / Ollama) ├── integrations/tracker-client.ts # Real GitHub / Linear / Slack / Jira issues ├── reporters/playwright.ts # Playwright reporter (failed test → .html) ├── exporters/ │ ├── html-replay.ts # Self-contained replay bundler (gzip rrweb stream) │ ├── html-template.ts # Inlined viewer template + inflate/mount runtime │ ├── rrweb-runtime.generated.ts # Inlined rrweb Replayer (npm run gen:rrweb) │ ├── ai-prompt.ts # AI prompt + .md report + "Export for AI (.html)" │ ├── har-export.ts # HAR 1.2 network export │ └── share-link.ts # Cloud share upload (PHASE2-CLOUD, gated off) ├── patterns/ # Heuristic detectors (frustration, etc.) ├── scanner/ # Auto-bug scanner + detector modules └── ui/ ├── index.ts # Barrel export ├── helpers.ts # Shared utilities ├── toast.ts # Toast notifications ├── quick-bug.ts # Tabbed ticket modal ├── issues-panel.ts # Session list + scanner findings panel ├── recording-hud.ts # Floating recording timer + Stop / Capture / Draw ├── replay-scrubber.ts # Timeline scrubber for video replay └── live-bug-card.ts # Inline notification card for auto-detected bugs cli/ └── bin.ts # CLI tool source (compiled to dist/bin.mjs) ``` ## Data Flow ``` User interacts with page ↓ Event collectors (collectors.ts) capture clicks, inputs, API calls, errors, console ↓ Self-filtering: isTraceBugElement() checks → skip our own UI events ↓ Emit function creates TraceBugEvent objects ↓ Plugin system: runEventPlugins() — plugins can filter/transform events ↓ Batched writes to localStorage (storage.ts, 1s flush interval) ↓ Hook system: emitHook("error:captured", event) notifies subscribers ↓ On error: auto-generate reproduction steps (repro-generator.ts) ↓ Dashboard reads from localStorage to render session list/detail (tabbed view) ↓ User exports: GitHub Issue / Jira Ticket / PDF / JSON / Text ``` ## Chrome Extension Architecture ``` Popup (popup.html/js) ↓ chrome.runtime.sendMessage Background Service Worker (background.js) ────┐ ↓ chrome.scripting.executeScript │ chrome.offscreen.createDocument ↓ chrome.tabs.sendMessage ↓ Content Script (content-script.js) Offscreen Document (offscreen.html / offscreen.js) — extension context on page — holds MediaStream + MediaRecorder ↓ CustomEvent dispatch — persists recording via service worker Page Context (tracebug-init.js + tracebug-sdk.js) — MAIN world ↓ TraceBug SDK methods ``` **CSP-Safe Injection:** Uses `chrome.scripting.executeScript({ world: "MAIN" })` — no `