Source available on GitHub: MrMatt57/MrMatt.io

Design Philosophy

  • Minimal and fast — no JS frameworks, no bloat, static HTML/CSS
  • Content-first — the site publishes writing and serves as a professional presence
  • Zero dependencies — vanilla JS, no npm, no external libraries anywhere
  • Own your stack — static files you control, no platform lock-in
  • Low maintenance — no comment systems, no dynamic backends
  • AI as a collaborator — Claude generates, the human reviews and refines
  • Spec-driven development — plan before you build, every feature documented
  • Automation where it matters — AI and APIs handle the tedious parts so publishing stays frictionless

Static Site

  • Hugo (extended) with PaperMod theme (git submodule)
  • Custom CSS with Roboto Slab typography
  • No npm, no build tools — Hugo’s built-in asset pipeline handles everything

Development

  • Spec-driven workflow — every feature starts with a numbered spec in .specs/ before any code is written
  • Claude Code for interactive development — /feature creates a spec + git worktree, /ship commits, pushes, opens a PR with auto-merge, and cleans up
  • Git worktree isolation keeps the main checkout clean while features are in progress

Serverless Backend

  • Cloudflare Pages Functions (three endpoints)
  • /api/describe-photo — Claude Vision proxy with CORS locked to mrmatt.io
  • /api/oauth-exchange — GitHub OAuth token exchange
  • /api/oauth-client-id — serves the OAuth client ID to the frontend

CI/CD

  • GitHub Actions — builds Hugo with submodules, compiles Cloudflare Functions, and deploys on every push to main
  • Pull requests run build checks before merge, including Pages Functions validation
  • Concurrency controls cancel in-progress deploys when a new push arrives

Hosting & DNS

  • Cloudflare Pages (free tier)
  • Cloudflare DNS
  • Cloudflare Web Analytics — server-side, no JavaScript tag

Security

  • Content Security Policy with deny-by-default baseline (default-src 'none') and SHA-256 script hashes — no 'unsafe-inline' in script-src
  • HSTS with preload, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, and Permissions-Policy
  • CORS locked to mrmatt.io on all API endpoints — API keys stay server-side in Cloudflare encrypted environment variables
  • OAuth CSRF protection via cryptographic state parameter, single-user whitelist authorization
  • CodeQL static analysis on every PR via GitHub Actions
  • security.txt (RFC 9116) for vulnerability disclosure

Automated Publishing

  • GitHub OAuth authentication scoped to the repo owner
  • Upload creates a feature branch (photo/YYYY-MM-DD-slug), commits the image and Hugo content file, opens a PR, and enables auto-merge — all from the phone
  • GitHub REST API for branches, blobs, trees, and commits; GraphQL API for the auto-merge mutation
  • Photo goes from camera roll to live on the site with no terminal, no laptop

Photo Upload

  • Vanilla JS progressive web app at /upload — no frameworks, no dependencies
  • Android share target — share a photo directly from the camera roll to the site
  • Service Worker with network-first caching and cached share-target handoff between the browser and upload page
  • Native EXIF parsing from raw JPEG bytes to extract photo dates — no libraries
  • Client-side image conversion and resizing via Canvas API before sending to AI

AI-Powered Descriptions

  • Anthropic Claude Haiku 4.5 vision model generates photo titles, alt text, and descriptions from uploaded images
  • Cloudflare Pages Function proxies requests to the Anthropic API, keeping the API key server-side
  • Feedback loop — review the AI output, provide guidance, and regenerate until it’s right
  • Structured JSON output parsed directly into Hugo front matter fields