1
Click to send
0
Cloud roundtrips
localhost
Where the bridge lives

The copy-paste shuttle

Open a gallery page on a file host. You see twelve links you want. Right-click the first, copy, switch to the download manager, paste. Back to the browser. Right-click the second, copy, switch, paste. On the seventh link you lose your place, and you're never really sure whether you grabbed everything.

I resent browser extensions on principle, which made this a hard call. But the copy-paste shuttle was the single biggest complaint in my inbox, so I held my nose and built one. The Veloxar Companion extension makes that shuttle one click. It just landed, and this post is about the architecture behind a feature that looks, from the outside, like it could not possibly need any.

Local bridge, not cloud bounce

The obvious way to build a browser-to-app bridge in 2026 is to punt: ship the URL up to a cloud service, poll for it from the desktop app, done. It works, and it's wrong for this problem.

Your browser and your download manager are on the same laptop, inches apart in silicon. Routing a URL through a datacenter in another state so the app can pull it back adds latency, a failure mode, and a dependency on whether somebody remembered to pay the AWS bill. A cloud bridge also means every link you send passes through somebody else's database. Even if that somebody is us. Especially if that somebody is us. The best way to not leak a list is to never have it.

And if Veloxar's servers ever go down, your download manager should not notice. With a cloud bridge it would notice instantly -- a local problem becomes everybody's problem.

So we didn't. The extension talks to the desktop app over plain HTTP on localhost. The desktop app opens a NWListener on port 9999 and serves a small JSON API. The extension's fetch call never leaves the machine.

If your browser and your app are on the same machine, routing their conversation through a datacenter is cosplay. A localhost request completes in under a millisecond, costs nothing to operate, and cannot be knocked offline by an outage on a continent you aren't on.

What the extension actually asks for

People are right to be suspicious of extensions. An extension is a piece of code with a microphone held up to your browser, and the fix for that is specificity, not reassurance. So here's the entire permissions block of manifest.json, with a line about why each one is there.

activeTab. When you click the toolbar icon, the extension gets permission to read the tab you just clicked from, and only that tab. It doesn't follow you around the rest of your browsing. It's the most user-respecting permission Chrome offers and I leaned on it hard.

scripting. Required to inject the media scanner -- src/lib/media-detect.js -- into the active tab when you ask the popup to find downloads. The scanner walks the DOM for <video>, <audio>, and <source> tags, and probes known players (JWPlayer, Plyr, videojs) for their current source. It runs once, on demand, and returns a list.

contextMenus. Adds the "Download with Veloxar" right-click item on links, videos, and images, plus a "Send page to Veloxar" item for the page itself.

storage. Saves two things: the port the desktop app is on, and the API key returned from pairing. Nothing else.

Host permissions are restricted to http://localhost/* and http://127.0.0.1/*. That's it. The extension isn't allowed to talk to any remote host. It cannot exfiltrate your browsing data, because its outbound fetch only knows how to reach 127.0.0.1. The browser enforces that, not me promising nicely.

The discovery handshake

When the extension starts, it doesn't know whether Veloxar is running. A bad extension would guess and fail silently. A worse one would spin on a timer and burn battery. This one probes a single endpoint and updates a status dot.

The popup's VeloxarAPI.ping() fires a GET to /api/status on the configured port. If the response comes back with success: true, the dot goes green and the tabs light up. If the fetch rejects with Failed to fetch because nothing's listening, the dot goes red and the Capture tab shows a clear "open Veloxar to continue" state instead of pretending to work.

Pairing is a second step. The extension posts to /api/pair, the app returns an API key (if auth is enabled), and the extension tucks it into chrome.storage.local. The trust model is local: if you can reach the Veloxar process on localhost, you're already sitting at the machine. I'm defending against other local processes, not remote attackers, because there aren't any to defend against.

The Remote API, in seven endpoints

RemoteAPIServer.swift routes seven prefix groups. The full handler list is in Sources/Features/RemoteAPI/RemoteAPIServer.swift if you want to read the code:

"Send a link" is deliberately the smallest operation I could get away with. No rich metadata, no per-URL options, no package grouping. Just an array of strings:

POST http://localhost:9999/api/linkcollector
Content-Type: application/json
Authorization: Bearer <api-key>

[
  "https://example.com/video/abc123",
  "https://example.com/video/def456"
]

The link collector picks up the URLs, runs them through the crawler pipeline, and the normal Veloxar plumbing takes over. The extension doesn't know or care which plugin will handle the link. It hands off and walks away.

Why popup, not content script

An extension has two places it can run code on a page: a popup (when the user clicks the toolbar icon) or a content script (injected on every page load). They look similar. They are not. A content script runs whether you asked for it or not, on every page the manifest matches, forever. A popup runs when you click it.

Veloxar's content_scripts array is empty. On purpose. The media scanner lives in the popup flow: you click the icon, background.js receives a scan-tab message, and it uses chrome.scripting.executeScript to inject media-detect.js into the current tab exactly once. The scanner runs, returns its list, and that's the entire lifetime of the injection.

The trade-off is that we don't see media until you ask. An autoscanning content script could pre-warm the list, but it would also be watching you across every site you visit, including the ones where you'd rather it didn't. I picked the conservative side. The popup finishes scanning before you can read the page title; nobody has complained about the latency.

Firefox, honestly

Manifest v3 is cross-browser in theory. In practice, Firefox's v3 implementation has enough quirks around service workers and host_permissions that I haven't shipped a Firefox build yet. The Chromium build (Chrome, Edge, Brave, Arc, Vivaldi) works today. A Firefox port is on the list, not in the bag. I'm not going to pretend the checkbox is ticked until it actually is.

From page to queue

You're on a page with a dozen links you want. You click the Veloxar icon. The popup shows what it found. You hit "Send all to Veloxar." The dot stays green, the popup closes, and the desktop queue grows by twelve items before you've switched windows.

That's the whole feature. What's interesting is what isn't there: no cloud roundtrip, no sign-in, no sync service, no background page scanning, no outbound traffic leaving your machine. One click, one local POST, one growing queue. The boring solution turned out to be the right one.