Local-first CMS engines like
@thekeystatic are amazing until you try to get clever with CI/CD and accidentally break your entire content pipeline.
I’ve been completely caught up in this debugging loop since my last post, but honestly, it was so fun figuring it out (with a ton of help from AI, of course).
I wanted to automate hosting markdown images on Cloudflare R2, so I wrote a Python script in GitHub Actions. The naive plan: scan the markdown on push, upload the local images to R2, rewrite the URLs in the .mdoc files, and delete the local assets to keep the repo clean.
It worked perfectly... once.
Shit got real when I started editing and deleting posts. Absolute chaos. Keystatic's started throwing GraphQL issues because it was looking for local file paths that my script had literally just vaporized.
Had to rip it out and rethink the whole architecture:
• Stop mutating the raw source files in CI (treat them as read-only).
• Create custom Astro <Image/> and <Video/> components.
• Update keystatic.config.ts and Markdoc to parse these new elements, letting the build step handle the CDN mapping dynamically instead of rewriting the markdown files.
Be careful with your CMS schema. Lesson learned.
#buildinpublic #astrojs #webdev #cms #developertalk #blog