What works

An honest rundown of what DemoTape handles, what it handles automatically, and where the edges are today.

Works out of the box

Multi-port apps

Frontend on 3000, API on 8001, auth service on 4000 — DemoTape detects all running ports and routes them through a single public URL. No reverse proxy config needed.

Quick sharing

Run demotape, get a link, share it. Your reviewer sees the live app. You can update code while they're using it.

Session replay

Full visual replay of the reviewer's session — every click, scroll, page transition, and DOM change. Powered by rrweb.

Network request capture

Failed fetch() and XMLHttpRequest calls (4xx, 5xx, network errors) are captured and shown in the session timeline. You see the URL, status code, and timing.

Console recording

All console output (log, info, warn, error, debug) is captured with timestamps. Stack traces from errors are included.

Cookie rewriting

Cookies with Domain=localhost are rewritten to work under the public tunnel URL. Other attributes (Path, Secure, HttpOnly, SameSite) are preserved. Your auth flow works without changes. See the cookie-session and auth-flow examples.

HTTPS

The public URL is always HTTPS. If your local server uses HTTPS (e.g., self-signed certs), DemoTape proxies to it correctly.

Location header rewriting

Redirect responses with Location headers pointing to localhost are rewritten to the public URL. Server-side redirects work as expected. See the location-rewrite example.

WebSocket proxying

WebSocket connections are proxied through the tunnel. Hot module reload (HMR), live updates, and real-time features work. See the realtime example.

Absolute URL rewriting

URLs like http://localhost:3000/api in HTML, JSON, and JavaScript responses are rewritten to the public tunnel URL. Client-side fetch(), XMLHttpRequest, WebSocket, and EventSource calls are intercepted and rewritten at runtime.

Response decompression

Gzip, Deflate, and Brotli responses are transparently decompressed for URL rewriting.

Viewer comments

Reviewers can leave timestamped comments through the overlay. Comments appear in your session replay at the exact moment they were written.

Framework support

DemoTape auto-detects these frameworks and their default ports:

FrameworkDetection
Next.js/_next/ marker, next.config.*
Vite/@vite/client marker, vite.config.*
Nuxt/_nuxt/ marker, nuxt.config.*
Create React App/sockjs-node marker
Astro/__astro marker, astro.config.*
SvelteKitSvelte markers, svelte.config.*
Angularangular.json
StorybookStorybook markers
RailsGemfile
Djangomanage.py
Laravelcomposer.json

Any HTTP server on a local port works — the framework detection just improves auto-selection. See working examples for Next.js, SvelteKit, Nuxt, and more.

Platform support

OSArchitecture
macOSIntel (x64), Apple Silicon (arm64)
Linuxx64, arm64
Windowsx64, arm64

Current limitations

These are things DemoTape doesn't handle yet or by design.

OAuth and fixed redirect URLs

OAuth flows that use a hardcoded redirect URL (e.g., http://localhost:3000/callback) won't work through the tunnel, because the provider redirects back to localhost instead of the public URL. You'll need to update the redirect URL in your OAuth provider settings to match the shared URL.

Cross-origin iframes

Session recording cannot capture content inside cross-origin iframes (e.g., embedded Stripe checkout, third-party widgets). The iframe appears in the replay but its contents are blank.

Event sampling

Mouse movements are sampled at 50ms intervals, scroll events at 150ms, and input events are deduplicated to the latest value. This is sufficient for replay but may miss very fast intermediate states.

Binary responses

URL rewriting only applies to text-like responses (HTML, JSON, JavaScript, XML, SVG). Binary responses (images, fonts, PDFs) are passed through unchanged.

Apps that check domain in code

If your app has server-side logic that checks req.hostname and rejects non-localhost requests, you'll need to adjust that check. The proxy sends x-forwarded-host with the public hostname.