# Hatch.surf Architecture

## Overview

Hatch.surf is the landing page and brand site for El Foundation. It consists of:
- **Static frontend** (site/) — HTML/CSS/JS served via nginx
- **Go backend** (cmd/hatch) — API server for future dynamic features

## Deployment Architecture

```
GitHub Push → GitHub Actions → Build Docker Image → SCP to Server → Docker Run → Caddy (reverse proxy)
```

**Benefits:**
- Containerized — isolated from host
- Reproducible — same image in dev/prod
- No host filesystem dependency (no `/var/www`)
- Easy rollback — just change image tag
- Self-contained — static files baked into image

## Docker Setup

### Frontend (site/)

**Dockerfile:**
```dockerfile
FROM nginx:alpine
RUN rm -rf /usr/share/nginx/html/*
COPY . /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
```

**docker-compose.yml:**
```yaml
services:
  hatch-homepage:
    build: .
    ports:
      - "3000:80"
    restart: unless-stopped
```

Note: Static files are baked into the image during build. No host mount required.

### Backend (cmd/hatch)

**Dockerfile:**
```dockerfile
FROM golang:1.25-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . ./
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /bin/hatch ./cmd/hatch

FROM scratch
COPY --from=build /bin/hatch /bin/hatch
EXPOSE 8080
ENTRYPOINT ["/bin/hatch"]
```

**docker-compose.yml:**
```yaml
services:
  hatch:
    build: .
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:8080"
    volumes:
      - hatch-data:/data
    environment:
      - HATCH_PORT=8080
      - HATCH_DB_PATH=/data/hatch.db
      - HATCH_BASE_URL=${HATCH_BASE_URL:-http://localhost}

  caddy:
    image: caddy:2-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy-data:/data
      - caddy-config:/config
    environment:
      - HATCH_HOSTNAME=${HATCH_HOSTNAME:-localhost}
    profiles:
      - with-caddy

volumes:
  hatch-data:
  caddy-data:
  caddy-config:
```

## Deployment Flow

### GitHub Actions (deploy-site.yml)

1. **Build** — `docker build -t hatch-homepage:latest ./site`
2. **Save** — `docker save hatch-homepage:latest | gzip > hatch-homepage.tar.gz`
3. **SCP** — Copy tarball to server
4. **Load** — `docker load < /tmp/hatch-homepage.tar.gz`
5. **Run** — `docker run -d --name hatch-homepage ...`

### Server Configuration

**Nginx reverse proxy** (host nginx):
```nginx
server {
    listen 80;
    server_name hatch.surf;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name hatch.surf;

    ssl_certificate /etc/letsencrypt/live/hatch.surf/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hatch.surf/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

## Secrets Management

- **DEPLOY_HOST** — Server IP/hostname
- **DEPLOY_USER** — SSH user (nara)
- **DEPLOY_KEY** — SSH private key (stored in GitHub Secrets)

No secrets in repo. All deployment credentials in GitHub Secrets.

## Rollback Procedure

If deployment fails:
```bash
# On server
docker stop hatch-homepage
docker rm hatch-homepage
docker run -d --name hatch-homepage --restart unless-stopped -p 127.0.0.1:3000:80 hatch-homepage:previous-tag
```

## Future Improvements

1. **Container registry** — Push images to GitHub Container Registry (ghcr.io)
2. **Health checks** — Add HEALTHCHECK to Dockerfile
3. **Monitoring** — Add Prometheus metrics endpoint
4. **CDN** — Serve static assets via Cloudflare/CloudFront
5. **SSL automation** — Certbot in container or Caddy auto-SSL
