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)