Back to Blog
3 min read

Building PodCheck: A Podcast RSS Feed Validator

Why I built a free RSS feed health checker for podcasters, how it works under the hood, and what I learned shipping a focused Laravel side project.

Laravel PHP Side Project Open Source

I’ve spent years working on podcast infrastructure at Castos, building feed delivery, enclosure handling, and all the messy details that make podcasts work across platforms. One thing I kept running into was how often feeds had subtle issues that silently caused problems: missing artwork, incorrect durations, malformed GUIDs, descriptions just slightly too long for Apple Podcasts to display correctly.

There was no quick, free tool that gave you a clear picture of your feed’s health. So I built one.

What PodCheck Does

PodCheck takes a podcast RSS feed URL and runs it through 14 validation checks across two levels: channel and episodes. It produces a 0–100 health score broken into three categories:

  • Compliance: does your feed meet Apple Podcasts, Spotify, and Google Podcasts specs?
  • Technical: are enclosures, GUIDs, and publication dates well-formed?
  • Best Practices: are titles and descriptions optimized for SEO and discoverability?

Reports are cached for an hour and shareable via a unique URL, so you can send a feed check to a client or colleague without them having to re-run it.

Why Laravel

This was a deliberate choice. Laravel is what I reach for when I want to move fast without sacrificing structure. The RSS parsing, validation pipeline, scoring logic, and HTTP layer all fell into place quickly.

The architecture is straightforward: a FeedFetcher retrieves and parses the XML, a FeedValidator orchestrates the checks, and a HealthScorer calculates weighted scores per category. The FeedReport model handles persistence with unique slugs for shareable links.

I also used Alpine.js for the frontend interactivity and Tailwind CSS 4 for styling, a stack I’ve used enough that the UI didn’t slow me down.

Shipping With Confidence: 335+ Tests

One of my goals with this project was to treat it like production software, not a side project that “works on my machine.” I wrote 335+ unit tests with Pest PHP covering every validator and scorer.

This paid off immediately. Several edge cases I discovered while writing tests (empty episode arrays, feeds with no explicit language tags, artwork URLs returning redirects) would have caused confusing report results without test coverage catching them first.

Deployment

The app is containerized with a multi-stage Docker build and deployed on Railway. DNS is handled via GoDaddy pointing to the Railway domain. The whole infrastructure is simple enough to reason about but solid enough to handle real traffic.

What I Learned

A few things stood out from this build:

Scope discipline matters. I had ideas for user accounts, historical tracking, and email reports. I shipped none of them. The core value is the instant analysis; everything else is noise until people are actually using it.

RSS is messier than you’d expect. The spec is loose, platforms interpret it differently, and real-world feeds do genuinely bizarre things. Robust error handling in the fetcher and parser saved me from a lot of hard-to-reproduce bugs.

Open source from day one. The repo is public. I wanted other developers to be able to learn from it or contribute, and having it open keeps me honest about code quality.

If you run a podcast, check your feed. It’s free and takes about five seconds.