Network & Preview
SeaCloud Sandbox exposes sandbox ports through sandbox-router. The current production environment uses path-style URLs: the port and Sandbox ID are placed in the first path segment, for example https://sandbox-router.cloud.seaart.ai/3000-sandbox-.../.
Runtime API traffic usually uses the template’s default port. Managed runtimes commonly use 9000; plain application templates may use a different default port, such as 9001. Your application should listen on its own port, such as 3000.
URL Model
Section titled “URL Model”Current production environment:
https://sandbox-router.cloud.seaart.ai/{port}-{sandboxID}/| URL | Meaning |
|---|---|
envdUrl, for example https://sandbox-router.cloud.seaart.ai/9000-{sandboxID} | Template default port. For managed runtimes, this is usually runtime API, health, files, and processes. |
https://sandbox-router.cloud.seaart.ai/3000-{sandboxID}/ | Direct access to an app listening on port 3000 inside the same sandbox. |
sandbox.getHost(3000) | Recommended SDK path. The SDK derives a public proxy URL from envdUrl; you do not need to build router URLs manually. |
Older templates that set envdBaseDomain to a bare domain may still return the historical subdomain form https://{port}-{sandboxID}.{domain}/. New templates and the current production environment should be treated as https://sandbox-router.cloud.seaart.ai/{port}-{sandboxID}/.
Start A Simple Static Preview
Section titled “Start A Simple Static Preview”await sandbox.files.makeDir("/root/workspace/site");await sandbox.files.write( "/root/workspace/site/index.html", "<!doctype html><h1>Hello SeaCloud</h1>",);
await sandbox.commands.run("python3", { args: ["-m", "http.server", "3000", "--bind", "0.0.0.0", "--directory", "/root/workspace/site"], background: true,});
console.log(sandbox.getHost(3000));sandbox.files.make_dir("/root/workspace/site")sandbox.files.write( "/root/workspace/site/index.html", "<!doctype html><h1>Hello SeaCloud</h1>",)sandbox.commands.run( "python3", args=["-m", "http.server", "3000", "--bind", "0.0.0.0", "--directory", "/root/workspace/site"], background=True,)print(sandbox.get_host(3000))Vite-Style Server
Section titled “Vite-Style Server”await sandbox.commands.run("sh", { cwd: "/root/workspace", args: ["-lc", "npm run dev -- --host 0.0.0.0 --port 3000"], background: true,});
console.log(sandbox.getHost(3000));Curl Derivation
Section titled “Curl Derivation”If you are using raw APIs and already have sandboxID, build the path-style app URL directly.
APP_URL="https://sandbox-router.cloud.seaart.ai/3000-${SANDBOX_ID}/"echo "${APP_URL}"If you only have a current-production envdUrl, replace the port in the first path segment:
APP_URL=$(printf '%s' "${ENVD_URL}" | sed -E 's#/([0-9]+)-#/3000-#')echo "${APP_URL}"Runtime Health And Proxy
Section titled “Runtime Health And Proxy”Use runtime health to distinguish runtime reachability from app readiness:
curl -i "${ENVD_URL}/health"Expected managed-runtime health is usually 204 No Content. GET {envdUrl}/ may return a small JSON response such as { "status": "ok" }; that does not mean your app is served on port 9000.
Runtime also supports a proxy route:
GET {envdUrl}/proxy/3000/The raw public port URL uses sandbox-router path style:
https://sandbox-router.cloud.seaart.ai/3000-{sandboxID}/Outbound Network Policy
Section titled “Outbound Network Policy”Public preview exposes traffic from the internet to a sandbox port. Outbound traffic is controlled separately by the template, environment, and account policy.
| Destination | Expected behavior |
|---|---|
| Public internet APIs | Available when the selected template and account policy allow outbound access. |
| SeaCloud APIs | Used by SDKs. Do not hard-code service addresses. |
| Private infrastructure ranges | Not part of the public contract and may be blocked by network policy. |
If a workload requires calling a private service, route that call through your backend or an explicit product integration instead of relying on sandbox network reachability.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Check |
|---|---|
9000 returns health but the app is missing | 9000 is the runtime API port, not your app port. |
App URL returns 502 | Process exited, wrong port, or service only binds to 127.0.0.1. |
| Blank page | HTML is served but assets are missing or using a wrong base path. |
| WebSocket fails | Confirm the framework uses the same host and public port route. |
readyCmd passes but preview fails | Confirm readyCmd checks the same port that users open. |