Dan Shipper's personal site. Plain HTML + CSS, no framework, built for humans and answer engines.
site/— hand-authored pages (home, press shell), styles, fonts, robots/llms/faviconcontent/— data:writing.json(selected essays),timeline.json,press.json(coverage list),facts.json(verified bio facts + sources),wp-*.json(scraped WordPress export),wp-assets/(mirrored legacy images)scripts/build.mjs— assemblesdist/: injects lists into pages, regenerates all ~109 legacy blog posts at their original URLs, builds the archive index, sitemap, and llms-full.txtscripts/check.mjs— verifier: internal links, curated external links, JSON-LD validity, one-h1 rule (--externalfor the full sweep)scripts/og-card.html— source forsite/og.png(screenshot at 1200×630)
node scripts/build.mjs # build dist/
node scripts/check.mjs # verify (add --external for link sweep)
python3 -m http.server 4173 --directory distHosted on Vercel (vercel.json holds redirects from old WordPress paths). Push to main → auto-deploy, or vercel --prod.
Change the JSON in content/ (or the HTML in site/), rebuild, push. The legacy archive (2011–2016 posts) is preserved verbatim — don't edit those posts, they're historical record.