Jack Herron provides a surgical dissection of TanStack Start’s rendering versatility, transforming architectural complexity into a clear decision matrix. It is an essential guide for developers seeking to master the nuanced trade-offs of the React Server Components era.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
5 Ways To SSR/RSC on TanStack StartAdded:
now that we have React Server Components and TanStack Start, let's talk about the five different ways to get data onto your page, including SSR, non SSR, RSC, all of the different variations.
Let's get right into it.
Now before we get into it, I'm gonna take a quick digression and just answer something that's been coming up a lot recently.
I'm not sure who needs to hear this, but React Server Components were not the first time that React did server-side rendering, not by a long shot.
React has always had server-side rendering even before NextJS.
In fact, it's a pillar of the React architecture, that it is isomorphic, meaning that React can render in both the server context and in the client context.
And that has been since day one.
Next came around because before Next everyone was using their own DIY bespoke versions of SSR.
Next, just standardized those with what they're now calling the "Pages Router" and then added RSC support with what they're now calling the "App Router".
But at every point along that line, React has always been capable of being server-side rendered.
It was just a question of how you want to do that server side rendering.
So let's talk about the five different ways that you can do them with TanStack Start.
Starting off with not at all the client side rendering version.
So here is our example.
It's five different ways to go and get the Pokemon list from the Pokemon API.
You're not gonna see any difference in terms of the UI really, other than just explanations of what's going on.
So what's interesting with the client side rendering version is that the request to the Pokemon API is made off of the client in a classic Single Page Application or SPA way, but it's incredibly clean in TanStack Start, as you'll see.
Here is the "ssr-variants" project code.
All of this is available to you for free in GitHub and the link in the description right down below.
Of course, the index page simply has links to all of the variants.
The one that we're looking at right now is the CSR page, and the critical component here is we've set SSR to false.
That means that TanStack Start is not going to server side render this page.
It's only going to send the code for the page out to the client, and the client is gonna do all the work.
Now what happens here is that the TanStack Router then kicks in and the loader is fired, when the page first starts up, that loader goes and makes the fetchTopPokemon from the API.
And then the page component, in this case, CsrPage uses Route.useLoaderData to just go and get that Pokemon data that the router has choreographed in terms of loading this route.
So it doesn't really matter if this is a hard nav or a soft nav to this page.
The effect is always gonna be the same.
The router is gonna manage getting the data from the loader before it actually renders the page.
All right.
Now let's talk about the server side rendered version to this.
So if I go over to "Server-side rendering" here, we're not actually going to server side render.
That's actually a SPA nav between those two things.
And in that case, TanStack Start is going to do exactly what we did with CSR, but just call it SSR.
That's a feature that's not a bug If you do a hard nav, like what I'm gonna do now by refreshing the page, you can see over here, if we look at the page source, we can do a find.
"Bulbasaur" and it appears in the HTML.
So it is rendering on the server and then passing it off to the client, and the client is actually going to do another re-render on the page.
That's really important to know.
That is the standard react hydration cycle, and it happens when you're not using RSCs.
So when you look at the RSC variants coming up, those are only ever going to render on the server and then get sent down to the client.
All right, now let's go take a look over at the code.
In this case, you might take a look at "ssr.tsx", and in this case, "ssr" is true, which is also the default.
So you don't need to necessarily put that on there, but check out how we're doing the loader and the getting of the Pokemon.
It's exactly the same between those two.
How cool is that?
Now there's another SSR variant called "data-only", and we actually had this before we had RSC.
This is really cool, especially if you're doing something like a dashboard.
Let me show you.
So if I go back here to the homepage and I go to "Data-only SSR", and again, I do a hard refresh.
You can see that there's a slight flash here as it brings in the data.
So what's actually happening?
Well, again, if we look at the page source.
We can see that we have no HML for bor, but we do have data for Bulbasaur, so the data is being fetched on the server, then being sent down to the client for rendering, and that's why you see that little flicker there.
Is that the server is getting the data, it's sending it down to the client, and then the client is the only place that's actually doing the rendering.
Again, super handy for something like a dashboard where you don't want to go and CDN cache the contents of the page, but you do want to get data off the server, probably more securely than off the client and then pass it down to the client for rendering.
So let's take a look at the code for this.
Again, exactly as we had before, but in this case we're just saying SSR data only, but it's exactly the same code otherwise.
All right, now let's talk about React Server Components or RSC support in TanStack Start.
So the first thing you need to know is that I've enabled RSC support by bringing in the ViteJS plugin for RSC, and then simply enabling RSC on the TanStack Start Vite plugin.
Super easy.
Let's go take a look at the page and we'll try out "RSC - renderServerComponent".
So this is using the RSC low level API.
TanStack Start actually has two ways of doing RSC.
You can do them in combination.
You can do one or the other, or you can not use any RSC at all.
Totally up to you.
All the options are open.
Let's go take a look at how this is done.
So we'll go over here to "rsc-renderable.tsx".
And we can see that we have a new component at the top of the page, PokemonServerList.
And importantly, it's an async component.
Just like you'd have in the NextJS App Router.
We're gonna go and await fetchTopPokemon.
Super easy way to go and get your data in here.
Then we render those top Pokemon.
And that server function uses renderServerComponent with that component.
Just JSX, like you'd expect.
And that gets back a renderable.
We're gonna return that as PokemonList.
And then you can start to see where this intersects with the architecture that we had before, we're using the same loader like we had before.
SSR is true, and we are getting that Pokemon e, we're turning that as loader data, and then we break that out in our page, we get PokemonList back, and then we just simply drop that into our JSX wherever we want it.
It's just a remarkably clean and simple architecture.
Now if we go back to the route definition again, think about what the loader is doing here.
It's just getting Pokemon renderable.
It could actually go and get other data.
It could render other RSCs.
Whatever you want, you can go and just have as much of a combination of architecture as you want in that loader, and TanStack Start gonna do all of the work of coordinating all that.
Now let's take a look at our final fifth version of this, and that is the Composite Component version.
So I'll go over here to "RSC - createCompositeComponent", and as you can see exactly the same output as that we have before.
But what in this case we're doing is we're returning a shell of a component to the page, and then the page can go and actually slot in dynamic components.
In this case, we've created.
Client slot where that composite component can go and take interactive components.
So when you think about how you might want architecture, like a page shell, that's where you want to think about this.
RSC composite API, that is unique and specific to TanStack Start.
Let's take a look at the code.
Over an "rsc-composite.tsx" We can see again the PokemonServerRows, just like we have before.
An async function.
Now in this getPokemonComposite server function.
We call that createCompositeComponent and give it a component.
This component is actually defined right here.
It defines the shell of the layout and then takes any children and pops 'em in there wherever you want.
You can also have as many slots as you want defined on these composite components.
So you can have like a call to action section or an ad section or however you wanna lay out your shell.
Then down on the createFileRoute, again, we're calling that loader.
If you haven't noticed, loaders are really important here.
We grab, in this case, the "src" for the composite component, and then we pass that to the CompositeComponent component as "src", and then we give it any kind of slots we have.
In this case we have the children slot, so we just drop in a paragraph tag and that's what would go in there.
If you have interactive components, those can go in there and you don't need to use "use client".
But I'll get into more of that in another video where we really drill down into the differences between the Low Level API and the Composite Component API, and how and when we want to use those two.
In the meantime, I hope this is giving you a nice overview of how TanStack Start manages server side rendering and RSCs and five different combinations of the above.
If you have any questions or comments, be sure to put that in the comment section right down below.
In the meantime, if you like this video, hit that like button.
If you really like the video, hit the subscribe button and click on that bell.
You notified the next time new Blue Collar Coder comes out.
Related Videos
VALORANT's Latest 'Exclusive' Tier Bundle is Rough...
KangaValorant
17K views•2026-05-28
Flight Attendant Mocks Poor Looking Black Woman — Mid Air Announcement Exposes Her Real Power
SkyboundStories-b4r
184 views•2026-05-28
I FIXED My Friend’s Blown Turbo RX-8… Then Sold It
Cameron-RX8
134 views•2026-05-28
NewsWatch 12 at 5: Top Stories
NewsWatch12
1K views•2026-05-28
Simon Jordan & Danny Murphy deliver PREDICTIONS for Arsenal's Champions League FINAL with PSG
talkSPORTArsenal
6K views•2026-05-28
Botting is OUT OF CONTROL in Classic WoW (Again)...
SolheimGaming
108 views•2026-05-28
The "AI Job Apocalypse" is CANCELLED!
WesRoth
9K views•2026-05-28
STREET FIGHTER 6 - INGRID Story Walkthrough @ 4K 60ᶠᵖˢ ✔
RajmanGamingHD
12K views•2026-05-28











