When people see a browser extension add translation controls, a side panel, or a sending workflow to WhatsApp Web, a common question is: how does the extension actually interact with the page?
The short answer is that a modern Chrome extension is split across several execution environments.
No single script should be responsible for the interface, persistent state, task scheduling, and access to the page at the same time.
This article explains the architecture at a practical level without depending on private implementation details that may change whenever WhatsApp Web changes.
A browser extension does not run as one program The simplest mental model is to divide the extension into four parts: The extension interface A background service worker A content script attached to WhatsApp Web A small bridge running in the page's own JavaScript context Each part has a different job and a different level of access.
The extension interface is what the user sees: forms, task history, translation settings, saved scripts, and media selection.
It should focus on interaction rather than long-running work.
The background service worker coordinates tasks and stores state.
It can receive a request from the interface, keep track of progress, and send commands to the correct WhatsApp Web tab.
The content script lives alongside the webpage.
It can inspect the rendered document, inject controls, and communicate with the extension runtime.
Chrome isolates it from the page's own JavaScript environment for security.
The page bridge exists because isolation is sometimes a limitation.
A content script can see the DOM, but it does not automatically share the same JavaScript objects as WhatsApp Web.
When deeper page integration is required, a carefully scoped bridge can exchange explicit messages between the isolated extension world and the page world.
Why not put everything in the content script?
It is tempting to keep the entire feature in one file because the content script is already attached to WhatsApp Web.
That approach becomes fragile quickly.
The script would have to render the interface, observe the page, manage tasks, store data, process media, handle retries, and survive navigation changes.
When one part fails, it becomes difficult to determine whether the problem came from the UI, the task state, or the page integration.
Separating responsibilities creates clearer failure boundaries: The interface validates user input and displays state.
The background worker owns task progression.
The content script owns visual integration with the current page.
The page bridge performs only the operations that require page-context access.
This separation does add message passing, but that complexity is easier to reason about than a single script with hidden dependencies everywhere.
The side panel and the chat page are separate surfaces MSG.AI adds a workspace next to WhatsApp Web instead of replacing the page.
The panel is useful for operations that need space: reviewing recipient lists, editing reusable scripts, viewing task progress, or choosing media.
Small actions, such as translating one message, are more natural next to the message itself.
That creates two interface surfaces that must remain synchronized.
For example, changing a target language in the panel should affect the translation action beside the current conversation.
Pausing a task should update both the background state and the progress shown in the panel.
If the user reloads WhatsApp Web, the interface should restore from persistent state instead of inventing a new task.
The lesson is that DOM injection is only the visible part of the work.
State coordination is usually harder.
Page changes are the main source of fragility WhatsApp Web is a living application.
It changes without following the release cycle of a third-party extension.
CSS class names can change.
Buttons may move.
The composer can be rebuilt.
A message bubble may render differently for media, quoted replies, reactions, or dif