#seo
Japanese OG Images with Satori: The 5 MB Font You Never Ship
Satori draws CJK text only if you hand it a font that has the glyphs — and it fails silently when you don't. Measured numbers for Noto Sans JP: subset size, weight pairing, per-card cost, and why the 5 MB never reaches the CDN.
Do AI Crawlers Render JavaScript? What GPTBot Actually Sees
GPTBot, ClaudeBot, and PerplexityBot read raw HTML and never run your JavaScript. How to test what AI crawlers see, and when client-side rendering costs you.
Astro i18n Without a Plugin: Bilingual Content Collections
How I added Japanese to this blog with no i18n plugin: locale folders in one collection, translation pairing by slug, hreflang, and a typed UI dictionary.
Cloudflare Workers Redirects: The _redirects File
No Worker code required — a plain-text _redirects file handles 301s on Workers static assets. Syntax, splats, limits, and the trailing-slash gotcha that bit me.
How to Add llms.txt to an Astro Site (Generated, Not Hand-Written)
Generate llms.txt and llms-full.txt from Astro content collections so they never go stale — endpoint code included, and an honest look at whether anything reads them yet.
Astro Structured Data: The JSON-LD Google Still Uses
FAQ rich results died in May 2026, HowTo in 2023. The structured data that still earns you something, and how to emit it from Astro content collections.
Auto-Generate Open Graph Images in Astro with Satori
Generate a 1200x630 OG image for every post at build time — no headless browser, no runtime cost. The full Astro + Satori setup, font gotchas included.
Fixing Web Font LCP in Astro: PageSpeed 83 → 99
Inlining the stylesheet was the easy win. The real problem was preloading fonts to hide a layout shift — and the metric overrides that fixed LCP instead.