rdev/cookbooks/landing-page.md
jordan 8282d60c69 feat: implement composable monorepo template system with component architecture
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>
2026-01-31 19:11:42 -07:00

306 lines
8.1 KiB
Markdown

# 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="<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)
```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)