Back to blog

April 13, 2026

Sharing a Local App Shouldn't Require DevOps

Why showing a local multi-service app to one person should not require staging environments, tunnel hacks, or deployment work.

Sharing a Local App Shouldn't Require DevOps

You've got something working. Frontend talks to the API, the API talks to the database, auth flows through correctly, the whole thing runs beautifully on your machine.

Now someone needs to see it.

And suddenly you're not a developer anymore. You're a sysadmin trying to deploy a production environment for an audience of one.


The Gap

There's a strange void in the developer toolchain. We have incredible tools for building locally and incredible tools for deploying to production. But the space in between — "let someone else use this thing that runs on my laptop" — is somehow still a mess.

The common options:

Deploy it. Spin up a staging environment. Set up CI. Configure DNS. Wait 20 minutes. Realize the environment variables are wrong. Fix them. Redeploy. Wait again. All so your client can look at it for 90 seconds and say "looks great."

Screen share. Jump on a Zoom. Share your screen. Navigate the app yourself while someone watches. They see your cursor, your flow, your assumptions. They never touch anything. You learn nothing.

Tunnel it. Open ngrok, point it at port 3000, send the URL. Simple — until it isn't.


The ngrok Problem

Single-port tunneling tools work fine when your entire app is one process on one port. A static site. A simple API. A toy project.

Real apps aren't one port. You've got a frontend on 3000, an API on 8080, maybe a second service on 5000. You're running a database, a queue, a websocket server. The whole thing is held together by relative paths, shared cookies, and the quiet assumption that everything lives on the same origin.

Tunnel one port and the rest falls apart.

The frontend can't reach the API because it's calling /api/... and the tunnel only knows about the frontend. Cookies set by one service don't apply to another because they're suddenly on different domains. CORS headers are wrong because the origin changed. HTTPS works on the tunneled port but not on the others, so mixed-content rules block half your requests.

You can hack around this. Run multiple tunnels. Rewrite your environment variables. Hardcode the tunnel URLs into your config. Spend an hour turning your local dev setup into a fragile mess that breaks the moment a tunnel URL rotates.

Or you could just… not do any of that.


What It Should Look Like

The workflow should be: run the app, share a URL, done.

No deploying. No rewriting config. No coordinating multiple tunnels. No explaining to your tester which URL is which. One link that works like your app works locally — same routing, same cookies, same HTTPS behavior across every service.

That's what DemoTape does. It detects your running ports, routes them behind a single URL, and handles the cookie rewriting, header injection, and HTTPS consistency automatically. You run npx @demotape.dev/cli, send the link, and the person on the other end gets your full app — not a broken slice of it.

No infrastructure. No staging environment. No "wait, let me fix the tunnel."


The Multi-Service Reality

This isn't an edge case. Most modern apps are multi-service by default.

A Next.js app with API routes? That's a frontend and a backend on the same port, but add an external API or a microservice and you're multi-port immediately. A React frontend with an Express API? Two ports, minimum. Docker Compose setups? Three, four, five services, each on their own port, each expecting to talk to the others.

Single-port tunneling was designed for a simpler era. The tools haven't caught up to how we actually build things.

Every developer has lost time to this. You just want to show someone your work, and instead you're debugging CORS policies and cookie domains at 10pm because a tunnel rotated its URL.


The Hidden Cost

The real damage isn't the time you waste setting things up. It's the demos you don't do.

Every friction point between "it works locally" and "someone else can see it" is a reason to postpone sharing. To wait until it's deployed. To wait until staging is set up. To wait until it's "ready."

Meanwhile, you're building in the dark. No feedback. No reality check. No one catching the UX problem that's obvious to everyone except you.

The best time to share is when it's still rough — when changing things is cheap and feedback actually shapes the product. But if sharing requires 30 minutes of DevOps every time, you'll find reasons not to.


It's a Solved Problem (Now)

Local development is a solved problem. Deployment is a solved problem. The five minutes of sharing in between shouldn't be the part that requires a tutorial.

Run your app. Share a link. Let someone use it. That's the whole workflow.

npx @demotape.dev/cli — one command, all your ports, one shareable URL.

Stop deploying staging environments for an audience of one.