LongCut logo

Fixing React full-stack with zero-syntax type safety | by Tanner Linsley, creator of React Query

By React Conferences by GitNation

Summary

## Key takeaways - **Zero-Syntax Type Safety**: TanStack Start infers types from your application code with zero type annotations, making it safer than annotated TypeScript despite no syntax, foolproof for any skill level. [02:49], [03:11] - **Client-First Full-Stack**: TanStack Start behaves like a single page app with SSR on first request then SPA, preserving the simple SPA mental model while weaving in server capabilities if needed. [04:55], [05:10] - **Router is 90% of Framework**: TanStack Start is 90% TanStack Router, inheriting its unique type safety and developer experience that upgrades any web app across frameworks. [06:12], [06:30] - **Isomorphic Code by Default**: All code runs isomorphically on server during SSR and client during navigations; use server functions for server-only logic via RPC from client. [13:05], [13:36] - **End-to-End Type-Safe Links**: Links and search params are fully type-safe; IDE complains if missing required params or wrong types, ensuring correctness across routes. [15:42], [17:36] - **Meta-Framework Fatigue Critique**: Meta-frameworks demand mental model changes, refactors, and breaking updates like RSCs with little pragmatic benefit, making simple apps harder. [18:39], [19:09]

Topics Covered

  • TypeScript without annotations
  • Client-first full stack
  • Isomorphic code by default
  • Type-safe links everywhere
  • Meta-frameworks demand too much

Full Transcript

That's uh that's my new picture, by the way. Um I don't look anything like I did

way. Um I don't look anything like I did about a year ago, which is a good thing.

Things are going well. Um so today marks um 18 months that I've been sustainably working full-time on open source at

Tanstack, which is pretty crazy. So, I

uh I never expected that I would my full-time job would be this. And I'm not going to lie, I love it. It's it's a dream come true. So, hopefully you've heard of Tanstack. If you haven't, it is

an open- source organization responsible for some of uh what I would call the greatest libraries, especially for the React ecosystem. Um and recently we have

React ecosystem. Um and recently we have been building something that we're very excited about. It's called Tanac Start.

excited about. It's called Tanac Start.

Obviously, it's the name of the talk.

Um, and Tanax Dart is quickly becoming a great way to build all kinds of apps.

Uh, whether that's dynamic server driven websites, full stack, client side, spas, even static sites, um, and whatever you want to throw at it with vibe coding.

It's it's pretty versatile and I'm going to do my best today to show you how it works and why we're really excited about it. So, first of all, um this new

it. So, first of all, um this new framework, like all of our other libraries, are not just written with TypeScript, but they're designed to be type safe from the ground up. And it's

really painful that I have to keep saying this, but uh those two things are not the same. Um to explain this, I would like to briefly help you understand the status quo of writing

type- safe code for the web.

uh even when using like your favorite popular TypeScript libraries out there, this is common syntax to see all over your application with ZTEX annotations

basically. And uh they're just about

basically. And uh they're just about everywhere in your code. And

unfortunately, this experience typically defines learning and using TypeScript for most of us JavaScript engineers.

It's not very fun. Um writing and maintaining all these type annotations everywhere. It takes a lot of effort.

everywhere. It takes a lot of effort.

It's repetitive. Um, it's errorprone because it's optional. It's forgettable

because, uh, if you decide to give up, you can just not do it and bypass it.

Uh, and to me, that is a one-way street to bugs, eventually burned out developers, um, and eventually a a very real strain on your end users. So, I'd

like to show you the same code. Uh, this

code, this is code that works. Um, I

redacted some of it, but I I want to show you how it could be designed um to be fully type safe.

So, believe it or not, this is also TypeScript. Um, and it's even safer than

TypeScript. Um, and it's even safer than that last version that I showed you, despite there being zero type syntax in any of the code.

So at Tanstack, we had spent a long time, years researching and perfecting our ability to infer the types out of your application code and business

logic. And the result is actually less

logic. And the result is actually less code that we just saw. Um, but it's also safe by default. Uh, it doesn't take any effort no matter what your skill level

is. So whether you're an expert or a

is. So whether you're an expert or a junior or you're just learning. Um, and

this makes it foolproof because um, type safety isn't something you want to have to think about. Uh, so this this ultimately allows you and your team and

and even like your AI agents to actually get back to building stuff instead of worrying if it's going to run in production. Um, and when it turns out

production. Um, and when it turns out when you lean into this type safe first design, uh, it pays dividends the the more that you invest into it. So it

makes all things e these things easier.

Uh building new features, fixing bugs, refactoring, uh pivoting everything in your entire application. Um with full type safety and tools that are designed for it, you have as much reassurance as

you possibly can that nothing's going to break.

So type safety alone makes start a very compelling choice of web framework. it

it makes it extremely different already out of the out of the box from everything else you've ever used and it's really difficult to explain that.

You kind of have to experience it. So if

you hear people being like oh tack start and type safety and you're like why are you excited about this? Go and try it out and experience it and you might understand why. Um but also it's uh it's

understand why. Um but also it's uh it's uniquely client first. And this is weird because five or six years ago, I wouldn't even had to have said this, but we've been obsessed with the server uh

very much so over the last couple of years. So now I have to say it's a

years. So now I have to say it's a client first full stack framework. Uh

what does that actually mean? It means

that it behaves like a single page app.

Um it shouldn't be anything uh revolutionary, but single page app uh we've been doing this for the last decade, right? You get to keep reasoning

decade, right? You get to keep reasoning about this really simple mental model.

It's SSR on the first on the first request and after that it turns into an SPA. Um, we've been refining this model

SPA. Um, we've been refining this model for the last decade. Um, and only recently have we been doing these big shifts back to the server, which is cool for some aspects. I mean, we just heard

Amy talk about how awesome Redwood is.

Um, and Nex.js and React Router and everybody's talking about the server.

I've been building apps for the last 10 years that have been spas and I don't necessarily want to leave behind all that hard work that we've done over the last decade. So the idea is that you get

last decade. So the idea is that you get to keep the libraries and the patterns and the speed of the existing SPA ecosystem that we've been investing into for so long. But now with one massive

difference, you have this ability to weave in serverside capabilities if and when you need them. And that if is very important. Um, TANSAC start is able to

important. Um, TANSAC start is able to do this first of all because it's based on Tanstack router. So, I'm going to hype Tanstack router big time right here because it's it's a majority of the

framework itself. Like 90% of start is

framework itself. Like 90% of start is just the router and there's just not really another router like it out there.

Um, it I would say it's the first of its kind in the the developer experience, the type safety that we just talked about, all the APIs that it comes with

on their own. It's a serious upgrade for any web application across any React meta framework or any any JavaScript framework. Hands down, the experience

framework. Hands down, the experience you get with Tanstack Router is truly unique. Um, and that would just work for

unique. Um, and that would just work for a clientside app if we're not even talking about SSR or server or full stack stuff. But start is based on

stack stuff. But start is based on tanstack router. So it inherits all of

tanstack router. So it inherits all of those things. And people are like, so

those things. And people are like, so what is start, right? Start brings with it the solution to the server, right?

SSR, streaming API routes, server functions, middleware. Um, and same as

functions, middleware. Um, and same as Redwood, which is a a great attribute, a fully transparent request response life cycle. And because of this, you you

cycle. And because of this, you you works anywhere that you deploy it. Um, I

think that all this stuff is table stakes. Uh, I I don't want to get up

stakes. Uh, I I don't want to get up here and say, hey, we built a framework and does the same thing that everybody else does. Um, so I want to I want to

else does. Um, so I want to I want to show you want to show off Tanstack router and start briefly really really quickly and and show you what it looks like and feels like to use and then um

maybe show you some fun things that we're working on that are are really going to be unique. So um I wish I had prepped more for this demo. It could be interesting. So if you like something

interesting. So if you like something you see, you could like clap and I'll be like, "Oh, let's go that direction." And

if it's silent, I'll just be like, "Okay, let's move on to the next thing."

Um, hold on. I got to change to mirroring really quick. Entire screen.

Yay. Demo time.

All right. So, I'm going to use the tanstack CLI to create a new project.

Uh, npm create or pnpm create at tanstack start latest is going to kind of boot up our CLI. Jack Harrington is the one who has buil building this CLI

and it's fantastic. Um, we're just going to name this React Summit.

Uh, yes, Tailwind. No, don't care right now. Uh, let's go with Cloudflare in

now. Uh, let's go with Cloudflare in honor of the day. Um, and don't worry, we're not going to deploy right now. Um,

we could add on a bunch of add-ons if we wanted. Um, I'm not going to do any of

wanted. Um, I'm not going to do any of this. There's a ton of them. Um, and all

this. There's a ton of them. Um, and all of these add-ons, they'll either integrate right into the system as it as it builds. Some of them are like demos

it builds. Some of them are like demos that you can just delete easily. We're

not going to do any of that. We even

ship it with like a chat demo. You know,

everybody's got to do AI these days.

We're not going to do that. We're just

going to go with like barebones.

And hopefully PNPM doesn't mirror through um Cloudflare today or something like that. Yay, it worked. Okay. So, CD

like that. Yay, it worked. Okay. So, CD

React Summit. All right. Uh I'm going to bring up my editor really quick.

Let's go full screen on that. Bump that

thing up like crazy.

And then let's start the dev server.

And localhost.

What is this?

There we go.

All right. Cool. So, we got this fun little demo uh site and it's like welcome tens start. Here's some

documentation. Um this page is running.

Is this running tens art? So, this page was SSRD. Uh, and I think if we like

was SSRD. Uh, and I think if we like turn off JavaScript, yeah, it just keeps working. So, yay. SSR checkbox. Now, we

working. So, yay. SSR checkbox. Now, we

can move on. Um, we have server functions. So, uh, this time stamp. Wow,

functions. So, uh, this time stamp. Wow,

it's time. Look at the time. We we got that time from the server and we did it in a server function. And I'll show you that in a minute. Um, I can even show you API requests that don't even have anything to do with server functions.

This is just uh you know get put post type uh handlers. I can show you that.

And we even have some demos of hey this is SPA mode. So this uh this page is an SPA. We don't do anything during SSR.

SPA. We don't do anything during SSR. And you can just kind of say you know what for this route I only want to render on the client. Then we can do other things like do full SSR which the whole site's been this way the entire time. I don't know why we have that

time. I don't know why we have that example. And then there's data only

example. And then there's data only which is interesting. And all this data uh the data was actually fetched on the server and streamed down but we rendered everything on the client. So you can kind of split very unique. Can't really

do that with any other framework. It's

very fun. Um so let's dig into the code.

I just want to give you like the brief the quick tour of kind of what it feels like to to use Tanstack start. I have

seven minutes. Great. Okay. So we have a router file. This is where we create a

router file. This is where we create a tanstack router. And what's fun is all

tanstack router. And what's fun is all the stuff that you learn about Tanstack router when you if you want to start using start um none of that has to change. There's no modes, there's no

change. There's no modes, there's no upgrades, syntax changes, nothing. Uh

you just take your existing routes and you just keep using them the way you've been using them. But now you have all this server side magic that you can use.

This is one of the only changes you have to make is you have to put your router inside of this get router function because we create a new router for every request. After that, everything is

request. After that, everything is basically the same. This route tree is generated because it we ship with file-based routing if you want to use it. You can do codebased routing too if

it. You can do codebased routing too if you want. You can even do configuration

you want. You can even do configuration based routing. Um we support all of the

based routing. Um we support all of the flavors. But here's our route uh folder

flavors. But here's our route uh folder over here. This is our root component.

over here. This is our root component.

Um and this wraps our entire application. So we've got head and meta.

application. So we've got head and meta.

We've got some link tags that we're putting in there. Here's our root document. We actually control the entire

document. We actually control the entire layout with HTML body header. Uh we even have Tanac dev tools in there. That's

pretty fun. Um we're rendering all of our scripts and then we're passing our children and that's where we're going to render the rest of our application. So

here's our index page. Um what's fun is if we uh if we were to create a new route inside of here, just like uh a fun

little route, let's do test.tsx.

um we just fill it for you. So you don't have to worry about boilerplate. Uh some

people like what is this? Don't worry

this is how we make it all type safe and you just export a single route and here's a component. From here we can add a loader uh and this will return this message and this is this is a core um

thing that I want to teach. So the only thing that you need to unlearn and learn with tensar is that everything is isomorphic by default. Isomorphic is a fancy word. What does that mean? is that

fancy word. What does that mean? is that

it means all the code that you write and see by default will run during SSR on the server and on the client during future navigations. So somebody might so

future navigations. So somebody might so this loader if you've ever used remix you might be thinking well this might run on the server. It doesn't. This runs

on the client and the server. So the

question is that well how do I make it run only on the server? Well, we can create a server function and any of the logic that we put inside of here now is

only going to run on the server. And we

can also run this function from the client, but it's an RPC. It goes back to the server to ensure that we only run it there. Um, that's how we create an

there. Um, that's how we create an isomeorphic first framework. And there's

lots of other utilities that let you isolate your code to only the server or only the client. It's very cool. Um,

let's let's be done with this page.

Let's go back here uh to some of these demos. So, here is uh that API request

demos. So, here is uh that API request route that we were looking at. Um,

I'm not even going to show you that one.

That one's not cool. Uh, here's the data only route. This is fun. So, we're

only route. This is fun. So, we're

getting those punk songs. If you saw that list of punk songs there, all we did was said SSR data only. And what

that does is we we grab this data on the server and we stream it down, but the component doesn't render until we get to the client. So, we're kind of using the

the client. So, we're kind of using the server and SSR to do some fun things with streaming the data. Like, we're

already on the server doing SSR. Let's get the data while we're there, stream it down. But maybe you have a bunch of

it down. But maybe you have a bunch of stuff on this page and you're like, you know what, we don't need to SSR the actual content, so we'll just render it on the client. That's kind of a fun pattern. Um, this full SSR is just the

pattern. Um, this full SSR is just the default. So, you'll notice there's

default. So, you'll notice there's nothing in here that's special. Um, or

there's SPA mode where you can just say SSR false. Uh, and none of this is going

SSR false. Uh, and none of this is going to run or render on the server at at all. Uh, we can just actually take this

all. Uh, we can just actually take this entire demo and um delete it, I think.

And we're just kind of back to the regular stuff. Um, but what's cool in

regular stuff. Um, but what's cool in here is if if we take a new route and let's just call this about.tsx.

Oh, cool. We have an about page now. And

we'll go back to our index. And on the homepage here, I'm just going to come to the bottom and write a link. It's a a link tag, an a tag, right? That we want

to go to a specific page. And this is where that uh type safety comes in. If I

could import my link component.

So, we specified a link. We don't have a two. And it's complaining. And it's

two. And it's complaining. And it's

like, hey, it needs to be a link to one of these places. And if we go to autocomplete, we'll see that we have about. So links are all type safe, that

about. So links are all type safe, that type safety follows you everywhere. And

if we were go to about and actually add a um search validate search object, let's say this page required a name. Um

let's do default world. And sure, I think I think zod is already in here. I

hope it is. No, it's not. So we're just going to do this. It'll just be a function with uh search and

that should work just fine name search name world as string. Obviously, we

would want to use a validator here, but I don't have zod installed.

It will infer these types. Uh you know what? Let's just break the rules. I know

what? Let's just break the rules. I know

I talked about like if we get lazy, we can just disable it. So, let's just do this.

uh d as string.

No, let's make it better. Name string.

Cool. So, we'll just pretend that we actually use zod to validate this data.

Um and then down here, if we want to use the search, uh we can grab name and it will be a string. And you can actually grab this from any other route as well.

Uh and then if we come back to our index page, you'll notice that we have an error now because we declared a required search parameter on that page. This link

is now complaining and it says, "Hey, you're missing params." Okay, let's add params. Uh, I don't know what it is yet. Let's

pretend I'm a junior developer and I have no idea what I'm doing. Um, okay.

It still says search. Search is declared here. It's not params. It's search. I'm

here. It's not params. It's search. I'm

sorry. Search is complaining now. Oh,

the expected type comes from search because it's not assignable to namestring. So we actually have to pass

namestring. So we actually have to pass a name and finally it stops complaining and we can make this as strict as we want. So this is exactly the type of

want. So this is exactly the type of experience I had to build at nozzle uh this huge SAS application because we had dashboards and links going everywhere saving all that state into the URL which

you should be doing. You can imagine why all this stuff becomes extremely valuable. I have 38 seconds and so much

valuable. I have 38 seconds and so much more to show so I just got to stop demoing.

Um all right, let's close this. Uh, I'm

going to go back to I'm going to go back to my keynote really quick.

All right, so much more to demo. There's

so many videos. Just come talk to me and I'll show you as much demo as you want.

Um, there's just not enough time in the day to show you everything. But I I have some last closing thoughts. I'm going to go into my Q&A a little bit. So um from my personal perspective I feel like the

last few years like our meta frameworks have been asking a lot from us. They've

been asking us uh for changes to our mental models. They've been asking us to

mental models. They've been asking us to refactor uh sometimes our code, sometimes the way our brains work.

They've been doing they've been giving us breaking changes and and kind of dancing around solutions. Um RSC's have kind of thrown everything for a loop.

We're moving to the server. is very

tumultuous and all this movement I feel like has given us very little benefit in return pragmatically as somebody who just needs to build an application deliver something to my users I don't

see a whole lot of benefit so for me I felt it's felt even more difficult at times to do what I used to consider simple and easy just like four or five years ago so this is why I believe that

React does deserve a new meta framework and we're getting them we just heard about one before um and I believe that we deserve one like Tanac start. I

believe that start is a practical, stable, open, very community-based project and and it's ultimately not at the mercy of a product company roadmap

or or a bottom line. Um this is a project that has tons of talented engineers and partners and users already shipping it to production that believe

that start is critical for React's future. Um, we have spent a total of 5

future. Um, we have spent a total of 5 years developing the technology that went into Tanstack Start. Um, and I believe that it actually will improve

the quality and the speed that we can build for the web um, in a very meaningful way. Uh, I'm here to earn

meaningful way. Uh, I'm here to earn that claim. We're here to earn that and

that claim. We're here to earn that and the only way for for us to do that is for you to go and give it a try and let us know what you think. That's it.

Loading...

Loading video analysis...