Neil Godfrey

Tinley Park · May 18, 2026

Sprint 2026-S01 · Journal and chat launch

sprintproject: digital-twin

2026-S01 · Journal and chat launch

The first sprint — taking neil.godfreylabs.com from idea to live, with a working chat surface backed by a local model and a brief form that lands in Neil's inbox.

Goal

Ship a personal site that the planned Upwork profile video (GL-52) can credibly point at as proof. Chat must actually respond (not be a shell). Brief must actually deliver. End-to-end HTTPS, $0 ongoing cost.

What shipped

  • Site live at https://neil.godfreylabs.com — Astro static, S3 origin, CloudFront, Cloudflare DNS/proxy, end-to-end HTTPS
  • Auto-deploy via GitHub Actions (OIDC role to gl-prod, S3 sync, CloudFront invalidation, host-scoped Cloudflare cache purge)
  • BriefForm — visitors POST to a Lambda → SES email lands in [email protected] with the visitor's email as Reply-To
  • Chat — visitors POST to chat-bridge.godfreylabs.com → Cloudflare Tunnel → Docker chat-bridge container on Mac → host Ollama (qwen3:8b). Origin allowlist + per-IP rate limit + output filter. Knowledge corpus mounted from vault/knowledge/
  • Mood-ring status badge (LIVE / ONLINE / AWAY / RESTING) — manual toggle today, real heartbeat in v2
  • Repo restructured to Smith standard layout: vault/, api/, web/, blog/, mobile/, plus docs/ and .github/workflows/
  • 9 durable Behaviors locked in gl-graph-godmode

What didn't ship

  • v1.1 chat: real declarative LLM responder module + RAG over expanded corpus + streaming. Today's chat is a strong system prompt only.
  • OG image — placeholder still in place
  • Cal.com link uses placeholder URL
  • Self-hosted woff2 fonts — Google CDN today

Retrospective

Worked

  • Specs-before-code discipline saved cycles. ADRs caught architectural drift twice (Lambda vs Function URL, Route53 vs Cloudflare).
  • Behavior nodes in the graph are the right memory primitive. Declarative LLM modules are the right reasoning primitive — not the same layer.
  • Containerizing the bridge meant the chat survives Mac reboots without launchd plumbing.

Didn't

  • Hand-rolled CORS headers on JSONResponse → Content-Length mismatch → silent JSON truncation in the chat. Lost ~30 min to it. Lesson: use framework middleware unless there's a specific reason not to.
  • Smith's first cost estimate didn't account for CloudFront being uncached on the first deploy. Real bill came in well below the conservative ceiling, but the framing felt off.

Next time

  • Wire eval set early so we measure chat improvements with numbers, not vibes.
  • Decide on launchd vs Docker for cloudflared up-front; switching mid- session was a small drag.

Linked

  • #sprint
  • #gl-neil
  • #launch