This site is a work in progress — still shipping new things every week

Vortex Failed. Here's What I Learned.

Koushith
6 min read

Vortex Failed. Here's What I Learned and What I'm Doing With It.

Last year I built a Chrome extension and it worked nicely for a few websites.

I had like 80+ tabs open while researching something and had zero idea how any of them connected to each other. Tab managers dont solve this. They just add more UI on top of the same broken thing. Browsing is spatial but tabs are linear. Nobody thinks in a flat list of 90 rectangles.

So I built Vortex. Every website becomes a node on an infinite canvas. Click a link inside a node and it spawns as a connected child node. Your research trail maps itself visually. Figma prototype view but for actual browsing.

VortexClick to enlarge

I was using it daily for weeks. Layer panel like Figma, minimap for navigation, sticky notes on any node, color coding for different threads. It worked.

Then it started breaking everywhere.


What Killed It

Chrome's Manifest V3. But it wasnt just one thing. Let me explain.

The core of Vortex is: render actual live websites inside nodes on a canvas. User clicks a link inside one of those rendered sites, instead of navigating away it spawns a new connected node. Thats the whole product.

To do this you need to embed third-party websites in iframes inside your extension. And Manifest V3 made that nearly impossible for any real website.

Vortex with working sitesClick to enlarge

CSP Headers

Most websites ship Content-Security-Policy with frame-ancestors 'self' or frame-ancestors 'none'. This tells the browser "dont let anyone embed me in an iframe". Google Docs, Notion, GitHub, Linear, every tool you'd actually want on your research canvas sets this. Browser just refuses to load them. Blank frame. No error you can catch either, the iframe just silently refuses.

X-Frame-Options

Older sites that dont use CSP still set X-Frame-Options: DENY or SAMEORIGIN. Same result. Browser blocks the embed before your code even runs.

The Manifest V3 Problem

In V2 you could use webRequest API to intercept responses and strip CSP/X-Frame-Options headers before the browser enforced them. Hacky but it worked. V3 killed webRequest for response modification. Moved everything to declarativeNetRequest which is static rules declared upfront. You cant dynamically modify response headers based on context anymore. Chrome reviews these rules and they dont like you stripping security headers.

COEP/COOP

Then theres the newer stuff. Cross-Origin-Embedder-Policy: require-corp means the embedded site needs to explicitly opt in to being embedded. Almost no site does this for random extensions. So even if you somehow bypass CSP, COEP blocks you at another layer.

The Proxy Workaround (And Why It Sucks)

I could have gone the proxy route. Run every website through a server that strips all security headers before serving to the extension. Some tools do this.

But think about what that means:

  • You're proxying every website the user visits through your server. Privacy nightmare.
  • Expensive to run. Every page load hits your infra.
  • Still breaks sites that rely on same-origin cookies, WebSocket connections, or service workers.
  • You become responsible for all that traffic.

The Permission Problem

Other option was requesting <all_urls> permission with full host access. Chrome Web Store reviewers flag this immediately. Review times go from days to weeks. And users see that "this extension can read and change all your data on all websites" warning. For a canvas tool. Nobody clicks allow on that.

Layer panel and minimapClick to enlarge

What Actually Worked

Simple static sites. Blogs, docs without strict CSP, basic marketing pages. Maybe 10-15% of what you'd actually want to research. And the thing is, the sites you need for deep research (dashboards, tools, apps) are exactly the ones with the strictest headers. So the broken path was the common path.

Thats a dead product.


What I Took From It

The idea was right. The surface was wrong.

Spatial canvas for thinking while you research is a real problem. 80 tabs is still a disaster. Context disappears when you close the browser. People wanted this. The response when it went viral was crazy.

But rendering third-party websites inside a canvas through a browser extension will always be a losing fight. Security policies are getting stricter not looser. The web is moving towards more isolation. I was literally trying to break web security to make my product work. Thats not a sustainable foundation.

The other realisation: I was solving the browsing problem but the actual problem is the thinking problem. I didnt want a better tab manager. I wanted to see how ideas connect. The websites were just the medium. The notes and connections were the real thing.

When I looked at how I actually used Vortex, the sticky notes I'd attach to nodes were more valuable than the rendered websites. The spatial arrangement of "this connects to that" was the insight. Not some live DOM rendering.

Sticky notes and color codingClick to enlarge


Porting It Into SideNotes

Taking all the good parts and putting them into SideNotes.

SideNotes is my desktop app. Electron, local first, Obsidian-style linking, no cloud, no account, no login. Already has the note graph and a block editor. What it needed was the spatial canvas.

SideNotes editorClick to enlarge

Brought the infinite canvas in as a first class view. Instead of embedding live websites (the thing that killed Vortex), nodes on the canvas are notes. You can drop a URL and it saves as a rich link card with title, favicon, OG image. But we're not rendering the site. The note is the artifact.

Same spatial mental model. No CSP. No Manifest V3. No Chrome Web Store. No proxy servers.

The Canvas

Built with React Flow. Drag notes from sidebar onto canvas, connect them, group them visually. Saves as .canvas JSON (Obsidian-compatible, so you can open same files in Obsidian if you want).

SideNotes canvasClick to enlarge

Grouping on the canvasClick to enlarge

Figma shortcuts came over. ⌘K to add, ⌘F to search, ⌘D to duplicate. Select multiple nodes, group them, collapse groups, colour code threads. All the spatial stuff that made Vortex feel good, just without the iframe hell.

The Rest of SideNotes

Not just the canvas. Block editor with slash commands, drag handles, code blocks with syntax highlighting. Connections graph (Sigma + WebGL) showing all wikilinks in the vault. Daily notes, mood tracking, tables, Mermaid diagrams, six themes in light and dark, PDF/HTML export. Plain markdown files on disk. No database, no sync, no account.

Connections graphClick to enlarge

Daily notesClick to enlarge


Vortex failed because I picked a surface that was fighting me from the start. The browser is a read-only window into other people's apps. You cant make it a canvas without fighting every security policy on the internet. And those policies exist for good reason na.

SideNotes is mine. Whole stack. No platform gatekeeping. Canvas works because I own every layer. Thats it. Dont build on a surface that doesn't want you there.

Vortex on GitHub / SideNotes on GitHub