Routes.yaml made easy(-ier?)
Did I make it easier? Not sure.

It's been a long couple months of building things for other people. (Profitable, but long.) This weekend, I took a little break and built a routes editor, because I felt like it. (I'd like to say I built it for me, but no, I can crank out raw .yaml as fast as I can get my LLM auto-complete to get out of the way. I built it because I wanted to build something.)
Routes.yaml is a Ghost super-power. It's super useful for grouping content in various ways, with pagination and rss feeds built in. I've written about it before:


You might also want to read the official docs, here:
Despite all the documentation, ghost routing seems to give lots of folks headaches, and non-coders perceive writing a routes.yaml
file as "coding", and therefore not something they're willing to do. 🤷♀️ So, I attempted to write a tool that was powerful enough to handle a variety of interesting routing cases, while maybe easy enough to use to help the non-coders make it work. Did I succeed? I'm honestly not sure.
It presently lives at https://sws-routes-builder.netlify.app/, and I'd love for you to try it out and let me know what you think!
A few caveats and notes:
- Some themes make #get requests, particularly on the homepage, rather than using routing, for a variety of good and bad reasons. (I'm looking at you, Source.) Currently, Ghost #get requests completely ignore routing. So if nothing is working, consider the possibility that your theme isn't using your routing, not that your routes file is wrong. Maybe that will change in the future? I had a fun conversation with Hannah about it the other day, but talk is cheap and code isn't.
- There are valid filters that my editor just doesn't handle. I'm not doing nested logic or cases where you want to require a post to have BOTH two tags (instead of either of two tags), or cases where separate types of filters should be joined with OR instead of AND. I thought about it. I decided that the folks who could articulate and create that level of complexity in any editor I could create would probably be happier writing a routes.yaml.
- I've added some validation and hints, but you can still probably get it to write something invalid or not what you intended. Edge case examples appreciated.
- I wanted my brand purple for the background, but I don't love the crayon-box-explosion that resulted. Sorry. 🙈 I should probably just stick to Tailwind colors next time.
Questions
- I'm interested in having more templates available. What should I add? Should I collect the routes files for custom themes and make them available here?
- Would it be useful if I read your theme's templates (from a theme.zip or API key) and made the template fields be dropdowns?
- Similarly, would it be useful to have a dropdown for the data field with your site's actual page/post/tag/author slugs? (That would require an Admin API key.)
- If I had Admin API access, I could actually tell you how many posts would appear in each channel and collection. That seems like it could be really useful for debugging.
- It's possible to filter by date. Does anyone do that? This was one of those things that felt like maybe it was just cluttering up the options, so I didn't include it. [But then I included an RSS checkbox, so maybe I'm not entirely internally consistent.]
- If you were giving me your API key anyway, would you want a button that would actually upload your routes.yaml for you?
The technical bits
- I built it in React. State was a pain, because it always is, and there's a heck of a lot of it here.
- Currently there's no back-end. Your data is persisted using LocalStorage only.
- It's on Netlify because I'm lazy. 😄
- My current LLM coding helper of choice is Claude Sonnet 4, running in Cursor, for those curious. Did it help? Yes. Did it get in the way? Yes. [In one amusing moment, I asked it to split the now 2000+ line codebase out of the singular .jsx file. It did create some new .jsx files with code duplicating my main.jsx file. It utterly failed to actually delete that code from the main.jsx file, or to import from the new files created, or to set up imports in the new files created, such that I spent a while playing whack-a-mole with import errors.]