On Runtime, each agent's app gets its own microVM and a private HTTPS address in one call. The app never runs on your servers. The address needs a token unless you make it public. Hot reload works because previews support WebSockets. The sandbox has Node.js 24.21.0. Next.js 16.4.3, the current version on 25 October 2026, needs Node.js 20.9 or later.
Run the agent's app
Upload what the agent wrote, or scaffold a fresh project. Then start the dev server and share it:
TypeScriptimport { Sandbox } from "withruntime";const nextConfig = `import type { NextConfig } from "next";const nextConfig: NextConfig = { allowedDevOrigins: ["*.runtimehost.com"] };export default nextConfig;`;const sbx = await Sandbox.create({ timeoutSeconds: 3600 }); // keeps running after this script endsawait sbx.exec("npx create-next-app@16.4.3 site --yes --use-npm --disable-git", { check: true, timeoutMs: 600_000, env: { NEXT_TELEMETRY_DISABLED: "1" },});await sbx.files.write("/workspace/site/next.config.ts", nextConfig);await sbx.spawn("npx next dev -p 3000", { cwd: "/workspace/site", env: { NEXT_TELEMETRY_DISABLED: "1" },});await sbx.exec("npx wait-on@9.1.0 http://127.0.0.1:3000", { check: true, timeoutMs: 180_000 });const preview = await sbx.previews.create(3000);console.log(preview.urlWithToken); // a link that carries its tokenPythonfrom withruntime import SandboxNEXT_CONFIG = """import type { NextConfig } from "next";const nextConfig: NextConfig = { allowedDevOrigins: ["*.runtimehost.com"] };export default nextConfig;"""sbx = Sandbox.create(timeout_seconds=3600)sbx.exec("npx create-next-app@16.4.3 site --yes --use-npm --disable-git", check=True, timeout_ms=600_000, env={"NEXT_TELEMETRY_DISABLED": "1"})sbx.files.write("/workspace/site/next.config.ts", NEXT_CONFIG)sbx.spawn("npx next dev -p 3000", cwd="/workspace/site", env={"NEXT_TELEMETRY_DISABLED": "1"})sbx.exec("npx wait-on@9.1.0 http://127.0.0.1:3000", check=True, timeout_ms=180_000)print(sbx.previews.create(3000)["urlWithToken"])For a project the agent already wrote, replace the scaffold with
sbx.files.upload("./site", "/workspace/site") and npm ci. Upload the source
without its node_modules. Packages installed on a Mac carry native binaries
built for the wrong system.
Why allowedDevOrigins matters
In development, Next.js blocks requests for dev-only assets and endpoints. It
blocks them when they come from an origin other than localhost, its
subdomains, or the hostname the server started with. A preview's hostname is a
name under runtimehost.com. Without an entry, the page loads, but the dev
assets it requests are refused with 403. The dev server logs "Blocked
cross-origin request to Next.js dev resource". Hot reload then never connects.
| Setting | Effect |
|---|---|
| No entry | Next.js blocks the preview's requests for dev assets |
allowedDevOrigins: ["*.runtimehost.com"] |
Every preview address works; * covers one label, which is all a preview uses |
next start (production) |
No dev endpoints, so the setting does not apply |
Next.js matches only the hostname of the request's Origin. Write the entry
without https:// and without a port.
Dev server or production build
| Question | next dev |
next build then next start |
|---|---|---|
| Does an edit show immediately? | Yes, over hot reload | No; rebuild first |
| Does it match what users would get? | Close, but compiled on request | Yes |
| Who should open it? | The person watching the agent work | A reviewer, a client, a demo |
| Preview visibility | Private, with its token link | Private, or public when paid |
To share the finished app:
TypeScriptimport { Sandbox } from "withruntime";const sbx = await Sandbox.connect(process.env.SANDBOX_ID ?? "");const build = await sbx.exec("cd site && npx next build", { timeoutMs: 900_000, onStdout: (text) => process.stdout.write(text),});if (build.exitCode !== 0) throw new Error(build.stdout + build.stderr);await sbx.spawn("npx next start -p 3001", { cwd: "/workspace/site" });await sbx.exec("npx wait-on@9.1.0 http://127.0.0.1:3001", { check: true, timeoutMs: 120_000 });const demo = await sbx.previews.create(3001);console.log(demo.urlWithToken); // the link carries its tokenOn a paid sandbox, sbx.previews.create(3001, { visibility: "public" }) gives
an address that anyone can open, with no token. A sandbox without credit keeps
its previews private.
A failed build is useful to the agent too. next build checks types. Send its
output back as the next message, and the agent sees each error with its file
and line.
How much disk a Next.js app takes
A fresh create-next-app@16.4.3 project, measured on a Linux x86-64 machine on
25 October 2026:
| Part | Size |
|---|---|
node_modules |
476 MB |
.next after next build |
30 MB |
npm's download cache, ~/.npm |
533 MB |
That fits the default 4 GiB disk, which has about 2.5 GiB free, with room to
spare. An agent that adds many packages, or a monorepo, needs more. Ask for
diskMiB: 8192 when you create the sandbox. Without credit, a sandbox has up to
10 GiB.
Start from an image with the dependencies installed
Build the project's dependencies into a custom image with a Dockerfile. The lockfile comes first, so a rebuild after a code change reuses the installed packages:
dockerfileFROM runtimeENV NEXT_TELEMETRY_DISABLED=1WORKDIR /workspace/siteCOPY package.json package-lock.json ./RUN npm ci --no-fund --no-auditCOPY . .RUN chown -R 1000:1000 /workspace/sitePythonfrom withruntime import Runtimeruntime = Runtime()with open("site/Dockerfile") as handle: runtime.images.build(name="site", dockerfile=handle.read(), context_dir="site", on_log=lambda line: print(line["text"]))sbx = runtime.sandboxes.create(image="site")sbx.spawn("npx next dev -p 3000", cwd="/workspace/site")print(sbx.previews.create(3000)["urlWithToken"])Keep node_modules and .next in .dockerignore, so the build context holds
only the source.
Related
- Preview apps an AI agent builds
- Preview a Vite dev server
- Test the app with Playwright
- Per-user dev environments
- Custom domains for a finished app
Sources
Checked 25 October 2026.
- allowedDevOrigins:
what Next.js blocks in development, the
localhostdefault, wildcard rules and hostname-only matching - create-next-app:
--yes,--use-npm,--disable-git - next CLI:
-p, default port 3000, Turbopack by default - Next.js installation: Node.js 20.9 or later
- Next.js telemetry:
NEXT_TELEMETRY_DISABLED=1 - next on npm: version 16.4.3
Facts on this page were checked on 25 October 2026.