Blog
SEO and GEO Notes for Freelance Developers: Getting Found by Google and by AI
SEO gets you found on Google; GEO (Generative Engine Optimization) gets you cited when ChatGPT or Perplexity answers "recommend me a developer." How the two divide labor, and what to actually do — using homework I just did on this very site as the example.
Some Thoughts on Using Claude Fable
This blog system, the dragon animation wiring, even this post itself — a lot of it came out of a running conversation with Claude Fable. Notes on what that actually felt like.
Next.js Static Export in Practice: One Codebase, Deployed to GitHub Pages and Vercel
How I turned a Next.js 15 App Router project into a fully static export and published it to both GitHub Pages and Vercel from a single repo — plus the pitfalls along the way.
Putting a 3D Dragon on a Web Page with React Three Fiber: Performance and Mobile Trade-offs
How the flying dragon in my hero section works — compressing a GLB from 32MB to 1.8MB, flight paths, prefers-reduced-motion, and keeping it smooth on mobile.
Think Before You Build: Planning a Landing Page vs. a Corporate Website
Many clients open with 'I need a website,' when what they actually need may be a single page. On goals, content, budget, and maintenance — the essential planning differences between the two.
Built to Work Without Signal: Field Notes on Offline-First PWA Design
Lessons from building the reporting system for Taiwan Trail Stewardship: no signal in the mountains, but an offline-first PWA lets users browse and report anyway, syncing when connectivity returns.
A Web Performance Checklist, Starting from Core Web Vitals
What LCP, CLS, and INP each measure, why Google factors them into search ranking, and the practical checklist I run through on every optimization project.
One Set of Styles for Dark and Light: Driving Your Color Scheme with CSS Variables
No duplicated styles, no JavaScript toggle — extract your palette into CSS variables and let prefers-color-scheme follow the system automatically. This very site works that way.