How Vertical Tab Extensions Use the Firefox Sidebar API
This article provides a quick overview of the technical relationship between popular vertical tab extensions, such as Tree Style Tab and Sidebery, and the Firefox Web Browser's Sidebar API. It covers how these extensions allocate user interface space, synchronize with browser tabs in real-time, maintain hierarchical tree structures across sessions, and navigate the security limitations of the Firefox WebExtensions framework.
Declaring the Sidebar Space
To exist in the Firefox sidebar, extensions like Tree Style Tab and
Sidebery must first declare their presence in their
manifest.json configuration file. They achieve this using
the sidebar_action manifest key.
This key defines the default title, icon, and, most importantly, the
local HTML file (default_panel) that Firefox will render
inside the sidebar container. Unlike content scripts that are injected
into standard web pages, this HTML file runs in a privileged extension
context. It acts as a persistent, independent webpage positioned next to
the main browser viewport, styled entirely with the extension's own
CSS.
Controlling the
View with browser.sidebarAction
Once declared in the manifest, the extension controls the sidebar's
behavior using the browser.sidebarAction JavaScript API.
This API allows the extension to programmatically open, close, or toggle
the sidebar panel—usually in response to a user clicking a toolbar
button or pressing a keyboard shortcut like F1.
Because a user might have multiple Firefox windows open at once, the
sidebarAction API scopes its operations by
windowId. This allows Sidebery and Tree Style Tab to render
a unique sidebar instance for every open window, ensuring that the
vertical tab bar only displays the tabs relevant to the specific window
the user is currently viewing.
Real-Time
Synchronization via browser.tabs
The Sidebar API itself is merely a blank container; it does not
inherently know anything about browser tabs. To function as a tab
manager, vertical tab extensions rely heavily on the
browser.tabs API.
When the sidebar HTML document loads, its JavaScript executes
browser.tabs.query({currentWindow: true}) to fetch an array
of all open tabs in that window. The extension then builds a Document
Object Model (DOM) representation of these tabs inside the sidebar.
To keep the sidebar synchronized with the browser, the extension
attaches event listeners to the browser.tabs API:
onCreated: Fires when a new tab is opened, prompting the extension to insert a new tab element into the sidebar DOM.onRemoved: Fires when a tab is closed, telling the extension to delete the corresponding element.onUpdated: Fires when a tab's URL, title, or favicon changes, allowing the sidebar to update loading spinners and text.onActivated: Fires when the user switches tabs, allowing the extension to highlight the newly active tab in the vertical list.
Conversely, when a user clicks, drags, or closes a tab inside the
extension's sidebar, the extension captures that click event and sends a
command back to Firefox (such as browser.tabs.remove() or
browser.tabs.move()) to execute the action in the actual
browser.
Creating and Saving the "Tree" Structure
Firefox’s native tab system is completely flat, meaning the browser
does not natively understand parent-child tab relationships. Tree Style
Tab and Sidebery manufacture this hierarchy by combining the
openerTabId property with the browser.sessions
API.
When you middle-click a link on a webpage to open a new tab, Firefox
records the ID of the source tab in the new tab's
openerTabId property. The vertical tab extension reads this
property and visually indents the new tab underneath the source tab in
the sidebar's HTML.
However, if the user restarts Firefox, the openerTabId
data can be lost or insufficient for complex trees. To solve this,
extensions use the browser.sessions.setTabValue() API. This
allows the extension to attach custom JSON metadata—such as tree depth,
custom group colors, collapsed states, and parent IDs—directly to the
native Firefox tab object. When Firefox restarts and restores the
session, the extension calls getTabValue() on every tab to
reconstruct the exact visual tree structure.
API Limitations and the Native Tab Bar
While the interaction between these extensions and the Firefox API is robust, it is restricted by WebExtensions security boundaries. The Sidebar API only grants the extension control over the rectangular box of the sidebar itself; it does not allow the extension to modify the rest of the Firefox user interface.
Because there is no API available to hide the native horizontal tab
strip at the top of the browser, users of Tree Style Tab and Sidebery
end up with two visible tab bars by default. To bypass this API
limitation, users must manually create a userChrome.css
file in their Firefox profile directory to hide the native horizontal
tabs using custom CSS rules.