Skip to content
Guides · Recipes

How Do I Run a Next.js Dev Server With a Live Preview URL?

Updated October 27, 2026 .md

Short answer: Run next dev on port 3000 in the sandbox and host the port with sbx host. The page loads right away, but hot reload stays broken until you add "*.box.sandboxer.com" to allowedDevOrigins in next.config.ts and restart. Then edits made in the sandbox show up in the browser in under a second.

This page is about the Next.js dev server only. For how hosted URLs, tokens and cookies work in general, see Give a sandbox port an HTTPS URL. For built previews of each pull request, see Get a preview URL for every pull request.

At a glance#

Symptom on the hosted URL Cause Fix
Page loads, but edits never show up until you reload Next.js blocks its HMR WebSocket from origins it doesn't know allowedDevOrigins: ["*.box.sandboxer.com"], then restart next dev
Browser console: WebSocket connection to 'wss://…/_next/hmr?id=…' failed every few seconds Same Same
Server log: ⚠ Blocked cross-origin request to Next.js dev resource /_next/hmr Same Same
502 Nothing is answering on port 3000 Dev server isn't running Check the service and its log
URL works, then stops after the sandbox boots from disk Dev server was a one-off process Run it as an enabled systemd unit

Everything below was run on a small sandbox (2 vCPU, 4 GB) on 2026-10-27 with Next.js 16.4.3 and Turbopack. We drove a real headless Chromium against the hosted URL to watch the HMR socket. Tokens are replaced with <token>.

1. Create the app#

sbx new --name next-dev --type small
id=sb_t0uixywwik    # the id sbx new printed
sbx exec $id --timeout 600 "npx --yes create-next-app@latest web --yes"
Success! Created web at /home/user/web

This took 37 seconds, including the npm install. The sandbox has Node 22 and npm preinstalled. sbx exec stops a command after 30 seconds by default, so pass --timeout for installs. The flags go before the command.

2. Allow the hosted origin#

Next.js blocks cross-origin requests to dev-only resources by default. It allows localhost and the hostname it was started with. Your browser's origin is https://<subdomain>-3000.box.sandboxer.com, so that is blocked until you list it. Add one line to next.config.ts:

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  allowedDevOrigins: ["*.box.sandboxer.com"],
  // …the rest of your config
};

export default nextConfig;

Next.js matches only the hostname, and * stands for exactly one label. Every hosted port's hostname has one label in front of box.sandboxer.com (lucky-smart-magpie-3000), so this single entry covers any sandbox and any port. It also covers forks, which get a new subdomain. If you'd rather allow just one URL, the server log prints the exact hostname to paste in (step 5). The config is read only at startup: restart next dev after you change it.

3. Run next dev as a service#

next dev listens on 0.0.0.0 by default (CLI docs), so you don't need --localhost on the hosted port. Run it as a systemd unit, not a detached command, so it starts again if the sandbox ever boots from disk:

sbx exec $id "sudo tee /etc/systemd/system/next-dev.service >/dev/null <<UNIT
[Unit]
Description=Next.js dev server
After=network-online.target

[Service]
User=user
WorkingDirectory=/home/user/web
ExecStart=/usr/bin/npm run dev -- --port 3000
Restart=always
Environment=NEXT_TELEMETRY_DISABLED=1
StandardOutput=append:/home/user/next-dev.log
StandardError=append:/home/user/next-dev.log

[Install]
WantedBy=multi-user.target
UNIT
sudo systemctl daemon-reload && sudo systemctl enable --now next-dev && sleep 4 && cat next-dev.log"
▲ Next.js 16.4.3 (Turbopack)
- Local:         http://localhost:3000
- Network:       http://10.202.0.82:3000
✓ Ready in 501ms

We send output to a file so tail -f next-dev.log works as your dev console. In sandboxes created on October 27, 2026, a plain journalctl -u next-dev showed no entries; sudo journalctl -m -u next-dev shows them.

4. Host port 3000#

sbx host $id 3000 --title "Next dev"
https://lucky-smart-magpie-3000.box.sandboxer.com?_token=<token>

The URL is private: without the token it answered 401; with it, 302 and a cookie. The first page load after a (re)start compiled the route and took 3.0 seconds. The next load took 0.34 seconds.

Open the token link in your browser. The cookie it sets also covers the HMR WebSocket, so there is nothing extra to do for a private URL. Scripts that connect without a browser need to trade the token for the cookie first, as shown here.

5. What happens without allowedDevOrigins#

We ran the same app first without step 2. The page rendered (200), so everything looked fine. But the browser's HMR socket never opened:

10:23:24.927 ws open /_next/hmr
10:23:25.156 console error WebSocket connection to 'wss://lucky-smart-magpie-3000.box.sandboxer.com/_next/hmr?id=…' failed: Error during WebSocket …
10:23:25.156 ws close /_next/hmr
…              (the client retried every 1 to 5 seconds)

The server logged why:

⚠ Blocked cross-origin request to Next.js dev resource /_next/hmr from "lucky-smart-magpie-3000.box.sandboxer.com".
To allow this host in development, add it to "allowedDevOrigins" in next.config.js and restart the dev server:

We then edited the heading in app/page.tsx in the sandbox. Next.js recompiled (✓ Compiled in 218ms), but the open page kept the old text for the remaining 20 seconds of the test. Only a manual reload would have shown the change. A dev-asset request that carries an Origin header also got 403, while plain script loads got 200. That is why the page renders but live updates fail.

6. Hot reload over the hosted URL#

With allowedDevOrigins set and the server restarted, we loaded the page and then ran one edit from our laptop:

sbx exec $id "sed -i 's/To get started, edit the/Edit one, from the sandbox:/' web/app/page.tsx"

What the browser saw:

10:24:14.361 console log [HMR] connected
10:24:14.362 ws frame turbopack-connected
10:24:14.805 loaded, h1 = "To get started, edit the page.tsx file."
10:24:25.288 (sbx exec returned)
10:24:25.357 ws frame serverComponentChanges
10:24:25.643 ws frame built
10:24:25.664 h1 changed to "Edit one, from the sandbox: page.tsx file."

The heading changed 0.38 seconds after the edit command returned, with no reload from us. This loop is what you want when a coding agent edits files in the sandbox and you watch the result in your browser.

Stop, resume and memory#

Check Result
sbx stop $id --wait 2.2 s; the URL answered 404 while stopped
sbx resume $id 1.3 s, memoryRestored: true
First request after resume, old cookie 200 in 0.26 s: the same dev server, already warm
HMR after resume [HMR] connected; the next edit showed up live
Memory on small next-server used about 435 MB; the sandbox used 768 MB of 3,914 MB

Routes, tokens and browser cookies survive a stop. If a resume can't restore memory (memoryRestored: false, for example on a different CPU type), the sandbox boots from disk. The enabled unit then starts next dev again and the first page load compiles once more. We did not hit that case in this test.

FAQ#

Do I need --localhost when I host the port?#

No. next dev binds 0.0.0.0 by default and logs a Network: address. Use --localhost only if you started it with -H 127.0.0.1.

Can I put the full URL in allowedDevOrigins?#

No. Next.js matches only the hostname, so leave out https://, the port and the ?_token=. Never commit a token to next.config.ts.

Does this affect next build and next start?#

No. allowedDevOrigins applies only in development. A production server has no HMR socket. For built previews, see Get a preview URL for every pull request.

Why is the first page load slow?#

next dev compiles each route on its first request. In our test that took 3.0 seconds on a small sandbox, and later loads took about 0.3 seconds. After a restart, or a resume that boots from disk, the first load compiles again.

Can I share the preview with a teammate?#

Yes. Send the private token link. It works in their browser, HMR included, because the cookie covers the WebSocket. Switching the port to --public and back mints a new token, which cuts off old links.

More guides

Top AI sandbox platforms for code execution in 2026, ranked

For running AI-written code we rank Sandboxer, Freestyle and E2B first: each gives code its own VM with an API or SDK and can pause with memory. Pick Daytona for Windows or GPUs, Modal or Northflank for GPUs at scale, E2B or Northflank to run in your own cloud, and Vercel Sandbox if your app lives on Vercel.

Read the guide
Best sandboxes for running coding agents (Claude Code, Codex, Gemini CLI) in 2026, ranked

For coding agents we rank Sandboxer first: a full Ubuntu VM with Claude Code and Codex preinstalled, Docker, and stop-and-resume that keeps the agent's session in memory. Freestyle and Amp Orbs also keep memory across pauses. Pick E2B for prebuilt agent templates on open source, Docker Sandboxes for free local runs, and Codespaces if you live in GitHub.

Read the guide
Best Daytona sandbox alternatives in 2026, ranked

The best Daytona alternatives depend on why you're switching. For a full Linux microVM on every sandbox with memory-saving stop and Docker, we rank Sandboxer first. E2B suits open source and self-hosting, Modal massive short-job fleets, Northflank bring-your-own-cloud with GPUs, and Vercel Sandbox apps on Vercel.

Read the guide
Best E2B alternatives in 2026, ranked

If you're leaving E2B for longer sessions or a fuller machine, we rank Sandboxer first, then Freestyle: both give each sandbox a full Linux VM that keeps memory across pauses, with Docker and no short session cap. Pick Daytona for Windows or GPUs, Northflank for bring-your-own-cloud, and stay on E2B if you need open source.

Read the guide