Skip to content

Commit 1589d19

Browse files
cteclaude
andauthored
docs: add preview environments documentation (#495)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 0a7a113 commit 1589d19

2 files changed

Lines changed: 390 additions & 0 deletions

File tree

Lines changed: 389 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,389 @@
1+
---
2+
description: Configure multi-port preview environments with automatic domain routing and environment variable injection for full-stack applications.
3+
keywords:
4+
- Preview Environments
5+
- Multi-port
6+
- Named Ports
7+
- Environment Variables
8+
- Full Stack
9+
- Services
10+
- Postgres
11+
- Redis
12+
---
13+
14+
# Preview Environments
15+
16+
Preview environments let you run multiple services in a cloud container with automatic domain routing. Each port you configure gets a unique public URL, and environment variables are injected so your applications can communicate with each other.
17+
18+
## Overview
19+
20+
When you spawn an environment, Roo Code Cloud:
21+
22+
1. Creates a cloud container with your configured ports exposed
23+
2. Generates unique HTTPS domains for each port
24+
3. Injects environment variables like `ROO_WEB_HOST` and `ROO_API_HOST` into your container
25+
4. Clones your repositories, starts services, and runs your commands
26+
27+
This allows you to run a complete stack—frontend, API, workers—in a single preview environment where all the pieces can talk to each other.
28+
29+
## Configuration
30+
31+
Environments are configured in YAML format. Here's the complete schema:
32+
33+
```yaml
34+
name: My Full Stack App
35+
description: Frontend and API running together
36+
37+
repositories:
38+
- repository: myorg/frontend
39+
commands:
40+
- name: Install
41+
run: npm install
42+
- name: Start
43+
run: npm run dev &
44+
45+
- repository: myorg/backend
46+
commands:
47+
- name: Install
48+
run: npm install
49+
- name: Start
50+
run: npm run dev &
51+
52+
ports:
53+
- name: WEB
54+
port: 3000
55+
- name: API
56+
port: 3001
57+
58+
services:
59+
- postgres16
60+
- redis7
61+
62+
env:
63+
NODE_ENV: development
64+
```
65+
66+
## Named Ports
67+
68+
The `ports` section defines which ports to expose and what to call them:
69+
70+
```yaml
71+
ports:
72+
- name: WEB
73+
port: 3000
74+
- name: API
75+
port: 3001
76+
- name: ADMIN
77+
port: 3002
78+
```
79+
80+
For each named port, an environment variable is injected into your container:
81+
82+
| Port Config | Environment Variable | Example Value |
83+
|-------------|---------------------|---------------|
84+
| `name: WEB, port: 3000` | `ROO_WEB_HOST` | `https://abc123.vercel.run` |
85+
| `name: API, port: 3001` | `ROO_API_HOST` | `https://def456.vercel.run` |
86+
| `name: ADMIN, port: 3002` | `ROO_ADMIN_HOST` | `https://ghi789.vercel.run` |
87+
88+
### Naming Rules
89+
90+
Port names must:
91+
- Start with a letter
92+
- Contain only letters, numbers, and underscores
93+
- Be 1-50 characters long
94+
95+
The name is converted to uppercase for the environment variable (e.g., `web` becomes `ROO_WEB_HOST`).
96+
97+
### Limits
98+
99+
You can configure up to **4 named ports** per environment.
100+
101+
## Using Environment Variables in Your Code
102+
103+
The injected environment variables let your applications find each other without hardcoded URLs.
104+
105+
### React/Vite Frontend
106+
107+
```typescript
108+
// vite.config.ts
109+
export default defineConfig({
110+
define: {
111+
'import.meta.env.API_URL': JSON.stringify(process.env.ROO_API_HOST || 'http://localhost:3001')
112+
}
113+
})
114+
115+
// In your React code
116+
const response = await fetch(`${import.meta.env.API_URL}/api/users`);
117+
```
118+
119+
### Next.js Frontend
120+
121+
```typescript
122+
// next.config.js
123+
module.exports = {
124+
env: {
125+
NEXT_PUBLIC_API_URL: process.env.ROO_API_HOST || 'http://localhost:3001'
126+
}
127+
}
128+
129+
// In your code
130+
const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/users`);
131+
```
132+
133+
### Node.js/Express/Hono Backend
134+
135+
```typescript
136+
// Configure CORS to allow requests from the frontend domain
137+
app.use(cors({
138+
origin: process.env.ROO_WEB_HOST || 'http://localhost:3000'
139+
}));
140+
141+
// Or allow multiple frontends
142+
app.use(cors({
143+
origin: [
144+
process.env.ROO_WEB_HOST,
145+
process.env.ROO_ADMIN_HOST
146+
].filter(Boolean)
147+
}));
148+
```
149+
150+
### Inter-Service Communication
151+
152+
If you have multiple backend services:
153+
154+
```typescript
155+
// In your API service, call a worker service
156+
const workerUrl = process.env.ROO_WORKER_HOST || 'http://localhost:3002';
157+
await fetch(`${workerUrl}/jobs`, { method: 'POST', body: jobData });
158+
```
159+
160+
## Repositories
161+
162+
List the repositories to clone into your environment:
163+
164+
```yaml
165+
repositories:
166+
- repository: myorg/frontend
167+
commands:
168+
- name: Install dependencies
169+
run: npm install
170+
- name: Build
171+
run: npm run build
172+
- name: Start dev server
173+
run: npm run dev &
174+
175+
- repository: myorg/backend
176+
commands:
177+
- name: Install dependencies
178+
run: npm install
179+
- name: Run migrations
180+
run: npm run db:migrate
181+
- name: Start server
182+
run: npm run start &
183+
```
184+
185+
### Repository Format
186+
187+
Use the `owner/repo` format (e.g., `myorg/my-app`).
188+
189+
### Commands
190+
191+
Each repository can have its own commands that run in order. Commands support:
192+
193+
| Field | Description | Default |
194+
|-------|-------------|---------|
195+
| `name` | Display name for the command | Required |
196+
| `run` | The shell command to execute | Required |
197+
| `working_dir` | Directory to run the command in | Repository root |
198+
| `env` | Command-specific environment variables | None |
199+
| `timeout` | Maximum seconds to wait | 60 |
200+
| `continue_on_error` | Keep going if command fails | false |
201+
202+
### Background Processes
203+
204+
To start a server that keeps running, end the command with `&`:
205+
206+
```yaml
207+
commands:
208+
- name: Start server
209+
run: npm run dev &
210+
```
211+
212+
## Services
213+
214+
Add managed database and cache services:
215+
216+
```yaml
217+
services:
218+
- redis7
219+
- postgres16
220+
```
221+
222+
### Available Services
223+
224+
| Service | Default Port | Connection Variables |
225+
|---------|--------------|---------------------|
226+
| `redis6` | 6379 | `REDIS_URL` |
227+
| `redis7` | 6379 | `REDIS_URL` |
228+
| `postgres15` | 5432 | `DATABASE_URL`, `POSTGRES_*` |
229+
| `postgres16` | 5432 | `DATABASE_URL`, `POSTGRES_*` |
230+
| `postgres17` | 5432 | `DATABASE_URL`, `POSTGRES_*` |
231+
| `mysql8` | 3306 | `DATABASE_URL`, `MYSQL_*` |
232+
| `mariadb10` | 3306 | `DATABASE_URL`, `MARIADB_*` |
233+
| `clickhouse` | 9000 | `CLICKHOUSE_URL` |
234+
235+
### Custom Ports
236+
237+
If you need a service on a non-default port:
238+
239+
```yaml
240+
services:
241+
- name: postgres16
242+
port: 5433
243+
```
244+
245+
## Environment Variables
246+
247+
Define environment variables available to all commands:
248+
249+
```yaml
250+
env:
251+
NODE_ENV: development
252+
LOG_LEVEL: debug
253+
FEATURE_FLAGS: "new-ui,beta-api"
254+
```
255+
256+
These are merged with:
257+
1. Service connection variables (e.g., `DATABASE_URL`)
258+
2. Named port variables (e.g., `ROO_WEB_HOST`)
259+
3. Command-specific variables (highest priority)
260+
261+
## Complete Example
262+
263+
Here's a full-stack application with a React frontend, Hono API, and background worker:
264+
265+
```yaml
266+
name: E-Commerce Platform
267+
description: Full stack with frontend, API, and worker
268+
269+
repositories:
270+
- repository: acme/storefront
271+
commands:
272+
- name: Install
273+
run: npm install
274+
- name: Build
275+
run: npm run build
276+
env:
277+
VITE_API_URL: ${ROO_API_HOST}
278+
- name: Serve
279+
run: npx serve -s dist -l 3000 &
280+
281+
- repository: acme/api
282+
commands:
283+
- name: Install
284+
run: npm install
285+
- name: Migrate
286+
run: npm run db:push
287+
- name: Start
288+
run: npm run start &
289+
env:
290+
ALLOWED_ORIGINS: ${ROO_WEB_HOST}
291+
292+
- repository: acme/worker
293+
commands:
294+
- name: Install
295+
run: npm install
296+
- name: Start
297+
run: npm run start &
298+
299+
ports:
300+
- name: WEB
301+
port: 3000
302+
- name: API
303+
port: 3001
304+
- name: WORKER
305+
port: 3002
306+
307+
services:
308+
- postgres16
309+
- redis7
310+
311+
env:
312+
NODE_ENV: production
313+
LOG_LEVEL: info
314+
```
315+
316+
After the environment starts, you'll get unique URLs for each port. Visit the WEB URL to access your running application.
317+
318+
## Tips
319+
320+
### 1. Always Use Environment Variables for URLs
321+
322+
Don't hardcode URLs between services:
323+
324+
```typescript
325+
// Bad - breaks in preview environments
326+
const apiUrl = 'http://localhost:3001';
327+
328+
// Good - works everywhere
329+
const apiUrl = process.env.ROO_API_HOST || 'http://localhost:3001';
330+
```
331+
332+
### 2. Configure CORS Dynamically
333+
334+
```typescript
335+
// Bad - only works locally
336+
app.use(cors({ origin: 'http://localhost:3000' }));
337+
338+
// Good - works in preview and locally
339+
app.use(cors({
340+
origin: process.env.ROO_WEB_HOST || 'http://localhost:3000'
341+
}));
342+
```
343+
344+
### 3. Use Build-Time Variables for Static Sites
345+
346+
For frameworks like Vite, CRA, or Next.js, the API URL often needs to be known at build time:
347+
348+
```yaml
349+
commands:
350+
- name: Build
351+
run: npm run build
352+
env:
353+
VITE_API_URL: ${ROO_API_HOST}
354+
```
355+
356+
### 4. Handle Missing Variables Gracefully
357+
358+
In development, you might not have all variables set:
359+
360+
```typescript
361+
const apiUrl = process.env.ROO_API_HOST;
362+
if (!apiUrl) {
363+
console.warn('ROO_API_HOST not set, using localhost');
364+
}
365+
```
366+
367+
### 5. Use Consistent Naming
368+
369+
Pick a naming convention and stick with it:
370+
371+
```yaml
372+
# Good - clear and consistent
373+
ports:
374+
- name: WEB
375+
port: 3000
376+
- name: API
377+
port: 3001
378+
- name: ADMIN
379+
port: 3002
380+
381+
# Avoid - inconsistent naming
382+
ports:
383+
- name: frontend
384+
port: 3000
385+
- name: BACKEND_API
386+
port: 3001
387+
- name: Admin_Panel
388+
port: 3002
389+
```

sidebars.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ const sidebars: SidebarsConfig = {
127127
'roo-code-cloud/overview',
128128
'roo-code-cloud/login',
129129
'roo-code-cloud/cloud-agents',
130+
'roo-code-cloud/environments',
130131
'roo-code-cloud/task-sync',
131132
'roo-code-cloud/roomote-control',
132133
'roo-code-cloud/task-sharing',

0 commit comments

Comments
 (0)