Skip to main content
← All guides

Share a dev server with a client

Checked against the qURL™ CLI 3.4.1 source and documentation on October 9, 2026. Link and session behaviour is tested separately.

Content updated October 21, 2026. The verification date above records the original review; later behaviour checks are dated in the guide.

How do I let a client try my current local build without deploying it?

To let a client review your running Vite or Next.js app without deploying it, publish it with qURL and send the link from qurl share. ngrok and Cloudflare Quick Tunnels also connect a local app, through a URL that is public unless you add access rules; a Vercel preview deploys a build instead. Choose qURL for the live local build, and keep your computer and dev server running during the review.

What you need

  • A dev server running on this machine (Vite, Next.js, or similar)
  • The qURL CLI 3.4.1 or later
  • No account, API key, or sign-in

Steps

  1. Working in a coding agent? Paste the prompt instead

    In Claude Code, Cursor, Codex or another agent that can run commands, paste this in the project whose app is running. The agent installs the CLI, publishes the app privately and asks who should get in; the agent guides show each step. The steps below do the same by hand.

    Read https://layerv.ai/skills/qurl/SKILL.md and use qURL to share the app I'm running locally.
  2. Install the qURL CLI

    On macOS, install it with Homebrew. On Linux and Windows, download the package for your platform from the latest release; the CLI page lists each one. Nothing asks you to sign up.

    brew install layervai/tap/qurl
    qurl --version
  3. Vite: allow qurl.site hosts

    Requests reach the dev server with a Host header under qurl.site, and Vite 6.0.9, 5.4.12, 4.5.6 and later reject hosts they don’t know. Add .qurl.site to server.allowedHosts in your existing config. Vite restarts itself when a config file it loaded changes; restart it yourself if you just created one. Leave off --host: qURL reaches the dev server on localhost.

    // vite.config.js (merge into your existing config)
    export default {
      server: {
        allowedHosts: ['.qurl.site'],
      },
    }
  4. Next.js: allow qurl.site origins

    Next.js checks the Origin of requests to its dev resources and, for Server Actions, compares it with the host. Its docs say a tunnel needs *.qurl.site in allowedDevOrigins (Next.js 16.2 and later block without it) and, if you use Server Actions, in serverActions.allowedOrigins. next dev listens on every interface by default, so start it with next dev -H 127.0.0.1 to keep it off your network.

    // next.config.js
    module.exports = {
      allowedDevOrigins: ['*.qurl.site'],
      experimental: {
        serverActions: { allowedOrigins: ['*.qurl.site'] },
      },
    }
  5. Publish the address the dev server listens on

    For Next.js, publish http://localhost:3000. Vite prints http://localhost:5173/, but on some systems, such as macOS in our test, it listens only on IPv6, while qurl publish connects to localhost as 127.0.0.1. If publish reports that the app is not accepting TCP connections, publish http://[::1]:5173 instead, in quotes so zsh doesn’t read the brackets as a pattern.

    # Next.js (started with next dev -H 127.0.0.1)
    qurl publish http://localhost:3000
    # Vite
    qurl publish http://localhost:5173
    # Vite, if publish says it is not accepting TCP connections
    qurl publish 'http://[::1]:5173'
  6. Create a link with a longer session

    A review usually needs more than the default 1-hour session. The link itself still opens once and expires within 24 hours.

    qurl share <CRID> --session-duration 2h
  7. Send the link to one person

    Send it in a direct message, not a public channel: whoever opens it first uses it. Avoid email and apps that preview links, because a scanner that runs the page could use its one opening. Don’t open it yourself to check it, for the same reason. Run qurl share again whenever you need a fresh link.

  8. End the review

    When the review is over, stop serving the app with qurl stop. qurl start resumes it for the next round. qurl delete removes the resource for good after asking you to confirm, and its CRID can never be shared again.

    qurl stop <CRID>
    qurl delete <CRID>

What the recipient sees

Your client opens the link and lands on the app at an address like https://r_….qurl.site/, with no warning page, sign-up or install, and sees it as you do. In our tests through a qURL link with Vite 6, Vite 8.3.4 and Next.js 16.4.2, the hot reload socket connected and an edit to the source appeared in the browser opening the qURL link without a manual refresh.

Which option fits a client review?

OptionChoose it whenTrade-off
qURLqURL fits when the client should see your current local build, including changes you make during the review, with no deploy and no public URL.With qURL the review works only while your computer and dev server run, and each qurl share link opens once.
Vercel preview deploymentA Vercel preview deployment fits when the client reviews on their own schedule: the deployed build stays online after you close your laptop.A Vercel preview shows a pushed branch or commit, not uncommitted work. New Vercel projects enable deployment protection by default; check the project’s access settings before sharing. The Vercel CLI asks you to log in.
ngrokngrok fits when you want the same URL for every review session; its traffic policies can put OAuth or IP rules in front of the app.ngrok needs an account and authtoken, the URL is public unless a policy restricts it, and free-plan clients see a browser warning page first.
Cloudflare Quick TunnelsA Cloudflare Quick Tunnel fits a quick look with no account. With --allowed-mail, the client enters a one-time PIN sent to their email, and needs no Cloudflare account.A Cloudflare Quick Tunnel gets a new hostname each run, is public without --allowed-mail, and does not support Server-Sent Events.

Troubleshooting

If you seeDo this
The page says “Blocked request. This host … is not allowed.”Vite’s host check rejected the request. Add .qurl.site to server.allowedHosts in vite.config.js and restart Vite; a config file created after Vite started is not picked up until it restarts.
next dev logs “Blocked cross-origin request to Next.js dev resource”, or hot reload never connectsAdd *.qurl.site to allowedDevOrigins in next.config.js and restart next dev.
Server Actions fail with “Invalid Server Actions request”The browser’s origin (r_….qurl.site) differs from the host your app receives (c-….qurl.site). Add *.qurl.site to experimental.serverActions.allowedOrigins.
qurl publish says the local app is not accepting TCP connectionsStart the app first and check that curl works on the same address. qurl publish connects to localhost as 127.0.0.1, so if your app listens only on IPv6 (on macOS or Linux, lsof -iTCP -sTCP:LISTEN -nP shows [::1]), publish 'http://[::1]:PORT' instead. Keep the quotes: zsh treats the brackets as a pattern.
The recipient sees “Access link invalid”The link was already used or has expired. Run qurl share again and send the new link.
The recipient sees “Resource not found”The resource was deleted after the link was made. Publish the app again, then run qurl share and send the new link.
publish rejects http://127.0.0.1 with “only HTTPS URLs are allowed”, or asks you to log inYou have a CLI older than 3.0. On macOS run brew update, then brew upgrade qurl; elsewhere install the latest release again. After updating, qurl --version should print 3.4.1 or later.
publish prints no Access: line, or the Access: line says public and you did not ask for publicWith no Access: line, the CLI is older than 3.4.1: on macOS run brew update, then brew upgrade qurl; elsewhere install the latest release again. A resource that an older CLI published is public unless you published it with --private, and anyone who has the CRID of a public resource can open it. To make a public resource private, run qurl delete <CRID> and publish again with qurl 3.4.1 or later. The new resource is private and has a new CRID.
publish says this Linux session “can’t reach a systemd user manager”You are in a container or sandbox without a user service manager. Run qurl publish with --foreground; sharing lasts as long as that process runs.
publish says “Quota Exceeded” with “protected resource limit reached”, or “Your qURL account has reached a plan limit”You can see this without an account: a device with no account can keep up to 3 active resources, with links that last up to 24 hours. Run qurl list --status active, then qurl delete <CRID> for any you no longer need (it asks you to confirm; --yes skips that). qurl stop keeps the resource, so it does not free a slot.

Frequently Asked Questions

Should I send a Vercel preview instead?

Send a Vercel preview deployment when the client reviews on their own time or over several days: it is a deployed build that stays online with your laptop closed. Share the local app with qURL when they should see the build you are working on now, including edits made during the review. New Vercel projects enable deployment protection by default. Check the project’s access settings before sharing; Vercel Authentication is available on the Hobby plan.

Can a Cloudflare Quick Tunnel limit who opens the review?

Yes. cloudflared tunnel --url http://localhost:5173 --allowed-mail client@example.com asks each visitor for a one-time PIN sent to that address, and the visitor needs no Cloudflare account. Changing the allowed addresses means restarting cloudflared, which gives the tunnel a new hostname, and Quick Tunnels do not support Server-Sent Events.

Does hot reload work through qURL?

Yes, once the dev server accepts qURL’s hostnames. WebSocket upgrades and Server-Sent Events pass through a qURL link. On October 18, 2026, Vite 8.3.4 with .qurl.site in server.allowedHosts and Next.js 16.4.2 with *.qurl.site in allowedDevOrigins both applied source edits in the browser opening the qURL link without a reload; without those settings, Vite showed “Blocked request” and Next.js blocked its hot reload socket.

Why does Vite block the request?

Vite only allows localhost, .localhost subdomains, and IP addresses as the Host header by default. qURL requests arrive with a qurl.site host, so add .qurl.site to server.allowedHosts.

Is it safe to share a dev server?

Safer than binding it to every interface or putting it on a public tunnel URL, because the app has no public route and each link works once. But whoever opens the link reaches the dev server itself, and dev servers are not hardened for hostile traffic: Vite CVE-2025-31125, listed in CISA’s Known Exploited Vulnerabilities catalog, let clients that could reach a dev server read files it should refuse (fixed in Vite 6.2.4, 6.1.3, 6.0.13, 5.4.16 and 4.5.11). Keep the dev server updated, share with people you trust, and stop sharing when the review is done.

Who else can reach my app while the link is open?

Opening the link admits the network address it was opened from for the session, which lasts 1 hour by default. Other devices that share that public IP address, such as people on the same office or café network or VPN, can reach the app until the session ends. By default a link admits whoever opens it; access rules set through the API, such as IP allow and deny lists, can restrict that. Keep your app’s own sign-in for anything sensitive.

How do I stop sharing?

Run qurl stop <CRID> to pause serving the app, and qurl start <CRID> to resume it; a stopped app still counts toward your resource limit. qurl delete <CRID> removes the resource for good after asking you to confirm; its CRID can never be shared again.

Publish your app now

Install the CLI, then run one command. No sign-up, no API key.

Install the CLI ↗

Contact sales

Contact our team for enterprise deployments.

Enterprise starts with a scoped, paid pilot on one application, typically 60 to 90 days, credited in full toward year one if you convert within 60 days. Then an annual package sized to what you protect. Not per seat.