VISUALLIdesign system

Surface

Chrome extension

The Chrome extension, prototyped: the toolbar button (or the page's right-click menu) opens Visualli in Chrome's side panel beside the page you're reading — the same visual browsing as the MCP card, no vault or chat — with Open in Visualli to continue the journey.

Live prototype · ExtensionView DesktopOpen ↗

How it works

Features

6 of 6 features that apply here are UX ready · 9 N/A · Feature matrix for Chrome extension

UX ready 6
N/A 9

Build it

The Visualli extension does one thing: visualize the page you're reading in Chrome's side panel, with Open in Visualli to continue there. Component: ExtensionPanel.

The experience

  1. Toolbar button — the tree mark. Tooltip "Visualize this page", keyboard shortcut Alt+Shift+V (commands). Clicking opens the side panel for the current tab; clicking again closes it. Right-click — one item in the page's context menu (contexts: ['page']): Visualize this page, with the tree icon. Same result as the button. There is no "visualize selection" — the whole page is always the source.
  2. Reading — ExtensionPanel status="reading": the growing tree and Reading ‹domain›…; ideas bloom in as they're found.
  3. The map — status="ready": a read-only VisualMap with everything browsing does (peek, terms, Step inside, Go deeper, Map it). No edit, no moving, no vault, no composer — like the MCP card.
  4. Open in Visualli — the one primary action: saves the map to the user's vault and opens it in the app (new tab), where chat, editing and sources continue.
  5. Can't read — status="error": Couldn't read this page (login, paywall, too little text) and Try again.

Why the side panel (and not split view)

// background.js (MV3 service worker)
chrome.runtime.onInstalled.addListener(() => {
  chrome.contextMenus.create({ id: 'visualize-page', title: 'Visualize this page', contexts: ['page'] });
});

async function openPopup(tab) {
  const win = await chrome.windows.getCurrent();
  chrome.windows.create({ url: `panel.html?tab=${tab.id}`, type: 'popup', width: 440, height: win.height, left: win.left + win.width - 440, top: win.top });
}

if (chrome.sidePanel?.setPanelBehavior) {
  chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true });
} else {
  chrome.action.onClicked.addListener(openPopup);
}

chrome.contextMenus.onClicked.addListener((info, tab) => {
  if (info.menuItemId !== 'visualize-page') return;
  // sidePanel.open() must run synchronously inside the click (user gesture) — Chrome 116+.
  if (chrome.sidePanel?.open) chrome.sidePanel.open({ tabId: tab.id });
  else openPopup(tab);
});

Permissions: sidePanel, contextMenus, activeTab, scripting (read the page's text on click — no broad host permissions), storage.

Rules

Prototype source: components/catalog/ExtensionView/preview.html · Build notes: docs/platforms/chrome-extension.md