/projects — 2026-04-04

Building my website in Claude Code

in-progress

claude-code

mattcrowl.com — Site Setup

Date: 2026-04-04
Status: Complete — site is live

What Was Built

A personal portfolio site at mattcrowl.com to document AI learning in public. Built for a potential employer audience. Sections:

Tech Decisions

DecisionChoiceWhy
FrameworkAstro 6Built for content/markdown sites, zero JS by default, static output
LanguageTypeScript (strict)Existing preference
HostingCloudflare PagesDomain already on Cloudflare, free tier, auto-deploys on push
ContentMarkdown + Content CollectionsMatches Obsidian workflow, no CMS needed
DesignFull monospace, no frameworkCode-like aesthetic, minimal, fast

Repository

Setup Process

  1. Scaffolded with npm create astro@latest (Astro 6, minimal template, TypeScript strict)
  2. Built content collections for learning, projects, and SOPs
  3. Built Base layout with monospace type system and dark mode
  4. Created all pages with dynamic routes for each content type
  5. Added sample content (transformer explainer post, M365 policy assistant project, M365 offboarding SOP)
  6. Pushed to GitHub, connected to Cloudflare Pages

Gotchas Encountered

Workers vs Pages: Cloudflare’s dashboard combines Workers and Pages. Initially deployed as a Worker, which has a completely different build model. Had to delete and recreate as a Pages project.

main vs master: Astro scaffolds with master branch. GitHub creates repos with main as default. When I edited the README on GitHub it went to main, which had no code. Cloudflare was deploying main. Fixed by force-pushing master to main and renaming the local branch.

NODE_VERSION: Astro 6 requires Node >=22. Cloudflare doesn’t detect this automatically — needed to add NODE_VERSION=22 as an environment variable in Pages settings AND add a .node-version file to the repo.

DNS: mattcrowl.com had two legacy A records pointing to AWS IPs (leftover from a previous hosting setup). These conflicted with Cloudflare Pages custom domain setup. Deleted both — Microsoft 365 MX/SPF/DKIM records were unaffected.

Adding Content

Drop a .md file in src/content/learning/, src/content/projects/, or src/content/sops/ with the appropriate frontmatter, then push. See docs/setup.md in the repo for full frontmatter schemas.

Each SOP page automatically shows a “view source on GitHub” link pointing to the raw .md file. SOPs are intentionally generic (no client-specific content) so the public repo link is appropriate.