Skip to main content
Xeffen25
Back to projects
Cloudflare Build Badge

Cloudflare Build Badge

  • Astro
  • Svelte
  • TypeScript
  • Tailwind CSS
  • Cloudflare Workers

Why does this exist?

You know how GitHub Actions gives you that little build status badge for your README? Cloudflare Workers Builds doesn’t. If you sync a GitHub repo to Cloudflare so every commit builds and deploys automatically using Cloudflare Builds instead of GitHub Actions, there’s still no native way to show that status next to your other badges.

I kept running into that gap on Astro projects I host on Cloudflare. Especially for Eminence Astro Starter, another project of mine: shipping a README without a credible build badge felt unfinished. Nothing existing quite fit what I needed, so I built one myself.

What does it do?

It lets you put a live Cloudflare Workers Builds status badge on any GitHub repo, public or private, by deploying your own Worker. That’s the important part: your GITHUB_TOKEN stays on your instance. You’re not handing credentials to a third-party badge service.

Under the hood, each badge request hits the Worker, asks the GitHub Checks API for the latest Cloudflare Workers & Pages check on the branch you asked for (or the default), maps that to a Shields.io badge, and returns the SVG. The URL shape is /{username}/{repository}/status.svg, with an optional branch segment. Shields.io query params (style, logo, colors, cache) pass through; the Worker owns the status color and message.

You can use the live instance or copy the Astro template, set your domain, add a read-only token, and run your own.

How did I build it?

I used my unfinished Eminence Astro Starter as the base, partly to solve the badge problem, partly to dogfood the starter and see what was still missing. It was also a stack I already knew well enough to ship something real.

I could have gone thinner: a Hono Worker that only served the SVG, maybe a bit leaner for that one job. I didn’t. I wanted a proper UI for configuring badges, and I wanted to build it with tools I already use day to day. Same edge runtime for the marketing site and the badge endpoint felt like the right trade-off for a project this size.

Stack

  • Astro 7 on Cloudflare Workers
  • Svelte 5
  • TypeScript
  • Tailwind CSS 4
  • Shields.io
  • GitHub Checks API

The hard parts

I started this back when Astro 3 and Cloudflare Pages were what I was shipping on. AI already existed, but it was not good enough to walk me through this the way it would now, so I had to dig through docs myself.

The first wall was finding where the build status even lived. I went to the Cloudflare API first, because that is where the build was happening. At the time you could trigger builds, not read them. Then I bounced around GitHub: commit statuses, the Status API, deployments. None of it clicked until I landed on Check Suites and realized I could pick out the Cloudflare check by app/slug. Lesson: the status is not always on the platform that runs the build. Sometimes it shows up as a check on the git host, and you have to learn that API surface the hard way.

Once I had the right API, the next problem was reality: repos with lots of checks, pagination, and rate limits. I had to walk pages carefully so “latest Cloudflare build” meant the right check, while making as few requests as possible. When rate limiting still hits, I surface that error instead of pretending the badge is fine. Lesson: edge cases around “which check?” and “how many calls?” are part of the design, not leftovers.

Then Shields.io went down. I had not planned for that. I only noticed when the badge broke in a README. Now those failures fall back to stored SVGs so something useful still shows. Lesson: if you depend on an external renderer, assume it will fail, and decide the fallback before production does it for you.

Along the way I shipped several iterations, including thinner Hono-only attempts. Each one was cleaner and more efficient than the last: messy catch-alls turned into deliberate try/catch paths with accurate error messages. What you see now is the polished result of that path, not the first version that worked.

Impact

Honestly? Right now I don’t know of anyone else using it, so it’s mainly a tool for me. That said, it’s open source under MIT. If you want to use it, or you’ve hit the same gap I did, you can fix it the same way: deploy your own instance and keep your GitHub token on your side.

Links