Target: UAT / Local deployment on Mac Mini Stack: Go backend · SolidStart frontend · Redis Transport: Docker Compose (Docker for Mac / Podman Desktop)

Architecture

┌──────────────────────────────────┐
│  Browser                         │
└────────────┬─────────────────────┘
             │ HTTP  :3000
┌────────────▼─────────────────────┐
│  Frontend  (SolidStart)          │
│  Port 3000                       │
│  Proxies /api → backend          │
└────────────┬─────────────────────┘
             │ HTTP  :8080 (internal)
┌────────────▼─────────────────────┐
│  Backend   (Go / Echo)           │
│  Port 8080                       │
│  SSE, REST API, Queue service    │
└────────────┬─────────────────────┘
             │ TCP   :6379 (internal)
┌────────────▼─────────────────────┐
│  redis     (Redis 7 Alpine)      │
│  Port 6379                       │
│  Persistent AOF storage          │
└──────────────────────────────────┘
All three containers run on a private clawui bridge network. Only ports 3000, 8080, and 6379 are exposed on the host.

Prerequisites

ToolVersionNotes
Docker≥ 24Docker for Mac or OrbStack
Docker Composev2docker compose (not docker-compose)
Node.js≥ 22Only needed for local dev, not Docker
Go≥ 1.24Only needed for local dev, not Docker

Quick Start

1. Configure environment

cd devops/
cp .env.example .env
# Edit .env — at minimum set OPENCLAW_TOKEN
Key variables:
VariableDefaultDescription
OPENCLAW_ENDPOINThttp://localhost:8000OpenClaw gateway URL
OPENCLAW_TOKEN(required)Auth token for OpenClaw
CORS_ALLOWED_ORIGINShttp://localhost:3000Restrict CORS
FRONTEND_PORT3000Host port for frontend
REDIS_PORT6379Host port for Redis

2. Deploy

./scripts/deploy.sh up
This will:
  1. Build the Go binary (multi-stage Docker build)
  2. Build the SolidStart frontend (node:22-alpine)
  3. Start Redis, wait for it to be healthy
  4. Start the backend, wait for /health to return 200
  5. Start the frontend

3. Verify

./scripts/deploy.sh health
Expected output:
[OK]    Redis
[OK]    Backend health (http://localhost:8080/health)
[OK]    Frontend (http://localhost:3000/)
Open your browser at http://localhost:3000

Startup Sequence

Services start in this strict order (Docker depends_on + condition: service_healthy):
1. redis           → waits until redis-cli ping = PONG
2. clawui-backend  → waits until GET /health = 200
3. clawui-frontend → waits until HTTP 200 on :3000
The backend will not start until Redis is healthy. The frontend will not start until the backend is healthy. This prevents the frontend from serving a broken UI on first load.

Health Check Endpoints

ServiceEndpointMethodExpected
Backendhttp://localhost:8080/healthGET200 OK
Redisredis-cli ping (internal)PONG
Frontendhttp://localhost:3000/GET200 OK

Common Commands

# Start everything
./scripts/deploy.sh up

# Stop everything
./scripts/deploy.sh down

# Restart everything
./scripts/deploy.sh restart

# View all logs (Ctrl-C to exit)
./scripts/deploy.sh logs

# View backend logs only
./scripts/deploy.sh logs clawui-backend

# Check container health
./scripts/deploy.sh status

# Verify HTTP endpoints
./scripts/deploy.sh health

Updating the Application

# Pull latest code, rebuild and restart
git pull
./scripts/deploy.sh restart
Images are rebuilt from source on every up call. Docker layer cache makes rebuilds fast for unchanged layers.

Data Persistence

Redis data is stored in a named Docker volume redis_data. It persists across container restarts and docker compose down. To wipe all data:
docker compose down -v   # removes volumes too

Local Development (without Docker)

For active development, run services individually: Redis (if not using system Redis):
docker run -d -p 6379:6379 redis:7-alpine
Backend:
cd backend/go/clawui
cp .env.example .env   # fill in values
go run ./cmd/server
Frontend:
cd admin/apps/clawui
npm install
npm run dev   # runs on :3001 in dev mode
Note: Dev mode runs on port 3001. The app.config.ts proxies /api to http://localhost:8080 automatically.

Troubleshooting

Backend won’t start — “redis: connection refused”

Redis isn’t healthy yet. Wait 10–15 seconds, or check:
docker logs clawui-redis

Frontend build fails — “Cannot find module”

Node dependencies may be stale. The Docker build handles this, but for local dev:
cd admin/apps/clawui && npm install

Backend returns 500 — “openclaw: connection refused”

OPENCLAW_ENDPOINT is unreachable. Verify the gateway is running and the endpoint URL in .env is correct.

CORS errors in browser

Ensure CORS_ALLOWED_ORIGINS in .env matches the origin your browser uses (e.g., http://localhost:3000).

Port conflict

If port 3000, 8080, or 6379 is in use:
lsof -i :3000
Override ports in .env:
FRONTEND_PORT=3001
REDIS_PORT=6380

Known Issues

IDSeverityDescription
BUG-001CriticalOpenClaw adapter is mock-only; no real AI integration
SEC-001CriticalCORS wildcard — set CORS_ALLOWED_ORIGINS in .env
SEC-002CriticalSSE endpoints have no auth middleware
BUG-011CriticalFrontend does not send idempotency keys on retry
BUG-006HighNo SSE reconnection on stream failure
UAT note: The deployment is functional for testing the UI, content rendering, pinning, and session persistence. Real AI responses require OPENCLAW_TOKEN to point to a working gateway.