- Add session_id, model, allowed_tools to Claude request handler - Update OpenAPI spec for Claude endpoint - Fix BuildExecutor constructor call sites - Rewrite landing-test.sh for agent-driven flow - Fix cookbook documentation for correct API format Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
313 lines
8.5 KiB
Markdown
313 lines
8.5 KiB
Markdown
# Landing Page Cookbook
|
|
|
|
> Deploy a landing page built by a Claude agent through the threesix.ai infrastructure.
|
|
|
|
## Overview
|
|
|
|
This cookbook creates and deploys a landing page using **agent-driven development**:
|
|
|
|
```
|
|
POST /project/create-and-build
|
|
↓
|
|
Creates: Gitea repo + DNS + Woodpecker CI + K8s deployment
|
|
↓
|
|
Enqueues build task with prompt
|
|
↓
|
|
Worker picks up task → Claude builds the site
|
|
↓
|
|
Agent commits + pushes
|
|
↓
|
|
CI builds and deploys
|
|
↓
|
|
Live site
|
|
```
|
|
|
|
**No templates. Claude builds it from scratch based on your prompt.**
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
### API Access
|
|
```bash
|
|
export RDEV_API_URL="https://rdev.masq-ops.orchard9.ai"
|
|
export RDEV_API_KEY="<your-api-key>"
|
|
```
|
|
|
|
### Infrastructure Required
|
|
- rdev-api running with embedded worker
|
|
- Gitea at https://git.threesix.ai
|
|
- Woodpecker CI at https://ci.threesix.ai
|
|
- claudebox-0 pod running in rdev namespace
|
|
|
|
---
|
|
|
|
## Step 1: Create Project and Build in One Call
|
|
|
|
Single API call that creates infrastructure AND enqueues agent work:
|
|
|
|
```bash
|
|
curl -X POST "$RDEV_API_URL/project/create-and-build" \
|
|
-H "X-API-Key: $RDEV_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "my-landing",
|
|
"description": "Company landing page",
|
|
"prompt": "Build a modern landing page with: dark gradient background, centered hero section with company name and tagline, email signup form, responsive design. Use vanilla HTML/CSS/JS. Create index.html, styles.css, and a simple Dockerfile that serves with nginx.",
|
|
"auto_commit": true,
|
|
"auto_push": true
|
|
}'
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"project_id": "my-landing",
|
|
"name": "my-landing",
|
|
"domain": "abc123xy.threesix.ai",
|
|
"url": "https://abc123xy.threesix.ai",
|
|
"git": {
|
|
"owner": "jordan",
|
|
"name": "my-landing",
|
|
"html_url": "https://git.threesix.ai/jordan/my-landing"
|
|
},
|
|
"task_id": "task-uuid",
|
|
"status": "pending",
|
|
"status_url": "/builds/task-uuid"
|
|
},
|
|
"meta": { "timestamp": "..." }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Step 2: Monitor Build Progress
|
|
|
|
Poll the build status:
|
|
|
|
```bash
|
|
curl -s "$RDEV_API_URL/builds/{task_id}" \
|
|
-H "X-API-Key: $RDEV_API_KEY" | jq .data
|
|
```
|
|
|
|
**Status progression:** `pending` → `running` → `completed` (or `failed`)
|
|
|
|
When completed:
|
|
```json
|
|
{
|
|
"task_id": "task-uuid",
|
|
"project_id": "my-landing",
|
|
"status": "completed",
|
|
"prompt": "Build a modern landing page...",
|
|
"auto_commit": true,
|
|
"auto_push": true,
|
|
"started_at": "2025-01-29T10:00:00Z",
|
|
"completed_at": "2025-01-29T10:00:45Z",
|
|
"result": {
|
|
"success": true,
|
|
"commit_sha": "abc123",
|
|
"files_changed": ["index.html", "styles.css", "Dockerfile", "nginx.conf"],
|
|
"duration_ms": 45000
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Step 3: Monitor CI Pipeline
|
|
|
|
The agent's push triggers Woodpecker CI:
|
|
|
|
```bash
|
|
curl -s "$RDEV_API_URL/projects/my-landing/pipelines" \
|
|
-H "X-API-Key: $RDEV_API_KEY" | jq '.data[0]'
|
|
```
|
|
|
|
Wait for `status: "success"`.
|
|
|
|
---
|
|
|
|
## Step 4: Verify Deployment
|
|
|
|
```bash
|
|
# Check site is live
|
|
curl -I https://abc123xy.threesix.ai
|
|
|
|
# View the site
|
|
open https://abc123xy.threesix.ai
|
|
```
|
|
|
|
---
|
|
|
|
## Alternative: Two-Step Flow
|
|
|
|
If you prefer to create the project first, then submit builds separately:
|
|
|
|
### Create Project (empty repo)
|
|
```bash
|
|
curl -X POST "$RDEV_API_URL/project" \
|
|
-H "X-API-Key: $RDEV_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "my-landing",
|
|
"description": "Company landing page"
|
|
}'
|
|
```
|
|
|
|
### Submit Build Task
|
|
```bash
|
|
curl -X POST "$RDEV_API_URL/projects/my-landing/builds" \
|
|
-H "X-API-Key: $RDEV_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"prompt": "Build a modern landing page with dark theme, hero section, and email signup form. Use HTML/CSS/JS with nginx Dockerfile.",
|
|
"auto_commit": true,
|
|
"auto_push": true
|
|
}'
|
|
```
|
|
|
|
---
|
|
|
|
## Iterating on the Site
|
|
|
|
Submit additional builds to modify the site:
|
|
|
|
```bash
|
|
curl -X POST "$RDEV_API_URL/projects/my-landing/builds" \
|
|
-H "X-API-Key: $RDEV_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"prompt": "Add a pricing section with three tiers: Free, Pro ($29/mo), Enterprise (contact us). Match the existing dark theme.",
|
|
"auto_commit": true,
|
|
"auto_push": true
|
|
}'
|
|
```
|
|
|
|
Each build:
|
|
1. Claude clones the repo
|
|
2. Makes the requested changes
|
|
3. Commits and pushes
|
|
4. CI deploys automatically
|
|
|
|
---
|
|
|
|
## Adding Custom Domains
|
|
|
|
```bash
|
|
# Add www subdomain
|
|
curl -X POST "$RDEV_API_URL/projects/my-landing/domains" \
|
|
-H "X-API-Key: $RDEV_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"domain": "www.mycompany.com"}'
|
|
|
|
# List all domains
|
|
curl -s "$RDEV_API_URL/projects/my-landing/domains" \
|
|
-H "X-API-Key: $RDEV_API_KEY" | jq '.data.domains'
|
|
```
|
|
|
|
---
|
|
|
|
## Teardown
|
|
|
|
```bash
|
|
curl -X DELETE "$RDEV_API_URL/project/my-landing" \
|
|
-H "X-API-Key: $RDEV_API_KEY"
|
|
```
|
|
|
|
Removes: DNS records, K8s deployment, project metadata. Gitea repo preserved for safety.
|
|
|
|
---
|
|
|
|
## E2E Test Script
|
|
|
|
Run the full flow:
|
|
```bash
|
|
./cookbooks/scripts/landing-test.sh run my-test-landing
|
|
```
|
|
|
|
Check status:
|
|
```bash
|
|
./cookbooks/scripts/landing-test.sh status my-test-landing
|
|
```
|
|
|
|
Cleanup:
|
|
```bash
|
|
./cookbooks/scripts/landing-test.sh teardown my-test-landing
|
|
```
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
│ Agent-Driven Landing Page │
|
|
│ │
|
|
│ POST /project/create-and-build │
|
|
│ │ │
|
|
│ ├──► Gitea: creates repo │
|
|
│ ├──► Cloudflare: creates DNS │
|
|
│ ├──► Woodpecker: activates CI │
|
|
│ ├──► K8s: creates Deployment/Service/Ingress │
|
|
│ └──► Work Queue: enqueues build task │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ Worker polls queue, claims task │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ Claude Code executes in claudebox-0: │
|
|
│ - Clones repo │
|
|
│ - Builds site from prompt │
|
|
│ - Commits and pushes │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ Woodpecker CI triggered by push: │
|
|
│ - Builds Docker image │
|
|
│ - Pushes to registry │
|
|
│ - Updates K8s deployment │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ Site live at https://{slug}.threesix.ai │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Build stuck in pending
|
|
```bash
|
|
# Check worker status
|
|
curl -s "$RDEV_API_URL/workers" -H "X-API-Key: $RDEV_API_KEY" | jq '.data.summary'
|
|
|
|
# Should show at least 1 idle worker
|
|
```
|
|
|
|
### Build failed
|
|
```bash
|
|
# Get build details
|
|
curl -s "$RDEV_API_URL/builds/{task_id}" -H "X-API-Key: $RDEV_API_KEY" | jq '.result'
|
|
|
|
# Check rdev-api logs
|
|
./scripts/logs.sh -e
|
|
```
|
|
|
|
### Pipeline not triggering
|
|
```bash
|
|
# Check if commit was pushed
|
|
curl -s "https://git.threesix.ai/api/v1/repos/jordan/my-landing/commits" | jq '.[0]'
|
|
|
|
# Check Woodpecker
|
|
open https://ci.threesix.ai/jordan/my-landing
|
|
```
|
|
|
|
---
|
|
|
|
## Related
|
|
|
|
- [Full-Stack App Cookbook](./fullstack-app.md) - Next.js + Go backend
|
|
- [Worker Pool Guide](../.claude/guides/services/worker-pool.md)
|
|
- [Build Orchestration](../.claude/guides/services/build-orchestration.md)
|