[{"data":1,"prerenderedAt":60},["ShallowReactive",2],{"cms-projects-static-wordpress":3,"cms-projects":26},{"title":4,"excerpt":5,"slug":8,"rawDate":9,"date":10,"modified":11,"content":12,"readingTime":13,"acf":14,"tags":23,"author":24,"featuredMediaUrl":25,"featuredMedia":25},"Serverless WordPress",{"raw":6,"plain":7},"\u003Cp>WordPress&#8217;s editor without a WordPress server. The editor runs in your browser with WordPress Playground, and Cloudflare stores the content and rebuilds the static site.\u003C\u002Fp>","WordPress’s editor without a WordPress server. The editor runs in your browser with WordPress Playground, and Cloudflare stores the content and rebuilds the static site.","static-wordpress","2026-11-02T09:00:00",["Date","2026-11-02T00:00:00.000Z"],["Date","2026-11-03T00:00:00.000Z"],"\u003Cp class=\"wp-block-paragraph\">I like writing in WordPress’s block editor, but I didn’t want to pay for, patch and secure a WordPress server for a site that’s read far more often than it’s written. With static-wordpress, WordPress only exists while I’m editing. This site and its CMS run on it.\u003C\u002Fp>\n\n\n\n\u003Ch2 class=\"wp-block-heading\">How it works\u003C\u002Fh2>\n\n\n\n\u003Cul class=\"wp-block-list\">\n\u003Cli>Opening the CMS boots \u003Ca href=\"https:\u002F\u002Fwordpress.org\u002Fplayground\u002F\" target=\"_blank\">WordPress Playground\u003Cpicture>\u003Cimg decoding=\"async\" loading=\"lazy\" width=\"16\" height=\"16\" src=\"\u002Fcdn-cgi\u002Fimage\u002Fformat=auto,quality=80,fit=scale-down,width=32\u002Fimg\u002Ffavicons\u002Fwordpress.org.png\" alt=\"wordpress.org favicon\">\u003C\u002Fpicture>\u003C\u002Fa>, which is WordPress and PHP compiled to WebAssembly, in the browser and restores the last saved snapshot.\u003C\u002Fli>\n\n\n\n\u003Cli>Saving stores a database snapshot in \u003Cstrong>Cloudflare D1\u003C\u002Fstrong> and media in \u003Cstrong>R2\u003C\u002Fstrong>, then triggers a \u003Cstrong>Workers Builds\u003C\u002Fstrong> run of the site.\u003C\u002Fli>\n\n\n\n\u003Cli>At build time, a Nuxt module reads a token-protected content feed from the CMS Worker and prepares the posts, images and sitemap.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\n\n\u003Cp class=\"wp-block-paragraph\">Between edits, nothing runs except Cloudflare’s storage.\u003C\u002Fp>\n\n\n\n\u003Ch2 class=\"wp-block-heading\">What went into it\u003C\u002Fh2>\n\n\n\n\u003Cul class=\"wp-block-list\">\n\u003Cli>An editing lock, so two open tabs can’t overwrite each other’s snapshot.\u003C\u002Fli>\n\n\n\n\u003Cli>Custom fields defined in config that become native WordPress metaboxes. The links and tech stack on this page come from them.\u003C\u002Fli>\n\n\n\n\u003Cli>Importing a WordPress backup or WXR export, which is how this site’s existing posts moved over.\u003C\u002Fli>\n\n\n\n\u003Cli>Two TypeScript packages in a pnpm monorepo, with tests, released to GitHub Packages with changesets, and prereleases from every branch.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\n\n\u003Ch2 class=\"wp-block-heading\">Built with\u003C\u002Fh2>\n\n\n\n\u003Cp class=\"wp-block-paragraph\">TypeScript, Cloudflare Workers, D1, R2, Workers Builds, WordPress Playground and Nuxt.\u003C\u002Fp>\n\n\n\n\u003Cp class=\"wp-block-paragraph\">\u003C\u002Fp>",2,{"project_url":15,"github":16,"icons":17},"","https:\u002F\u002Fgithub.com\u002Fjoebailey26\u002Fstatic-wordpress",[18,19,20,21,22],"PHP","WordPress","Cloudflare","Nuxt","TypeScript",[],"Joe",null,[27],[28,35,48],{"title":4,"excerpt":29,"slug":8,"date":30,"modified":31,"readingTime":13,"acf":32,"tags":34,"author":24,"featuredMediaUrl":25,"featuredMedia":25},{"raw":6,"plain":7},["Date","2026-11-02T00:00:00.000Z"],["Date","2026-11-03T00:00:00.000Z"],{"project_url":15,"github":16,"icons":33},[18,19,20,21,22],[],{"title":36,"excerpt":37,"slug":40,"date":41,"modified":42,"readingTime":13,"acf":43,"tags":47,"author":24,"featuredMediaUrl":25,"featuredMedia":25},"Turnstile protected static forms",{"raw":38,"plain":39},"\u003Cp>Spam-protected website forms without a form service. A Cloudflare Worker checks Cloudflare Turnstile and emails each submission, and Vue composables handle the form.\u003C\u002Fp>","Spam-protected website forms without a form service. A Cloudflare Worker checks Cloudflare Turnstile and emails each submission, and Vue composables handle the form.","turnstile-forms",["Date","2026-10-30T00:00:00.000Z"],["Date","2026-11-03T00:00:00.000Z"],{"project_url":15,"github":44,"icons":45},"https:\u002F\u002Fgithub.com\u002Fjoebailey26\u002Fturnstile-forms",[46,20,22],"Vue",[],{"title":49,"excerpt":50,"slug":53,"date":54,"modified":55,"readingTime":13,"acf":56,"tags":59,"author":24,"featuredMediaUrl":25,"featuredMedia":25},"TV Shows Tracker",{"raw":51,"plain":52},"\u003Cp>A web app that tracks the TV shows I watch, emails me when a show is renewed or cancelled, and adds new episodes to my calendar. I first built it in 2020, then rebuilt it with Nuxt on Cloudflare.\u003C\u002Fp>","A web app that tracks the TV shows I watch, emails me when a show is renewed or cancelled, and adds new episodes to my calendar. I first built it in 2020, then rebuilt it with Nuxt on Cloudflare.","tv-shows",["Date","2020-05-10T00:00:00.000Z"],["Date","2026-11-03T00:00:00.000Z"],{"project_url":15,"github":57,"icons":58},"https:\u002F\u002Fgithub.com\u002Fjoebailey26\u002FTV-Shows",[46,20,21,22],[],1793734936954]