跪拜 Guibai
← All articles
JavaScript

Build a Chrome Side Panel That AI-Translates English Pages to Markdown

By mONESY ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Chrome's side panel API remains underused compared to popups, yet it solves the cramped-UI problem that makes many translation extensions unpleasant. This scaffold shows how to wire it with Manifest V3, strongly-typed cross-context messaging, and streaming AI output — a stack that transfers directly to summarizers, explainers, or any tool that processes page content through an LLM.

Summary

The extension uses a side panel rather than a popup, giving the translated output room to breathe. Four config files and thirteen source files form the skeleton: a content script clones and sanitizes the DOM before converting it to Markdown via Mozilla's Readability and Turndown, a background service worker orchestrates extraction and calls the AI API with SSE streaming, and a React panel renders the result with a typewriter effect. The messaging layer is fully typed so that protocol mismatches between the three contexts break at compile time.

API Key handling stays strictly in the background worker; the content script never touches it. The translation pipeline is provider-agnostic — swapping base URL, key, and model in the settings panel switches between DeepSeek, Qwen, GLM, or any OpenAI-compatible endpoint without code changes.

The guide is deliberately mechanics-only: it lists every file, its responsibility, and the exact configs to copy-paste, then leaves the logic implementation to the reader based on the annotated structure.

Takeaways
The extension opens a side panel, not a popup — `manifest.json` declares `side_panel` and omits `default_popup`.
`setPanelBehavior({ openPanelOnActionClick: true })` makes a toolbar icon click open the side panel directly.
Content extraction clones the DOM first to avoid mutating the live page, then normalizes lazy-loaded image URLs before passing the clone to Readability.
Extracted HTML is sanitized with DOMPurify and converted to Markdown with Turndown; a 50-character minimum triggers a selector-based fallback.
The AI call uses native `fetch` against an OpenAI-compatible streaming endpoint (`stream: true`), parsing SSE `data:` lines until `[DONE]`.
API keys live only in the background service worker — content scripts and pages share a less-trusted context and never access the key.
All cross-context messages (background, content script, side panel) are defined in a single strongly-typed `messages.ts` file.
Switching AI providers requires only changing Base URL, model, and key in the settings UI; no code edits are needed.
The build toolchain is Vite + crxjs, producing the loadable extension in a `dist/` folder — loading `src/` or the project root will fail.
The side panel's height auto-fills the viewport, but width must be adjusted manually by dragging the panel's left edge.
Conclusions

Treating the extension's three execution contexts (background, content script, side panel) as a distributed system with a typed message contract is the architectural move that prevents most silent runtime bugs.

The guide deliberately omits code for the 13 logic files and instead annotates their responsibilities — this forces the builder to engage with the structure rather than copy-pasting blindly, which is unusual for a "newbie-oriented" tutorial and likely intentional.

Using `@crxjs/vite-plugin` to bundle a Manifest V3 extension with React and TypeScript is still a relatively niche toolchain choice; the scaffold demonstrates it works but the plugin's long-term maintenance is a dependency risk worth noting.

Concepts & terms
Chrome Side Panel API
A Manifest V3 feature that lets an extension open a persistent panel attached to the browser's side, distinct from the transient popup window. It requires the `sidePanel` permission and a `side_panel` manifest entry.
SSE (Server-Sent Events)
A streaming protocol where the server pushes incremental data over a single HTTP connection. OpenAI-compatible chat APIs use it to deliver tokens as they're generated, with each chunk prefixed by `data:` and the stream terminated by `data: [DONE]`.
Readability (Mozilla)
A library that extracts the main readable content from a web page, stripping navigation, ads, and clutter. Originally powering Firefox's Reader View, it's now a standalone package used in many content-processing tools.
Turndown
A JavaScript library that converts HTML to Markdown. It's used here to turn sanitized page content into a format the LLM can reliably preserve during translation.
DOMPurify
A DOM-only XSS sanitizer for HTML. In this extension, it cleans extracted page content before any further processing, since page HTML is treated as untrusted input.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗