# 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 ```bash export RDEV_API_URL="https://rdev.masq-ops.orchard9.ai" export RDEV_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) ```bash 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:** ```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" } } } ``` 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 ```bash 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:** ```json { "data": { "type": "app", "name": "landing", "path": "apps/landing", "port": 3001, "template": "app-astro" } } ``` This adds: - `apps/landing/` - Astro project with Tailwind CSS - Updates `.woodpecker.yml` with build step for this component - Updates `Procfile` with dev server entry --- ## Step 3: Customize with Claude (Optional) Submit a build task to customize the landing page: ```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": "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: ```bash 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: ```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 5: Verify Deployment ```bash # 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: ```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 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: 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/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: ```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 ``` ┌─────────────────────────────────────────────────────────────────────┐ │ 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 ```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 ``` ### Component not appearing ```bash # List components curl -s "$RDEV_API_URL/projects/my-landing/components" \ -H "X-API-Key: $RDEV_API_KEY" | jq '.data' ``` --- ## Related - [Composable App Cookbook](./composable-app.md) - Full-stack apps with multiple components - [Worker Pool Guide](../.claude/guides/services/worker-pool.md) - [Composable Monorepo Guide](../.claude/guides/services/composable-monorepo.md)