Code from the posts
Each of these is generated from the file that actually runs — not pasted from it — so a snippet here cannot drift from the thing it was taken out of. Every one is written up in full on indiecore.net.
-
Static site → Cloudflare Workers with gated GitHub Actions deploys
A build-verify-deploy pipeline on Cloudflare's free tier, and the five traps that cost me an evening — including one that silently takes your staging URL offline.
ci-cd.ymlwrangler.jsonc -
Announce a blog post on LinkedIn from CI — the API script and the workflow
The LinkedIn API call that publishes a post is six lines. The token that expires every 60 days with no refresh, the read scope you cannot have, and a filename that became a dead link took the rest of the afternoon.
linkedin.mjslinkedin.yml -
Build gates for a static site — output verification and a Lighthouse budget
Reading every diff at generation speed isn't review, it's skimming. Here is the 169-line verifier that gates this site, and the bug behind every check in it.
lighthouse-check.mjsverify.mjsRead the code I don't review AI code. My build does. The check that passed while broken Cloudflare injects a beacon. My CSP said no.
-
Responsive image pipeline — Chrome's byte budget, measured sizes, one cache
Improve image delivery" makes two complaints in one panel. Both have exact arithmetic behind them, readable straight out of the JSON report.
image-pipeline.mjsresponsive-markup.mjs -
Accessible image lightbox — focus trap, restore, and the visibility trap
My lightbox was invisible and still in the tab order. Fixing that broke focus handling silently, because focus() on a hidden element reports nothing.
lightbox.csslightbox.js -
Rating puzzle difficulty by the decisions a level forces
Grid size is the obvious difficulty proxy and it is wrong. Measuring the branching factor of the solve gives a rating that survives contact with players.
summarise.jstiers.jswalk.js -
Campaign ordering — difficulty rates a level, progression places it
Sorting a level library easiest-to-hardest gives a campaign that is flat for a hundred stages and then a wall. What replaced the sort.
beats.jsenvelope.jstones.jsRead the code Difficulty rates a stage, progression places it
-
A Vite plugin that shrinks a JSON content pack into the build output
392 levels of JSON, pretty-printed for review and minified for the store. The Vite plugin that does it, and the hook choice that hid a real error.
shrink-stage-pack.js -
Cutting a Capacitor Android download in half — R8, ProGuard and the real delivered size
13.1 MB down to 5.9 MB delivered. R8 is off in the project Capacitor generates, and one library's consumer ProGuard rule was pinning 9,304 classes.
delivered-size.mjsdrop-web-firebase.jsproguard-rules.prorelease-build.gradle -
Conformance suite for generated game content — walk every level before shipping it
Unit-testing the game does not tell you whether the 392 levels in this build are solvable. So the suite plays every one of them.
pack-suite.js -
A mobile game coin economy priced off its own difficulty model
Levels differ 13x in the thinking they demand, so a flat coin reward is wrong on nearly all of them. Tying payouts to the difficulty walk.
economy.js