DEV Community

On Pounch Man
On Pounch Man

Posted on

I Built TabScribe: A Free Chrome Extension to Copy All Browser Tabs as Markdown (Under 100KB, 12 Languages)

Why I Built TabScribe

After yet another research session where I found myself manually copying 20+ browser tab URLs one by one into my Obsidian notes, I decided enough was enough. I needed a tool that could copy all my tabs at once — in Markdown format.

I searched the Chrome Web Store. The existing options were either:

  • Too bloated (OneTab at 2M+ users, but does way more than I need)
  • Only supported plain text URL lists (Copy All URLs)
  • Abandoned for years (the old TabCopy extension)

So I built TabScribe over a couple of weekends.

What TabScribe Does

One click → all your tabs land in your clipboard in your chosen format:

  • Markdown [title](url) — perfect for Obsidian, Notion, VS Code
  • JSON array — great for data processing
  • Plain text — with custom delimiters
  • HTML unordered list — for web-based notes

Key Features

Keyboard Shortcut (Alt+Shift+C) — Copy all tabs without opening the popup

💾 Save & Restore Tab Groups — Save your tabs as named groups locally. Restore them in a new window later. Great for context switching.

📤 Export as Files — .md, .txt, .json, or .html with auto timestamps

🎯 Smart Filtering — Auto-excludes chrome://, edge://, about: pages. Optionally exclude pinned tabs.

🔧 Custom Delimiter — Set your own separator for text output (e.g., | for CSV-style)

🌐 12 Languages — English, 中文, 日本語, 한국어, Deutsch, Français, Español, Português, Русский, Bahasa Indonesia, and more

🎨 Dark Mode — Auto-follows system theme

Technical Deep Dive

Tech Stack

Preact + TypeScript + Tailwind CSS + Vite + crxjs
Bundle: ~63KB (gzipped: ~17KB)
Dependencies: 0 external runtime deps
Enter fullscreen mode Exit fullscreen mode

I chose Preact over React deliberately. For a Chrome extension popup, every kilobyte matters. Preact's 3KB footprint vs React's 40KB+ is a no-brainer. Plus, with @preact/preset-vite, the DX is nearly identical.

The Clipboard Challenge (Manifest V3)

The hardest technical problem was clipboard access in Manifest V3's Service Worker context.

In MV3, the background page is replaced by a Service Worker — which has no DOM. The document.execCommand('copy') fallback doesn't work there. Here's my solution:

// Double-fallback clipboard strategy
async function copyToClipboard(text: string, html?: string) {
  // Strategy 1: Modern Clipboard API (works in popup + offscreen)
  try {
    const item = new ClipboardItem({
      'text/plain': new Blob([text], { type: 'text/plain' }),
      ...(html ? { 'text/html': new Blob([html], { type: 'text/html' }) } : {}),
    });
    await navigator.clipboard.write([item]);
    return;
  } catch { /* fall through */ }

  // Strategy 2: execCommand fallback (popup context only)
  if (typeof document !== 'undefined') {
    const textarea = document.createElement('textarea');
    textarea.value = text;
    document.body.appendChild(textarea);
    textarea.select();
    document.execCommand('copy');
    document.body.removeChild(textarea);
    return;
  }

  // Strategy 3: Chrome Offscreen Document (Service Worker context)
  await chrome.offscreen.createDocument({ /* ... */ });
  // Route clipboard write through the offscreen document
}
Enter fullscreen mode Exit fullscreen mode

i18n Architecture

I used Chrome's built-in chrome.i18n API with 12 locale JSON files. The extension name and description in manifest.json use __MSG_key__ placeholders, so the Chrome Web Store automatically displays the right language.

// _locales/ja/messages.json
{
  "extensionName": { "message": "TabScribe" },
  "extensionDesc": { "message": "すべてのタブをMarkdown/JSON/HTMLで一括コピー" }
}
Enter fullscreen mode Exit fullscreen mode

Privacy by Design

TabScribe collects zero data. Period.

  • No analytics
  • No tracking pixels
  • No external servers
  • No network requests (except extension updates from Chrome)
  • Everything stored in chrome.storage.local

Only 6 permissions requested, each with a clear purpose:

Permission Why
tabs Read tab titles & URLs
clipboardWrite Copy formatted text
storage Save preferences & tab groups locally
commands Register keyboard shortcut
downloads Save exported files
offscreen Clipboard access in Service Worker

Try It

🔗 TabScribe on Chrome Web Store

It's free. No signup. No tracking. Just productivity.


Built with Preact + TypeScript + Tailwind CSS. Source code available on GitHub.

Top comments (0)