diff --git a/box/guides/nextjs-setup.mdx b/box/guides/nextjs-setup.mdx
new file mode 100644
index 00000000..1f292fb5
--- /dev/null
+++ b/box/guides/nextjs-setup.mdx
@@ -0,0 +1,93 @@
+---
+title: "Next.js Setup"
+---
+
+This guide walks you through scaffolding a [Next.js](https://nextjs.org) app inside an Upstash Box and opening it in your browser through a public URL, without using an agent.
+
+The box gives you a full Linux environment with Node.js already installed, so you can create the app, run the dev server, and share it, all through the SDK.
+
+---
+
+## 1. Create a Box
+
+Create a box with the `node` runtime. You don't need to configure an agent for this. See the [quickstart](/box/overall/quickstart) if you haven't created one before.
+
+
+```typescript box.ts
+import { Box } from "@upstash/box"
+
+const box = await Box.create({ runtime: "node" })
+```
+
+```python box.py
+from upstash_box import Box
+
+box = Box.create(runtime="node")
+```
+
+
+---
+
+## 2. Scaffold the App
+
+Run `create-next-app` inside the box. The `--yes` flag accepts the default options so the setup runs without prompts, installing all dependencies.
+
+
+```typescript box.ts
+await box.exec.command("npx --yes create-next-app@latest my-next-app --yes")
+```
+
+```python box.py
+box.exec.command("npx --yes create-next-app@latest my-next-app --yes")
+```
+
+
+---
+
+## 3. Start the Dev Server
+
+Start the development server in the background so the command returns while Next.js keeps running on port `3000`. Commands run from the box's home directory (`/workspace/home`), where the app was created.
+
+
+```typescript box.ts
+await box.exec.command("cd my-next-app && nohup npm run dev > dev.log 2>&1 &")
+```
+
+```python box.py
+box.exec.command("cd my-next-app && nohup npm run dev > dev.log 2>&1 &")
+```
+
+
+---
+
+## 4. Create a Public URL
+
+Expose port `3000` with a public URL to view the app in your browser. Creating a public URL for a running server returns its address.
+
+
+```typescript box.ts
+const publicUrl = await box.getPublicURL(3000)
+
+console.log(publicUrl.url)
+// → https://-3000.preview.box.upstash.com
+```
+
+```python box.py
+public_url = box.get_public_url(3000)
+
+print(public_url.url)
+# -> https://-3000.preview.box.upstash.com
+```
+
+
+Open the URL in your browser and your Next.js app loads. See [Public URLs](/box/overall/preview) for authentication and other options.
+
+
+ Next.js blocks cross-origin dev resources by default, so hot reloading won't work over the public URL until you add the host to `allowedDevOrigins` in `next.config.ts`:
+
+ ```typescript next.config.ts
+ const nextConfig: NextConfig = {
+ allowedDevOrigins: ["-3000.preview.box.upstash.com"],
+ }
+ ```
+
diff --git a/box/overall/ephemeral-box.mdx b/box/overall/ephemeral-box.mdx
index 12902278..0c6263fb 100644
--- a/box/overall/ephemeral-box.mdx
+++ b/box/overall/ephemeral-box.mdx
@@ -55,7 +55,7 @@ The request sends `{ ephemeral: true, ttl?, runtime? }` to `POST /v2/box`.
| `expiresAt` | No | Yes |
| `agent.run()` / `agent.stream()` | Yes | **No** |
| `git.*` | Yes | **No** |
-| `getPublicUrl()` / `listPublicUrls()` / `deletePublicUrl()` | Yes | **No** |
+| `getPublicURL()` / `listPublicURLs()` / `deletePublicURL()` | Yes | **No** |
| `snapshot()` / `fromSnapshot()` | Yes | Yes |
| `pause()` / `resume()` | Yes | **No** |
| `configureModel()` | Yes | **No** |
diff --git a/box/overall/preview.mdx b/box/overall/preview.mdx
index 1bf8a841..c2cb4937 100644
--- a/box/overall/preview.mdx
+++ b/box/overall/preview.mdx
@@ -32,7 +32,7 @@ await box.files.write({
await box.exec.command("node /work/server.js &")
// Create a public URL
-const publicUrl = await box.getPublicUrl(3000)
+const publicUrl = await box.getPublicURL(3000)
console.log(publicUrl.url)
// → https://{BOX_ID}-3000.preview.box.upstash.com
@@ -71,13 +71,13 @@ Protect your public URL with bearer token or basic authentication.
```typescript box.ts
// With bearer token
-const publicUrl = await box.getPublicUrl(3000, { bearerToken: true })
+const publicUrl = await box.getPublicURL(3000, { bearerToken: true })
console.log(publicUrl.token) // Use this in Authorization header
// → "63d8b153..."
// With basic auth
-const publicUrl = await box.getPublicUrl(8080, { basicAuth: true })
+const publicUrl = await box.getPublicURL(8080, { basicAuth: true })
console.log(publicUrl.username) // → "user"
console.log(publicUrl.password) // → "f0f145f0..."
@@ -108,7 +108,7 @@ Creates a public URL that exposes a port on your box. Returns the URL and authen
```typescript box.ts
-const publicUrl = await box.getPublicUrl(3000)
+const publicUrl = await box.getPublicURL(3000)
console.log(publicUrl.url)
// → https://{BOX_ID}-3000.preview.box.upstash.com
@@ -128,7 +128,7 @@ Add `bearerToken: true` to require an authorization header when accessing the pu
```typescript box.ts
-const publicUrl = await box.getPublicUrl(3000, { bearerToken: true })
+const publicUrl = await box.getPublicURL(3000, { bearerToken: true })
console.log(publicUrl.token)
// → "63d8b153..."
@@ -154,7 +154,7 @@ Add `basicAuth: true` to require username and password when accessing the public
```typescript box.ts
-const publicUrl = await box.getPublicUrl(8080, { basicAuth: true })
+const publicUrl = await box.getPublicURL(8080, { basicAuth: true })
console.log(publicUrl.username) // → "user"
console.log(publicUrl.password) // → "f0f145f0..."
@@ -180,7 +180,7 @@ Enable both authentication methods. Either one will work when accessing the publ
```typescript box.ts
-const publicUrl = await box.getPublicUrl(8080, { bearerToken: true, basicAuth: true })
+const publicUrl = await box.getPublicURL(8080, { bearerToken: true, basicAuth: true })
console.log(publicUrl.token) // → "63d8b153..."
console.log(publicUrl.username) // → "user"
@@ -204,9 +204,9 @@ Get all active public URLs for this box.
```typescript box.ts
-const { publicUrls } = await box.listPublicUrls()
+const { publicURLs } = await box.listPublicURLs()
-console.log(publicUrls)
+console.log(publicURLs)
// [
// { url: "https://{BOX_ID}-3000.preview.box.upstash.com", port: 3000 },
// { url: "https://{BOX_ID}-8080.preview.box.upstash.com", port: 8080 },
@@ -232,7 +232,7 @@ Remove a public URL by port number.
```typescript box.ts
-await box.deletePublicUrl(3000)
+await box.deletePublicURL(3000)
```
```python box.py
@@ -251,10 +251,10 @@ Creating a public URL for a port that already has one will overwrite the previou
```typescript box.ts
// First public URL
-const publicUrl1 = await box.getPublicUrl(3000)
+const publicUrl1 = await box.getPublicURL(3000)
// Second public URL overwrites the first one
-const publicUrl2 = await box.getPublicUrl(3000, { bearerToken: true })
+const publicUrl2 = await box.getPublicURL(3000, { bearerToken: true })
// publicUrl1.url is no longer accessible
```
@@ -285,7 +285,7 @@ Creating a public URL on a paused box automatically resumes it.
await box.pause()
// This will resume the box
-const publicUrl = await box.getPublicUrl(3000)
+const publicUrl = await box.getPublicURL(3000)
```
```python box.py
@@ -327,7 +327,7 @@ Create a simple Express web server that:
`,
})
-const publicUrl = await box.getPublicUrl(3000)
+const publicUrl = await box.getPublicURL(3000)
console.log(`Public URL available at: ${publicUrl.url}`)
// Test the endpoints
@@ -397,7 +397,7 @@ if __name__ == '__main__':
await box.exec.command("pip install flask && python /work/app.py &")
// Create authenticated public URL
-const publicUrl = await box.getPublicUrl(8080, { basicAuth: true })
+const publicUrl = await box.getPublicURL(8080, { basicAuth: true })
console.log(`Public URL: ${publicUrl.url}`)
console.log(`Username: ${publicUrl.username}`)
@@ -477,8 +477,8 @@ await box.exec.command("npm install express")
await box.exec.command("node /work/frontend.js & node /work/api.js &")
// Create a public URL for each service
-const frontendPublicUrl = await box.getPublicUrl(3000)
-const apiPublicUrl = await box.getPublicUrl(8080)
+const frontendPublicUrl = await box.getPublicURL(3000)
+const apiPublicUrl = await box.getPublicURL(8080)
console.log(`Frontend: ${frontendPublicUrl.url}`)
console.log(`API: ${apiPublicUrl.url}`)
@@ -537,14 +537,14 @@ const box = await Box.create({ runtime: "node" })
await box.exec.command("npx http-server /work -p 3000 &")
// Create a public URL for testing
-const publicUrl = await box.getPublicUrl(3000)
+const publicUrl = await box.getPublicURL(3000)
// Run your tests against the public URL
const response = await fetch(publicUrl.url)
console.log(response.status) // 200
// Clean up
-await box.deletePublicUrl(3000)
+await box.deletePublicURL(3000)
await box.delete()
```
@@ -571,4 +571,4 @@ box.delete()
-The SDK still supports `getPreviewUrl`, `listPreviews`, and `deletePreview`, but they are deprecated aliases for `getPublicUrl`, `listPublicUrls`, and `deletePublicUrl`.
+The SDK still supports `getPreviewUrl`, `listPreviews`, and `deletePreview`, but they are deprecated aliases for `getPublicURL`, `listPublicURLs`, and `deletePublicURL`.
diff --git a/docs.json b/docs.json
index efe31a21..3b1c3193 100644
--- a/docs.json
+++ b/docs.json
@@ -1680,7 +1680,7 @@
},
{
"group": "Guides",
- "pages": ["box/guides/remote-development", "box/guides/code-review-agent", "box/guides/web-scraping-playwright", "box/guides/ai-sdk-code-interpreter", "box/guides/tanstack-ai-file-editor", "box/guides/openclaw-setup", "box/guides/hermes-setup", "box/guides/crabbox-setup"]
+ "pages": ["box/guides/remote-development", "box/guides/nextjs-setup", "box/guides/code-review-agent", "box/guides/web-scraping-playwright", "box/guides/ai-sdk-code-interpreter", "box/guides/tanstack-ai-file-editor", "box/guides/openclaw-setup", "box/guides/hermes-setup", "box/guides/crabbox-setup"]
}
]
},
diff --git a/llms-full.txt b/llms-full.txt
index ce11c3e9..958399bd 100644
--- a/llms-full.txt
+++ b/llms-full.txt
@@ -1172,6 +1172,99 @@ hermes gateway start > gateway.log 2>&1 &
This command runs automatically whenever the box starts, so your gateway is always available without manual intervention.
+# Next.js Setup
+Source: https://upstash.com/docs/box/guides/nextjs-setup
+
+This guide walks you through scaffolding a [Next.js](https://nextjs.org) app inside an Upstash Box and opening it in your browser through a public URL, without using an agent.
+
+The box gives you a full Linux environment with Node.js already installed, so you can create the app, run the dev server, and share it, all through the SDK.
+
+***
+
+## 1. Create a Box
+
+Create a box with the `node` runtime. You don't need to configure an agent for this. See the [quickstart](/docs/box/overall/quickstart) if you haven't created one before.
+
+
+```typescript box.ts
+import { Box } from "@upstash/box"
+
+const box = await Box.create({ runtime: "node" })
+```
+
+```python box.py
+from upstash_box import Box
+
+box = Box.create(runtime="node")
+```
+
+
+***
+
+## 2. Scaffold the App
+
+Run `create-next-app` inside the box. The `--yes` flag accepts the default options so the setup runs without prompts, installing all dependencies.
+
+
+```typescript box.ts
+await box.exec.command("npx --yes create-next-app@latest my-next-app --yes")
+```
+
+```python box.py
+box.exec.command("npx --yes create-next-app@latest my-next-app --yes")
+```
+
+
+***
+
+## 3. Start the Dev Server
+
+Start the development server in the background so the command returns while Next.js keeps running on port `3000`. Commands run from the box's home directory (`/workspace/home`), where the app was created.
+
+
+```typescript box.ts
+await box.exec.command("cd my-next-app && nohup npm run dev > dev.log 2>&1 &")
+```
+
+```python box.py
+box.exec.command("cd my-next-app && nohup npm run dev > dev.log 2>&1 &")
+```
+
+
+***
+
+## 4. Create a Public URL
+
+Expose port `3000` with a public URL to view the app in your browser. Creating a public URL for a running server returns its address.
+
+
+```typescript box.ts
+const publicUrl = await box.getPublicURL(3000)
+
+console.log(publicUrl.url)
+// → https://-3000.preview.box.upstash.com
+```
+
+```python box.py
+public_url = box.get_public_url(3000)
+
+print(public_url.url)
+# -> https://-3000.preview.box.upstash.com
+```
+
+
+Open the URL in your browser and your Next.js app loads. See [Public URLs](/docs/box/overall/preview) for authentication and other options.
+
+
+ Next.js blocks cross-origin dev resources by default, so hot reloading won't work over the public URL until you add the host to `allowedDevOrigins` in `next.config.ts`:
+
+ ```typescript next.config.ts
+ const nextConfig: NextConfig = {
+ allowedDevOrigins: ["-3000.preview.box.upstash.com"],
+ }
+ ```
+
+
# OpenClaw Setup
Source: https://upstash.com/docs/box/guides/openclaw-setup
@@ -2752,7 +2845,7 @@ The request sends `{ ephemeral: true, ttl?, runtime? }` to `POST /v2/box`.
| `expiresAt` | No | Yes |
| `agent.run()` / `agent.stream()` | Yes | **No** |
| `git.*` | Yes | **No** |
-| `getPublicUrl()` / `listPublicUrls()` / `deletePublicUrl()` | Yes | **No** |
+| `getPublicURL()` / `listPublicURLs()` / `deletePublicURL()` | Yes | **No** |
| `snapshot()` / `fromSnapshot()` | Yes | Yes |
| `pause()` / `resume()` | Yes | **No** |
| `configureModel()` | Yes | **No** |
@@ -4473,7 +4566,7 @@ await box.files.write({
await box.exec.command("node /work/server.js &")
// Create a public URL
-const publicUrl = await box.getPublicUrl(3000)
+const publicUrl = await box.getPublicURL(3000)
console.log(publicUrl.url)
// → https://{BOX_ID}-3000.preview.box.upstash.com
@@ -4512,13 +4605,13 @@ Protect your public URL with bearer token or basic authentication.
```typescript box.ts
// With bearer token
-const publicUrl = await box.getPublicUrl(3000, { bearerToken: true })
+const publicUrl = await box.getPublicURL(3000, { bearerToken: true })
console.log(publicUrl.token) // Use this in Authorization header
// → "63d8b153..."
// With basic auth
-const publicUrl = await box.getPublicUrl(8080, { basicAuth: true })
+const publicUrl = await box.getPublicURL(8080, { basicAuth: true })
console.log(publicUrl.username) // → "user"
console.log(publicUrl.password) // → "f0f145f0..."
@@ -4549,7 +4642,7 @@ Creates a public URL that exposes a port on your box. Returns the URL and authen
```typescript box.ts
-const publicUrl = await box.getPublicUrl(3000)
+const publicUrl = await box.getPublicURL(3000)
console.log(publicUrl.url)
// → https://{BOX_ID}-3000.preview.box.upstash.com
@@ -4569,7 +4662,7 @@ Add `bearerToken: true` to require an authorization header when accessing the pu
```typescript box.ts
-const publicUrl = await box.getPublicUrl(3000, { bearerToken: true })
+const publicUrl = await box.getPublicURL(3000, { bearerToken: true })
console.log(publicUrl.token)
// → "63d8b153..."
@@ -4595,7 +4688,7 @@ Add `basicAuth: true` to require username and password when accessing the public
```typescript box.ts
-const publicUrl = await box.getPublicUrl(8080, { basicAuth: true })
+const publicUrl = await box.getPublicURL(8080, { basicAuth: true })
console.log(publicUrl.username) // → "user"
console.log(publicUrl.password) // → "f0f145f0..."
@@ -4621,7 +4714,7 @@ Enable both authentication methods. Either one will work when accessing the publ
```typescript box.ts
-const publicUrl = await box.getPublicUrl(8080, { bearerToken: true, basicAuth: true })
+const publicUrl = await box.getPublicURL(8080, { bearerToken: true, basicAuth: true })
console.log(publicUrl.token) // → "63d8b153..."
console.log(publicUrl.username) // → "user"
@@ -4645,9 +4738,9 @@ Get all active public URLs for this box.
```typescript box.ts
-const { publicUrls } = await box.listPublicUrls()
+const { publicURLs } = await box.listPublicURLs()
-console.log(publicUrls)
+console.log(publicURLs)
// [
// { url: "https://{BOX_ID}-3000.preview.box.upstash.com", port: 3000 },
// { url: "https://{BOX_ID}-8080.preview.box.upstash.com", port: 8080 },
@@ -4673,7 +4766,7 @@ Remove a public URL by port number.
```typescript box.ts
-await box.deletePublicUrl(3000)
+await box.deletePublicURL(3000)
```
```python box.py
@@ -4692,10 +4785,10 @@ Creating a public URL for a port that already has one will overwrite the previou
```typescript box.ts
// First public URL
-const publicUrl1 = await box.getPublicUrl(3000)
+const publicUrl1 = await box.getPublicURL(3000)
// Second public URL overwrites the first one
-const publicUrl2 = await box.getPublicUrl(3000, { bearerToken: true })
+const publicUrl2 = await box.getPublicURL(3000, { bearerToken: true })
// publicUrl1.url is no longer accessible
```
@@ -4726,7 +4819,7 @@ Creating a public URL on a paused box automatically resumes it.
await box.pause()
// This will resume the box
-const publicUrl = await box.getPublicUrl(3000)
+const publicUrl = await box.getPublicURL(3000)
```
```python box.py
@@ -4768,7 +4861,7 @@ Create a simple Express web server that:
`,
})
-const publicUrl = await box.getPublicUrl(3000)
+const publicUrl = await box.getPublicURL(3000)
console.log(`Public URL available at: ${publicUrl.url}`)
// Test the endpoints
@@ -4838,7 +4931,7 @@ if __name__ == '__main__':
await box.exec.command("pip install flask && python /work/app.py &")
// Create authenticated public URL
-const publicUrl = await box.getPublicUrl(8080, { basicAuth: true })
+const publicUrl = await box.getPublicURL(8080, { basicAuth: true })
console.log(`Public URL: ${publicUrl.url}`)
console.log(`Username: ${publicUrl.username}`)
@@ -4918,8 +5011,8 @@ await box.exec.command("npm install express")
await box.exec.command("node /work/frontend.js & node /work/api.js &")
// Create a public URL for each service
-const frontendPublicUrl = await box.getPublicUrl(3000)
-const apiPublicUrl = await box.getPublicUrl(8080)
+const frontendPublicUrl = await box.getPublicURL(3000)
+const apiPublicUrl = await box.getPublicURL(8080)
console.log(`Frontend: ${frontendPublicUrl.url}`)
console.log(`API: ${apiPublicUrl.url}`)
@@ -4978,14 +5071,14 @@ const box = await Box.create({ runtime: "node" })
await box.exec.command("npx http-server /work -p 3000 &")
// Create a public URL for testing
-const publicUrl = await box.getPublicUrl(3000)
+const publicUrl = await box.getPublicURL(3000)
// Run your tests against the public URL
const response = await fetch(publicUrl.url)
console.log(response.status) // 200
// Clean up
-await box.deletePublicUrl(3000)
+await box.deletePublicURL(3000)
await box.delete()
```
@@ -5011,7 +5104,7 @@ box.delete()
```
-The SDK still supports `getPreviewUrl`, `listPreviews`, and `deletePreview`, but they are deprecated aliases for `getPublicUrl`, `listPublicUrls`, and `deletePublicUrl`.
+The SDK still supports `getPreviewUrl`, `listPreviews`, and `deletePreview`, but they are deprecated aliases for `getPublicURL`, `listPublicURLs`, and `deletePublicURL`.
# Pricing & Limits
Source: https://upstash.com/docs/box/overall/pricing
diff --git a/llms.txt b/llms.txt
index ff85a91a..bcb5a1c4 100644
--- a/llms.txt
+++ b/llms.txt
@@ -36,6 +36,7 @@
- [Build a Code Review Agent](https://upstash.com/docs/box/guides/code-review-agent.md)
- [Running Tests with Crabbox](https://upstash.com/docs/box/guides/crabbox-setup.md)
- [Hermes Setup](https://upstash.com/docs/box/guides/hermes-setup.md)
+- [Next.js Setup](https://upstash.com/docs/box/guides/nextjs-setup.md)
- [OpenClaw Setup](https://upstash.com/docs/box/guides/openclaw-setup.md)
- [Remote Development](https://upstash.com/docs/box/guides/remote-development.md)
- [AI File Editor with TanStack AI](https://upstash.com/docs/box/guides/tanstack-ai-file-editor.md)