Adds the composable monorepo template system that generates project skeletons with pluggable components (service, worker, app-react, app-astro, cli). Key changes: - Monorepo skeleton templates with shared pkg/, scripts/, and git hooks - Component templates (service, worker, app-react, app-astro, cli) with Dockerfiles, CI steps, and component.yaml manifests - Component domain model with validation and dependency resolution - Component handler endpoints for CRUD and composition - Template provider extended with BuildComposableProject and component assembly - Deployer extended with composable project deployment support - Handler timeout constants (TimeoutFastLookup through TimeoutLongRunning) - envutil package for centralized env var reads with defaults - api.DecodeJSON helper for standardized request body decoding - Standardized response helpers (WriteBadRequest, WriteNotFound, etc.) - Replaced fullstack-app cookbook with composable-app cookbook - Hardened handler timeouts, logging, and error responses across all handlers Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
8.1 KiB
8.1 KiB
Landing Page Cookbook
Deploy a landing page using composable templates through the threesix.ai infrastructure.
Overview
This cookbook creates and deploys a landing page using composable monorepo templates:
POST /projects
↓
Creates: Monorepo skeleton + Gitea repo + DNS + CI
↓
POST /projects/{id}/components (type: app, template: app-astro)
↓
Adds: Astro landing page component with valid CI step
↓
Git push triggers Woodpecker CI
↓
Live site at https://{slug}.threesix.ai
Template-driven. CI is pre-configured. No AI-generated YAML.
Prerequisites
API Access
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
Step 1: Create Project (Monorepo Skeleton)
curl -X POST "$RDEV_API_URL/projects" \
-H "X-API-Key: $RDEV_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "my-landing",
"description": "Company landing page"
}'
Response:
{
"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"
}
}
}
This creates a monorepo skeleton with:
README.md,CLAUDE.md,Procfile.woodpecker.yml(template-provided, valid CI)scripts/(discover, install, quality, dev)pkg/(shared Go packages)- Empty component directories (
services/,apps/,workers/,cli/)
Step 2: Add Landing Page Component
curl -X POST "$RDEV_API_URL/projects/my-landing/components" \
-H "X-API-Key: $RDEV_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "app",
"name": "landing",
"template": "app-astro"
}'
Response:
{
"data": {
"type": "app",
"name": "landing",
"path": "apps/landing",
"port": 3001,
"template": "app-astro"
}
}
This adds:
apps/landing/- Astro project with Tailwind CSS- Updates
.woodpecker.ymlwith build step for this component - Updates
Procfilewith dev server entry
Step 3: Customize with Claude (Optional)
Submit a build task to customize the landing page:
curl -X POST "$RDEV_API_URL/projects/my-landing/builds" \
-H "X-API-Key: $RDEV_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Update apps/landing to have: dark gradient background, centered hero section with company name \"Acme Corp\" and tagline \"Building the future\", email signup form with shadcn styling. Keep the existing Astro structure.",
"auto_commit": true,
"auto_push": true
}'
Monitor the build:
curl -s "$RDEV_API_URL/builds/{task_id}" \
-H "X-API-Key: $RDEV_API_KEY" | jq .data
Step 4: Monitor CI Pipeline
The push triggers Woodpecker CI automatically:
curl -s "$RDEV_API_URL/projects/my-landing/pipelines" \
-H "X-API-Key: $RDEV_API_KEY" | jq '.data[0]'
Wait for status: "success".
Step 5: Verify Deployment
# Check site is live
curl -I https://abc123xy.threesix.ai
# View the site
open https://abc123xy.threesix.ai
Iterating on the Site
Submit additional builds to modify the site:
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 to apps/landing with three tiers: Free, Pro ($29/mo), Enterprise (contact us). Match the existing dark theme.",
"auto_commit": true,
"auto_push": true
}'
Each build:
- Claude clones the repo
- Makes the requested changes
- Commits and pushes
- CI deploys automatically
Adding Custom Domains
# 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
curl -X DELETE "$RDEV_API_URL/projects/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:
./cookbooks/scripts/landing-test.sh run my-test-landing
Check status:
./cookbooks/scripts/landing-test.sh status my-test-landing
Cleanup:
./cookbooks/scripts/landing-test.sh teardown my-test-landing
Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ Composable Landing Page Deployment │
│ │
│ POST /projects │
│ │ │
│ ├──► Gitea: creates repo with skeleton │
│ ├──► Cloudflare: creates DNS │
│ ├──► Woodpecker: activates CI │
│ └──► Skeleton includes .woodpecker.yml (template-provided) │
│ │
│ POST /projects/{id}/components │
│ │ │
│ ├──► Adds apps/landing/ from app-astro template │
│ ├──► Updates .woodpecker.yml with build step │
│ └──► Updates Procfile │
│ │
│ POST /projects/{id}/builds (optional customization) │
│ │ │
│ └──► Claude modifies existing files, commits, pushes │
│ │
│ Git push triggers Woodpecker CI: │
│ ├──► Builds Docker image via Kaniko │
│ ├──► Pushes to registry.threesix.ai │
│ └──► Deploys to K8s │
│ │
│ Site live at https://{slug}.threesix.ai │
└─────────────────────────────────────────────────────────────────────┘
Troubleshooting
Build stuck in pending
# 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
# 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
# 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
Component not appearing
# List components
curl -s "$RDEV_API_URL/projects/my-landing/components" \
-H "X-API-Key: $RDEV_API_KEY" | jq '.data'
Related
- Composable App Cookbook - Full-stack apps with multiple components
- Worker Pool Guide
- Composable Monorepo Guide