I run my blog on Substack, but I wanted a place I can control. Something minimal, calm, and pleasant. It was also the perfect excuse to finally try TanStack Start (now in RC stage), something I’ve been postponing for a while because I assumed the beta label meant pain. You can check it here.
Next.js vs TanStack Start: mental models
I’ve been working with Next.js for three years, and I know its quirks, and I also know how quickly its mental model can get convoluted when you mix server and client concerns.
In Next.js, the model is more implicit: everything starts as a server component, until you hit a `use client` boundary, and from that point down the tree, everything is a client component. That sounds fine until you realize a component deep in that client tree now needs database data. Then you’ll start refactoring: pulling data fetching back up to the nearest server component, drilling down props and restructuring your component to fit the framework constraints. That always felt wrong.
Start approach is more straightforward: you mark what’s server-only, and keep the rest flexible. You don’t have to reorganize your whole tree when requirements change.
Two “aha” moments: cheerio and caching
The core of the blog is the `cheerio` library. It parses the HTML Substack returns and turns it into something I can render. It worked great, but it’s a heavy library, and I was sending it to the client on every page load. Fixing that was boring: I moved the parsing into a server function and sent already-formatted data to the client. No big refactor, same code, just in the right place.
The other win was caching. In Next.js, caching always felt a bit magical, and it was not always obvious what was actually happening.
TanStack Start uses TanStack Query for data fetching. I don’t post often, so I leveraged that to set an aggressive `staleTime` (a win for procrastination). I bumped the value, and that was it. I know exactly how long the data is fresh, and the navigation now feels instant.
So what?
TanStack Start has been win after win: it works, and makes my life easier.
The setup is straightforward, and you’ll feel at home if you already use Router and Query. It just works.
If you’re used to building SPAs, it will feel familiar, with the server part adding very little extra complexity. And if you come from Next.js, you might be surprised at how simple things are: no more magic, no mental gymnastics, no more twisting your code around to please the framework.