Firefox 153 added Local Mode to DevTools: it maps a folder on your disk to an https:// origin. You don't run npx serve or python -m http.server, and you don't touch mkcert. Open DevTools, point it at a folder, and https://shop.localhost/index.html loads straight from ~/code/shop.
The official docs pitch it in one line: "This prevents having to spawn a HTTP server to test a web page." I spent a while trying to poke holes in it. My take is that the docs oversell the HTTPS part, which localhost already gave you, and undersell per-project origins, which fix something that annoys me every day. Below is the setup, plus the limits that will send you back to Vite.
What Firefox Local Mode actually does
You register mappings. Each one has two fields:
-
Origin: a hostname Firefox serves over
https://, e.g.firefox.localhost -
Local folder: the directory the files come from, e.g.
/home/alex/app
After that, https://firefox.localhost/ loads /home/alex/app/index.html and gets a proper origin instead of null or file://, with the scheme, host and storage partition the rest of the web platform expects.
The docs list two goals. One is to "test all Web APIs, including the ones being restricted to Secure Contexts (i.e. using https)". The other is "having many distinct origins (domain) for each experiment / project" with "dedicated storage/cookies for each." The second one is the reason I'd keep using it.
How to set up Local Mode (three ways)
1. The DevTools Options panel
Open DevTools (F12) and go to the Options panel (the ⋯ menu, then Settings). Add a mapping with an origin and a folder, and add as many more as you need. This is the setup for projects you come back to.
2. The file:// notification bar
Drag an HTML file into Firefox, or open any file:// URL, with DevTools open. A notification bar appears at the top of DevTools with two buttons:
- Add To Settings opens the Options panel with a permanent mapping for that file's location already filled in.
- Try it creates a transient mapping for the current file or folder. It disappears when you close DevTools or Firefox.
"Try it" is what I'd use for a one-off: someone sends you a zip containing a demo, you unzip it, open index.html, click once, and you're on https.
3. about:config, for teams and dotfiles
Each mapping is stored as three prefs, where N is an incrementing integer:
devtools.local-mode.mappings.N.origin = "shop.localhost"
devtools.local-mode.mappings.N.path = "/home/alex/code/shop"
devtools.local-mode.mappings.N.disabled = false (optional)
Since they're ordinary prefs, you can put them in a profile's user.js and commit that to your dotfiles or an onboarding repo:
user_pref("devtools.local-mode.mappings.0.origin", "shop.localhost");
user_pref("devtools.local-mode.mappings.0.path", "/home/alex/code/shop");
user_pref("devtools.local-mode.mappings.1.origin", "admin.localhost");
user_pref("devtools.local-mode.mappings.1.path", "/home/alex/code/admin");
On Lobsters, kevincox already sets Firefox prefs through Nix and half-jokingly suggested deploying static sites straight into the Firefox config. The docs say the prefs exist "so that you can easily import and transfer them between profiles, or via automation." Paths are absolute, so a shared file only works if everyone keeps their checkouts in the same location.
Do you even need HTTPS on localhost? Usually not
The headline feature is "test HTTPS-only APIs without a server," and I don't fully buy it.
http://localhost is already a secure context. MDN's Secure Contexts page lists localhost, *.localhost, 127.0.0.0/8 and ::1 as potentially trustworthy, and it lists the file scheme as well. crypto.subtle and the async clipboard API already work on npx serve at localhost:3000. On Lobsters, majaha checked and found that window.isSecureContext is true on file:// in Firefox.
So if you're on one machine and already running a server, Local Mode doesn't unlock anything you didn't have.
It's more useful in the situation the feature is named for, where you skip the server entirely. A file loaded from disk can technically count as secure and still be unusable:
- Service workers don't register from
file://. The Service Worker spec rejects any script URL whose scheme isn'thttporhttps. Local Mode gives youhttps, so registration works. - The bigger issue is the origin. Firefox has treated local files as their own origins since the CVE-2019-11730 fix in Firefox 68, because the previous behaviour let a downloaded HTML file read its neighbours. That fix is why
fetch('./data.json')from afile://page breaks. With a mapped origin, everything in the folder shares one origin.
So Local Mode is a good fix for "open a folder and have it behave like a website," and mostly irrelevant for testing secure-context APIs, where the localhost server you already run was fine.
Per-project origins are the part worth keeping
Everybody's localhost:3000 holds leftovers from six projects. There's an auth token from last week's prototype still in localStorage and a service worker registered by some other app still intercepting requests. Somewhere in there is a cookie named session that belongs to who knows what.
They collide because the origin is http://localhost:3000 whichever project happens to be on that port. Each Local Mode mapping gets its own hostname, so shop.localhost and admin.localhost have separate storage, cookies and service worker registrations. You don't have to clear site data before switching projects, and you don't get a stale SW from another repo serving a cached index.html.
You can get the same result with a server by giving each project its own port or a *.localhost hostname in Vite. In practice almost nobody does.
Where it falls short
First, it only works while DevTools is open. The docs say so directly: "These mappings are only functional when DevTools are opened." Close the toolbox and https://shop.localhost stops resolving. For debugging that's fine. As a general way to keep a local site around, it's annoying.
Only Firefox can use it. The docs present this as a security property: no other program on your machine or network can reach the mappings. That also means no curl, no Playwright running in Chromium, and no testing from your phone. In the thread, pocket_walrus and Pomax both said they'd reach for Caddy when they need local HTTPS, and for anything beyond one browser on one machine that's still my answer too.
It also just serves files. The docs say nothing about custom response headers, SPA fallback rewrites or live reload. If your app needs Cross-Origin-Opener-Policy for SharedArrayBuffer, or /dashboard has to fall back to index.html, you need a server.
And early reports are mixed. On Lobsters, kiwec hit "failed to load" errors and a security error with the default firefox.localhost name, then went back to cloudflared tunnel. BD103 had it working for a handful of PNGs. I'd treat it as a v1 feature for now.
Local Mode vs npx serve vs Vite vs Caddy
| You want to... | Local Mode |
npx serve / python -m http.server
|
Vite | Caddy / mkcert |
|---|---|---|---|---|
| Open a static folder on https, no process | Yes | No | No | No |
| Isolate storage per project | Yes, one origin each | Only via separate ports | Configurable | Configurable |
| Register a service worker | Yes | Yes (on localhost) | Yes | Yes |
| Use TypeScript, JSX, bare imports | No | No | Yes | No |
| HMR / live reload | No | No | Yes | No |
| Custom headers (COOP/COEP) | Not documented |
serve via serve.json; http.server no |
Yes | Yes |
| Reach it from a phone or another browser | No | LAN, http unless you pass serve --ssl-cert
|
LAN, http by default | Yes, once the device trusts the CA |
| Works with DevTools closed | No | Yes | Yes | Yes |
My rule after reading through all this: if the project has a build step, Local Mode isn't for it. Keep Vite. If it's a static folder (a demo, a bug repro, a vanilla JS prototype, a PWA spike, a generated docs site), stop starting a server for it. Map the folder once with "Add To Settings" and be done.
The case I'd use it for most is bug reproductions. Someone files an issue with a zip, and instead of cd, npx serve, and "wait, port 3000 is taken," you open index.html, click Try it, and you have an https origin that won't touch anything else in your browser.
Try it today
- Update to Firefox 153 or later (153 shipped July 21, 2026).
- Open any local
index.htmlwith DevTools open. - Click Try it in the notification bar.
- Put an empty
sw.jsnext to it, then runisSecureContextandnavigator.serviceWorker.register('./sw.js')in the console. - If it holds up, click Add To Settings and choose a
*.localhostname per project.
How do you test HTTPS-only APIs locally right now: mkcert, Caddy, a tunnel, or push to staging and hope? And is "DevTools must stay open" a dealbreaker for you, or a fair price for never typing npx serve again?
Top comments (0)