hatch-surf/docs/ARCHITECTURE.md
Riley Zhang 26c9044377 feat(site): integrate landing page redesign source code into repository
- Update deployment scripts to use Docker with static files baked in
- Remove host volume mount in favor of self-contained Docker image
- Add verification script to ensure correct content is deployed
- Update documentation to reflect new deployment architecture
- Ensure build process produces correct output without manual copying

Closes ELF-268

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-25 03:41:14 +02:00

3.8 KiB

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:

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:

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:

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:

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. Builddocker build -t hatch-homepage:latest ./site
  2. Savedocker save hatch-homepage:latest | gzip > hatch-homepage.tar.gz
  3. SCP — Copy tarball to server
  4. Loaddocker load < /tmp/hatch-homepage.tar.gz
  5. Rundocker run -d --name hatch-homepage ...

Server Configuration

Nginx reverse proxy (host 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:

# 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