Port Forwarding for Web Apps
When an agent builds a web app inside a sandbox, Caged automatically detects the running server and provides a public preview URL. This recipe shows how to use it for development, demos, and reviews.
Prerequisites
- Caged CLI installed
- A running sandbox with a web app
Basic: Agent Builds and Previews a Web App
# Create sandbox with a Next.js project
caged up --template node-20 --repo https://github.com/your-org/web-app
# Let the agent build and start the dev server
caged exec cage-a1b2c3d4 "npm install && npm run dev"
# Check detected ports
caged ports cage-a1b2c3d4
Output:
PORT PROTOCOL PREVIEW URL PROTECTED
3000 http https://cage-a1b2c3d4-3000.preview.caged.dev no
Open https://cage-a1b2c3d4-3000.preview.caged.dev in your browser to see the app live.
Agent-Driven UI Development
Tell the agent to build a UI and verify it via the preview:
# .caged.yaml
template: node-20
resources:
cpu: 2
memory: 2048
budget: 10.00
secrets:
- ANTHROPIC_API_KEY
init_script: npm install
network_mode: allowlist
allowed_hosts:
- api.anthropic.com
- registry.npmjs.org
caged up
caged exec cage-a1b2c3d4 "claude 'Create a React dashboard with a sidebar, header, and three chart widgets. Start the dev server when done.'"
# Get the preview URL
caged ports cage-a1b2c3d4
# → https://cage-a1b2c3d4-3000.preview.caged.dev
Password-Protected Previews
Share previews with stakeholders while keeping them private:
# Add password protection
curl -X POST https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/ports/3000/protect \
-H "Authorization: Bearer caged_sk_..." \
-H "Content-Type: application/json" \
-d '{"password": "demo-review-2024"}'
Now visitors see a password prompt before accessing the preview. Share the URL + password with your team.
Multiple Services
Run a full-stack app with multiple services — each gets its own preview URL:
# Start frontend and backend
caged exec cage-a1b2c3d4 "cd frontend && npm run dev &"
caged exec cage-a1b2c3d4 "cd backend && npm run start &"
# Check all ports
caged ports cage-a1b2c3d4
PORT PROTOCOL PREVIEW URL PROTECTED
3000 http https://cage-a1b2c3d4-3000.preview.caged.dev no
8080 http https://cage-a1b2c3d4-8080.preview.caged.dev no
5432 tcp — no
E2E Testing with Preview URLs
Use the preview URL for automated E2E tests:
#!/bin/bash
# e2e-in-sandbox.sh
# Create sandbox and start the app
SANDBOX_ID=$(caged run --template node-20 --repo https://github.com/your-org/app \
--budget 5 --json | jq -r '.id')
caged exec "$SANDBOX_ID" "npm install && npm run dev &"
# Wait for server to start
sleep 5
# Get the preview URL
PREVIEW_URL=$(caged ports "$SANDBOX_ID" --json | jq -r '.[0].preview_url')
# Run Playwright tests against the preview
npx playwright test --config=e2e.config.ts \
--base-url="$PREVIEW_URL"
# Cleanup
caged destroy "$SANDBOX_ID" --force
Live Collaboration: Agent + Human
- Agent starts building in a sandbox
- You open the preview URL and watch progress live
- Give the agent feedback based on what you see
# Agent builds the UI
caged exec cage-a1b2c3d4 "claude 'Build a landing page for a developer tool. Start the dev server.'"
# You check the preview and want changes
caged exec cage-a1b2c3d4 "claude 'The hero section needs more contrast. Make the CTA button green and larger.'"
# Preview updates live — just refresh your browser
Custom Domain Preview (API)
Map a custom domain to a sandbox port for client demos:
curl -X POST https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/ports/3000/domain \
-H "Authorization: Bearer caged_sk_..." \
-d '{"domain": "demo.your-startup.com"}'
Custom domains require DNS configuration. Point a CNAME record to preview.caged.dev.
Tips
Ports are auto-detected: You don't need to declare ports. Caged scans for new listeners every 2 seconds.
HTTPS everywhere: All preview URLs use HTTPS automatically — no certificate configuration needed.
Hot reload works: If your dev server supports hot reload (Next.js, Vite, etc.), changes appear instantly in the preview URL.
Share with non-technical stakeholders: Preview URLs are just regular web URLs. Send them to designers, PMs, or clients — no CLI or account needed.