Source code and privacy policy for the SideDock browser extension.
  • JavaScript 69.6%
  • CSS 12.9%
  • HTML 8.8%
  • Python 8.7%
Find a file
2026-10-28 18:44:49 +00:00
icons feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
scripts feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
store feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
tests feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
.gitignore feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
app-config.js feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
manifest.json feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
package-lock.json feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
package.json feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
PRIVACY.md feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
README.md feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
service-worker.js feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
sidepanel.html feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
sidepanel.js feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00
styles.css feat: track SideDock extension source and preserve policy history 2026-10-28 18:44:49 +00:00

SideDock

A Chromium extension that keeps your saved web apps in Chrome's native side panel, with a 46-pixel app rail down its edge, similar to Vivaldi's web panels.

Click the toolbar button to open the side panel. Close it with the panel's own close button. The panel is one live page shared by every tab and window: switching tabs leaves the open app exactly as it was, including a half-typed message. Closing the panel ends its apps; they reload when you open it again. Click an app icon on the rail to show it; apps you have opened keep their state while you switch between them. The panel header holds the app name, reload, and a ⋯ menu for opening the app in a tab, editing it, and compatibility help.

Chrome draws the side panel's own header (with the SideDock name) and decides its width and side. Drag the panel's edge to resize it, and choose left or right in Chrome's Settings › Appearance › Side panel position. Earlier 2.x versions drew a dock inside each web page instead, to avoid that header. That dock could not share one app across tabs, and Claude refused to run under a website, so version 3.0 returned to the side panel. Its leftover settings are removed on update.

Use + to add a URL. Settings lists apps to edit or remove; right-clicking an app icon also edits it. New installs include Claude (https://claude.ai/new) with iframe compatibility enabled. Existing saved apps migrate to the sidebar, including previous tab/window shortcuts. Empty lists remain empty.

Install or update

  1. Open chrome://extensions in Chrome or edge://extensions in Edge.
  2. Enable Developer mode and choose Load unpacked, selecting this directory. For an existing unpacked install, click its Reload button.
  3. Accept any required extension permissions. If tabs still show the page dock from a 2.x version, refresh them to remove it.
  4. Click the SideDock toolbar button to open the side panel. Pin the button from the extensions menu to keep it in reach.

Keep the same extension ID to preserve saved apps. The side panel works beside any tab, including browser pages and PDFs.

Iframe compatibility

If a site refuses to appear, edit the app and enable Try iframe compatibility, then save. Chrome asks for access to that site's host. Claude's host access is included in the manifest for the requested experiment; other hosts are optional.

Compatibility uses declarativeNetRequest to remove X-Frame-Options and the response Content-Security-Policy for the enabled origin, including its scheme and port, only on sub_frame requests initiated by this extension. DNR cannot selectively remove an arbitrary CSP's frame-ancestors directive, so the whole response CSP is relaxed for those matching frame navigations. Other response headers, scripts, cookie values, normal top-level browsing, and frames initiated by ordinary websites remain unchanged. Disable compatibility or remove the last enabled app at that origin to remove its rule. Multiple apps at the same origin share the rule. The panel page is not web-accessible, so ordinary websites cannot frame it to borrow the compatibility rules.

The site permission also activates Chrome's extension-specific storage and cookie exceptions. In the browser test, an app inside the panel page received an existing SameSite=Strict; HttpOnly session cookie and reused its first-party local storage. If login is needed, use Sign in in a tab, finish sign-in there, then reload the app inside the sidebar. The tab is for establishing the login, not an app launch mode.

Limits remain:

  • Under the 2.x page dock, Claude showed "This page can't run in an embedded view" and failed after login, because a website sat above its frame. In the side panel, automated testing reaches Cloudflare's interactive "Verify you are human" check; a signed-in Claude session there has not been verified yet. Server-side verification and frame-detection scripts can still refuse an iframe.
  • Cross-domain login redirects and document navigations initiated inside an app can encounter frame restrictions again. Rules deliberately match extension-initiated navigations; they do not relax every request from an app domain.
  • Service-worker-generated/cached responses can bypass DNR. The extension does not clear site data or unregister site workers, which could lose sessions or offline data.
  • Browser privacy settings, cookie partitioning, and an app's authentication design can still prevent login reuse. No cookies are copied or rewritten.

Does a server help?

The first approach keeps authentication in the local browser and needs no server. A reverse proxy cannot automatically reuse local browser cookies; third-party login callbacks, cookie domains, scripts, and verification make transparent proxying fragile.

A different fallback is a persistent browser session running on the server, with its interactive display streamed into our iframe through an authenticated HTTPS endpoint. Kasm documents this iframe approach. The user would sign in separately in that remote browser. That would require server access and a protected, per-user browser profile; it is not implemented here.

Development checks

Run npm ci, npx playwright install chromium, then npm test. Tests load the actual extension in Chromium, use local HTTP fixtures, and do not need an account or external network. Chrome's side panel cannot be opened from a test, so they load the same panel page in a tab. They verify the toolbar's side-panel behavior, blocked/allowed framing, reuse of an existing session, draft retention while switching apps, rule scope and removal, missing site access, migration, empty lists, and that websites cannot embed the panel page. Tests add only loopback host permissions to an isolated copy of the extension.

Chrome Web Store release

Since 2.5.0, SideDock uses a blue and white sidebar icon based on Nodefav's palette. Its editable vector source is icons/icon.svg.

Run npm run package to generate sidedock-<version>.zip with only runtime files. Store submission copy and field instructions include the description, privacy disclosures, permission justifications, reviewer steps, and publisher details. The privacy policy source is hosted publicly on Forgejo, matching Nodefav's setup. Run npm run publish:privacy after changing it to update the hosted copy using your configured Git credentials.

store/assets contains three 1280×800 screenshots of the 2.x page dock (outdated for 3.0; npm run store:screenshots still targets the removed dock and needs rewriting before the next store submission), plus small and marquee promotional images. Regenerate them with npm run store:screenshots and npm run build:assets respectively; these require Playwright Chromium. These demo pages and temporary loopback permissions are excluded from the release ZIP.