Mirror DOM interactions from a source tab to a target tab in real time.
MirrorTab is a Chrome extension that captures user interactions on one browser tab (the source) and replays them live on another tab (the target). It supports clicks, keyboard input, form changes, and scrolling - with session recording and export built in.
- Live mirroring - clicks, inputs, keystrokes, and scroll events are forwarded from the source tab to the target tab in real time
- Session control - start, pause, resume, and stop a mirroring session from the popup
- Role badges - a floating badge on each tab shows whether it is SOURCE or TARGET
- Session recording - all events replayed on the target tab are recorded with timestamps
- Export - download the recorded session as JSON or plain text before or after stopping
- Smart selector - elements with an
idare resolved via#id; all others use a full structural CSS path, keeping replay accurate across DOM changes
Requirements: Node.js 18+, pnpm
# 1. Clone the repository
git clone https://github.com/KostaD02/MirrorTab.git
cd MirrorTab
# 2. Install dependencies
pnpm install
# 3. Start the dev server
pnpm startThen load the unpacked extension in Chrome:
- Open
chrome://extensions - Enable Developer mode (top-right toggle)
- Click Load unpacked
- Select the
dist/folder generated by the dev server
The extension hot-reloads on file changes while pnpm start is running.
pnpm buildThe production bundle is written to dist/ and a ready-to-upload .zip is placed in release/.
- Click the MirrorTab icon in the Chrome toolbar to open the popup
- Enter a Source URL and a Target URL
- Click Start Session - two new tabs will open automatically
- Interact with the SOURCE tab; every action is mirrored to the TARGET tab in real time
- Use Pause / Resume to temporarily suspend mirroring without closing the session
- Use Download JSON or Download Text to export the full event log from the target tab at any time
- Click Stop to end the session - recorded events are cleared
src/
├── background/
│ ├── index.ts # Service worker entry: wires session + tab listeners
│ ├── message-router.ts # Routes chrome.runtime messages to SessionManager
│ └── session-manager.ts # Class managing the full session lifecycle
│
├── content/
│ ├── main.ts # Content script entry: bootstraps capture, replay, badge
│ ├── mirror.ts # EventCapture (source) + EventReplay (target) classes
│ └── role-badge.ts # Floating SOURCE / TARGET badge injected into the page
│
├── popup/
│ ├── index.html # Popup markup
│ ├── main.ts # Mounts PopupController
│ ├── controller.ts # All popup UI logic and message dispatch
│ ├── validate-url.ts # URL validation helper
│ └── style.css # Popup styles
│
└── shared/
├── consts/ # APP_NAME, STORAGE_KEY, retry config
├── types/ # TypeScript interfaces and enums
└── util/ # Pure utility functions (selector, logger, tab helpers, …)
Each entry in the exported session log contains:
| Field | Description |
|---|---|
timestamp |
ISO 8601 timestamp of when the event was replayed |
type |
Event type: click, input, change, keydown, keyup, scroll |
selector |
Compact element identifier: TAG#id#firstClass#attr=val |
selectorStackTrace |
Full CSS structural path used for DOM resolution |
content |
Event-specific payload (coordinates, value, key info, scroll position) |
| Permission | Reason |
|---|---|
tabs |
Open source/target tabs and track their lifecycle |
scripting |
Inject the content script into tabs dynamically |
storage |
Persist the active session across service worker restarts |
host_permissions |
Send messages to content scripts on http:// and https:// pages |
Bug reports and feature requests are welcome via GitHub Issues. Please use the provided issue templates.
MIT © Konstantine Datunishvili