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/, plusdocs/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
- Plane: GL-67 (parent), GL-52 (video, not yet)
- Daily logs: 2026-W19
- Repo: GodfreySolutions/gl-neil
