My perspective on localf-first is that, I think ideally every developer would
love to be able to interact with their APIs as if they were localf-first.
and then I say that not necessarily meaning like offline, but just , I
synchronously did this thing and I can trust that it's going to
be persisted where it needs to be persisted and then move on.
and just kind of feel like everything gets instantaneous.
So, I have no doubts that that is what everybody wants.
It can be difficult to get there.
and if you try and get there too quickly, I know you can get into some
trouble and there's really smart people who are slowly trying to carve out
this space and make that a reality.
Welcome to the localfirst.fm podcast.
I'm your host, Johannes Shickling, and I'm a web developer, a startup founder, and
love the craft of software engineering.
For the past few years, I've been on a journey to build a modern, high quality
music app using web technologies, and in doing so, I've been falling down the
rabbit hole of local first software.
This podcast is your invitation to join me on that journey.
In this episode, I'm speaking to Tanner Linsley, creator of the TanStack
Ecosystem, including projects such as React Query and TanStack Router.
In this episode, we talk about the newest Project TanStack DB and explore
the problems it's trying to solve and how it works before getting started.
Also, a big thank you to Jazz for supporting this podcast, and
now my interview with Tanner.
Hey Tanner, it is so awesome to have you on the podcast.
How are you doing?
I'm doing great.
Thanks for having me.
I'm very excited to have you.
so most of the audience I'm certain are familiar with your work, are
probably using a lot of your tools, but would you mind introducing yourself?
Sure.
my name's Tanner Linsley and I've been building open source software
for, I don't know, almost 10 years.
been involved in some startups, one of them for about a decade where
we were building a, a SaaS product for SEO Marketing Analytics, which
was pretty intense, a lot of fun.
And, yeah, now I mostly work full-time on TanStack, which is kind of the
umbrella of all the tools that that I've built or have helped build in
the last, eight to 10 years, so.
That's, that's what I do.
That is awesome.
I think it's safe to say that everyone who's listening has at the very least
used a product that is using one of your tools, but I'm also pretty certain that
almost everyone is also directly using one of your tools and libraries in some
package days, dependencies, me included.
I'm a huge fan of your work and you and I actually had the chance to catch
up in person again at last year's next JSConf in, very sunny San Francisco.
And this is where I got the chance to show you what I've been working on
over the last few years with Live Store and generally chat about localf-first.
And I think this was probably not your first touch point
with, localf-first as such.
I think that goes way back further.
But maybe you can share a little bit of like your relationship to localf-first.
As I understand it, you are not yet fully in the center, you're aware
of it, but you also are developing your own perspective on it.
So maybe you wanna share that.
When we met at Nex Conf and what you showed me was impressive.
It was crazy.
and the stuff you had been showing me before and after
that is just mind boggling.
I think the furthest back I can go for like a localf-first, or at least what's
aspiring to be localf-first experience was like back with Meteor and PouchDB.
I remember playing with those extensively just thinking like, wow, this is so cool.
'cause, and back then it was like, there was a, a big push to have
everything be offline, you know, first, and then, sync when it can.
obviously, the syntax and the tools, the tooling and everything around local-first
like evolved drastically since then.
it doesn't even look the same.
but that was kind of my first experience with the feeling of localf-first
that you get where you kind of just, you can interact with your data.
Pretty much as if it's synchronous and then just kind of forget about it.
And that, I think PouchDB was probably the first one that I felt that with and
I was like, wow, this is really magical.
you know, it's definitely far from perfect and there's a reason that, you know, not
everybody's using PouchDB anymore, or even were using PouchDB, yeah, I think, in
the more modern, tool chains, everything you've been working on has been kind
of the most eye-opening along with some of the other stuff from like, Convex.
Convex is a TanStack partner, and they.
Kind of like that server-first, localf-first experience as well,
and they have really direct ties with TanStack Query, which is why
I've experienced a lot of that.
so yeah, my perspective on localf-first is that, I think ideally every developer
would love to be able to interact with their APIs as if they were localf-first.
and then I say that not necessarily meaning like offline, but just in a
very synchronous, I synchronously did this thing and I can trust that it's
going to be persisted where it needs to be persisted and then move on.
and just kind of feel like everything gets instantaneous.
So, I have no doubts that that is what everybody wants.
But obviously, as I'm sure we're going to discuss here over the next few minutes,
is that it can be difficult to get there.
and if you try and get there too quickly, I know you can get into some
trouble and there's really smart people like you and many others who are, or
who are slowly trying to carve out this space and make that a reality.
So I am very anxiously and excitedly watching and also trying, we're trying
to take part in that journey where it makes sense for TanStack to take part.
That is awesome.
Well, first of all, thank you so much for the kind words.
I'm a huge fan of just like overall the way, also how you approach your
projects, that you get to work on those projects in a sustainable way.
And I think this is really why so many people trust your projects.
So just wanted to mention that.
And there's like many different ways how to reach and go after that
goal that you've motivated, that you get instantaneous data, you get the
simplicity coming from synchronous data.
and I've certainly taken probably a more radical approach on that over
the last couple of years where really like, I had the luxury of working on a
greenfield project, so I was not burdened with everything that was there before.
So I could make much more.
radical and free design decisions.
So in the case of LiveStore is why I've embraced event sourcing.
But I think you are a bit more on the other side of the spectrum with
a technology like React Query, which, at acknowledged the reality that in
most projects there is already an API data source somewhere, and that
makes it so much easier to adopt.
And that shows in the download numbers and usage of, TanStack
Query, formerly React Query.
I think this is what most people really find themselves using on a daily basis,
but as they aspire to make their app faster, to load more quickly, reload more
quickly, then they also try maybe even make their app work in a offline scenario.
Then they try to get there step by step.
So maybe you can share some anecdotes of people doing that with
TanStack Query where they reach for optimistic mutations, et cetera.
Yeah, that happens all the time.
I think that's one of the reasons why it took off, is because it's very
pragmatic, for the slop that most people are working with every day.
Whether that's your own slop, hopefully you've been in your job
long enough to have to deal with your own slop, or it's slop from before,
or you're just moving so fast that.
That's just what it is.
But, but the reality is that, you know, things are just messy, when
you're shipping real products to real people as fast as possible.
and I built React Query 'cause I needed a way to make the experience better for, for
developers and users without needing to get in the middle of the entire process.
like Meteor was trying to do, or like GraphQL was trying to do
or Apollo, you know, I needed as little buy-in as possible with
the maximum amount of, effect.
And, that's what it came to be and I think it's very natural.
when you start playing with Query, you start to realize that it is
in a way, a sync engine, right?
You have defined these declarative.
subscriptions to your data, it's very manual, right?
Very, course brain manual timings of like, how often do I want
to go and get this thing right?
So it's in the middle of like a one-off, API call and a sync engine.
but it is living and breathing and, the life cycle of that life
in this, Query cycle still takes some effort from users, you know?
So when you change something, you need to let Query know, that you've
changed something at the very least.
And we call that this invalidation, right?
And this is kind of like the bare minimum for What I would call
probably the worst sync engine you could want is just like, I've changed
something, invalidate everything and just re-sync everything, right?
It's, it's very manual.
You are the one deciding when to re-sync.
And it turns out that a lot of developers just weren't
doing that in the first place.
so it's crazy to think that just teaching, giving people a good tool, like Query
and then telling them, Hey, when you change something, you need to just
mark everything as dirty and re-sync.
It.
Just, that has improved everybody's apps a ton.
And user apps, you know, it's like, oh, data is up to date.
You know, it's not super efficient, it's not automatic or whatever, but it is.
so I think that's, the bare minimum, and that's the reality where a lot
of developers are today is they're probably still coming, they may even
be coming from .net or, you know, some monolithic backend shop into front
end, and they've never done any front end syncing, data syncing at all.
And they might just think, well, I'm just gonna call my API and display the data.
Right?
So I think that that's the reality for most developers.
Most, successful companies are not running the latest and greatest, and many of
them probably don't even know, you know, the first thing about designing a sync
engine, I barely know anything about them.
So I, I wouldn't expect many, you know, many of your run of the mill
developers to know a lot about it either.
So, but I think that's the first step.
And I, I think personally that once you taste that, it's addicting.
You want more of that and you naturally start to say, okay,
how can I make this faster?
Right?
And that's on the read's end, which is kind of like the bare minimum.
It's like, I wanna read my data and make sure it's up to date.
And then you start thinking about the writes and you're like, oh, well you know
what would be cool is if when I click this button it just showed that it's done,
even though we know it takes, you know, a hot second for it to go and be done.
And then to resync all the data, it'd be cool if it was
just looked like it was done.
And so we call that an optimistic update, right?
Like optimistic, data manipulation and Query has that built in.
Again, it's very manual.
you have to manipulate the cache that's in your browser, in the Query client
to represent that new state manually.
and you fire off the mutation or, the change that's going
to result in that state.
And then you just kind of cross your fingers.
That when you invalidate your data, when it's done and that new
data comes in, it matches what you optimistically put in there.
Again, this is like from my perspective, if you can implement optimistic
mutations with something like Query, you're already so much further ahead
than what the standard has been for a very, very, very long time.
but like I said, it's very addicting.
So then after that, you know, you start to think, okay, this
mutation thing that I'm doing, these optimistic updates, those are tedious.
You know, it's like, well, I have to, I have to make those perform, like make
those optimizations myself and manipulate the cache and it feels dirty, right?
And so that's when it starts to get a little more intense with like,
okay, how could we make it so that when I say I clicked this button.
I should like this post somewhere that I don't have to go in and manually
kind of do the optimistic update that my mutation can just know what it's
going to affect, make the update, send it to wherever it needs to go, and
then it will sync when it needs to.
And then we can just carry on, not just as like a user interface to click
something and be able to carry on immediately, but also as a developer
to be able to say, this is what's changing, and then just move on.
You know, not have to worry about optimistic updates and cache
and validations and whatnot.
So this is where I think, at least for me, where things start to get really,
really fun and really, really scary.
Mostly because it's just, it's a new space, right?
And, you know, to, give you my perspective on it, I haven't gone
too far down that rabbit hole to be honest, because it involves a
lot of knowledge about a system.
usually involves knowing about schema or, creating schema in some way.
there's different implications for where that data is being synced, whether it's
local like offline or on a server or through web sockets or REST or whatever.
so there's just a lot that comes with that and that has been intimidating
for me because it's difficult for me to generalize where like, React
Query was easy to generalize.
but it doesn't mean that we're not thinking about it.
You know?
this was a, perfect tour from the beginnings of the motivations that led
to React Query and now TanStack Query, the benefit it provides and like how
far it gets you, but also like to the point where it brings you where things
are already working pretty well, but maybe you face some new challenges
and you would like things to work even more automatically in the right way.
You now need to better understand that.
And this is also like nicely reflects, like a lot of my thinking over the
last decade where I've been wrestling with the same ideas and the same
challenges and a few points always like bubbled up to me again as like those
can't be ignored in a generalized way.
And I think this is really the, key point to underscore here, like looking
for a generalized solution and like at least I don't want to be the bearer of
bad news, but I don't think for data there is a generalizable solution because
data is like the ultimate as it depends.
And I think this is where a technology like React as like
the first of its kind in a way.
showed us a, like close to generalizable solution that applied so perfectly
to so many different situations and use cases, and unfortunately I don't
think that is realistic for data.
Just because for data you have just different trade-offs.
Let's say you're building a banking app, this is where you really want to be
certain has that wire gone out or not.
But if you're building, let's say, a note taking app, it is actually more
important that you can just carry on writing down your thoughts, then
that you perfectly know that it's also already arrived on the server.
And so it's just different trade-offs and those different trade-offs
need or could be productized and systematized into something.
And this again, is where I think React Query has been just so phenomenal in
striking those trade-offs it meets people, where most of them are, where
they don't need the perfect thing.
Something good is already better than nothing.
And then just like calling, fetch themselves and then,
dealing with that somehow.
But for people who wanna now go further for a more specialized path,
I think this is where now there's like a, tree of potential new approaches
and potential new technologies.
And some of them you've been investigating.
And I think, one particular like hairy topic here to investigate further is
like, how do you get for the writes that you're doing for the optimistic
updates or the updates more generally.
What happens when you're updating data, like most directly, you're
updating data in like a local variable somewhere, somehow running in your,
let's say, React app, but then you're also maybe posting to an API endpoint,
and now it's already, the universes are already potentially splitting.
So you've updated your variable, maybe your API request.
Goes through.
And as that API request is being propagated further, fail
somewhere there and now you need to unwind the entire thing.
But let's say maybe you do two API requests, one goes through
the other, doesn't go through.
Now you're like in the split brain situation.
And so now you need to, should you wind it back, should you partially wind it back?
And now you need to handle that on your API server as well as on your client.
And on the client, maybe you just say like, you know what, if we hit this
case, it's so rare we just show an error message and say the user like
reload, but maybe it's not so rare.
And then you need to think about it in a more principled way.
And this is where another kind of manifestation of that is cash
inconsistency and There is a really great blog post, that goes
along the lines of like, your app shouldn't become a database.
we'll link it in the description.
But, I think that is like a very nice and provocative post that shows the
reality of most ambitious apps that as you pull more on that thread, your
app becomes a database with all the hard things about a database, and it
needs to be transactionally consistent.
So if you click that button, maybe it should reflect in
instead over here and over there.
And if it doesn't, your app feels broken or things might actually like
you get the dreaded, undefined is not a function because like some, like
array index is not there, et cetera.
And the more you pull on that, the more you want kind of like a
React-like foundation that you can just trust that is maybe a bit more
specialized to your use case, but you can actually trust and it just works.
And this is where I hope things are going.
Like, basically a tree of different possibilities for, mature and well
designed data systems that, match the corresponding set of trade-offs.
And it's now our role as educators to educate developers which trade-offs
work well for their apps and what are good, solutions and systems for those.
And I think that something like React Query has been an excellent catch
all that already lifts people up.
So I'm curious whether, that makes sense to you.
I think that makes total sense and, you know, the way that I have always looked
at like trying to solve these kinds of problems is: i'm always looking for like
the least common denominator, right?
And you can never find something that's perfect, but you can
find something that's 90%.
And then once you have tackled that problem, you can kind of move
down the spectrum to, the use cases that might be more important or
more intense, but you know, are not the least common denominator.
and I think that's where React Query sits for me.
You know, it's not the tool for all of the really, really specific
difficult use cases, but 90% of the time it's the right choice.
and then we can also, if you can build something where you can build
on top of it to get to those other use cases, then that's even better.
in this scenario, I personally am opening up more to the idea where
there, you know, there could be this, general like solution, right?
I don't know exactly how that looks.
Like you said, I mean React kind of just happened and it was like,
oh wow, this is a great solution for the problem components.
I don't know if I've seen the component solution for like data
yet, you know, 'cause there's so many different trade-offs.
Like you said, I'm so interested in, see in synchronous data management
through things like signals.
Like I talk with Ryan Carniato all the time about, he's working on all
this new Signals stuff and I just love it and I'm like, wow, this in terms
of like reactivity, this is amazing.
You know, this is something to keep your eye on.
but a lot of the Signals stuff that we see also isn't crossing
the network gap all the time.
and so that gets weird into like, well, how do you then roll things
back or how do you do transactions?
And so there's this split world, like you said, between lots of
effort going into both of these.
and I don't necessarily think that's a bad thing.
so I'll fill you in a little bit on something that we have been working on.
a little while ago we teased a library called TanStack Optimistic.
And the idea around TanStack Optimistic came from Kyle Matthews, and he's actually
the one who's been spearheading it.
and which is a crazy full circle because if you go back six or seven years, Kyle
and I were actually competing at one point building static site generation software.
I was building React Static, and he was working on Gatsby.
Next Js was getting into static site gen, and it was cool.
he went and raised money and turned Gatsby into this awesome thing.
And I was like, well, I have a company already, so I'm gonna fold.
I said, I'll have to do this later.
And what do you know?
now he's working on a new, on at a company doing ElectricSQL
and really cool stuff there.
And now I'm the one building the framework.
So the, the roles feel reversed, but we're working together on some things
right now because Kyle at ElectricSQL, they've become very interested in,
this exact kind of general toolkit that we have kind of been alluding to.
and one of the first problems that they ran into with ElectricSQL and, and
React Query and all this was that, they needed those optimistic updates to work.
but in a way that was kind of compatible.
Not just ElectricSQL, but just kind of in general, like what's this general
kind of optimistic transactional layer?
And that's what TanStack optimistic started out as.
and I mean, it worked, it was functional.
it still works today, right now, but it's, it's already evolving.
So that was just, you know, a couple months ago that we were
talking about TanStack optimistic.
So problem number one, TanStack optimistic is a bad name.
because we already have optimistic updates in React Query, TanStack Query.
So it's like, well, does this have something to do with Query?
so it was confusing, the second problem was that, we wanted to figure out, you
know, does this overlap with Query or not?
and could it, should it utilize Query or is it something completely different?
Right.
And.
So it turns out that, part of this layer we believe up to this point
is that, like you said, if you start pulling on this thread long
enough, it becomes a database, right?
And I don't really think that's a bad thing because a
database is a very loose term.
If you look at React Query, there's a Query cache inside of
query, and that's a database, you know, it's a key value store.
it's not relational, it's not, you know, sophisticated in any way.
I should clarify.
like the application should not become a database, typically, it
accidentally becomes a database.
And that's the point.
The app shouldn't be the database, but an underlying technology that
you use that goes above and beyond to be a database to do all the hard
work that it takes to be a database.
That should be the database.
And I think that's exactly what you're saying.
Totally agree.
Yes.
And that's, I think that's the most interesting thing, is that the database
is gonna be there no matter what, whether it's a, a replication, a cache,
a lens, whatever you wanna call it, all these different terms, right.
But that's, the direction we're headed.
So we, we've actually renamed TanStack, optimistic to TanStack DB.
And we're only working on a small part of it right now, which is the optimistic
parts and the collections part.
So let me get into that a little bit.
We don't need to go too far into this because I'll be honest, Kyle
knows 100% more about this than I do.
I know 1%.
we're just kind of consulting together just to make sure that like we can
build on top of each other's things.
what I understand at this point is that, you know, optimistic updates with
something like Query only get you so far.
And at some point you need that schema, like I was saying, you
need some kind of structure.
and you need some way to declaratively kind of build up these
relationships between your data.
of your data and that you're pulling from somewhere and your, mutations and, the
actions you're taking against your data.
And just having consistent actions against your data solves a lot of the problems
around, well, if it was just signals and we're just kind of firing reactivity
events off all over the place, how do you transaction those things together?
How do you roll things back?
I mean, there's ways to do that.
but it, we found that if we formalize things into mutations still, which
is very common across a lot of different database, implementations
that, that you can transact on those much easier and roll things back.
I mean, it's the same way with Convex, you know, in LiveStore too.
so we want a layer that is purely for the front end, it's purely
for the client where we can define these collections and define these
mutations that are going to happen and the relationships between those.
and then those can be fulfilled by syn So for instance, you can make a collection
to say, you know, here's all my users.
here's my filters on those users.
here's pagination, or here's just all the things that kind of create the
lens into this data source that I have.
And it's formalized contract, formalized schema on how you get that.
And then you have mutations that say, you know, I'm mutating this thing.
and this thing is a formalized structure within my application, and it has schema.
And then.
Behind that layer, you have an adapter to say, okay, now that we
have this formalized structure, we can wire this up to whatever we want.
We could read using a rest API, and kind of we could say, well, we want to pull
it, or we want to use invalidation, or we want to use SSE or something like that.
Or you could set it up to work with web sockets, or you could set it
up to work with SQLite or whatever.
it just needs to be fulfilled.
so in a similar way to React Query, saying, a promise is all you need, right?
for TanStack db, the loose vision right now is that you need something
that can satisfy the interface or not even the interface, but
the lifecycle of a sync engine.
That might be super drop in, like ElectricSQL or whatever, or it
might be more manual, which is what I'm really excited about to say.
I already have a rest, API, I'm already using React Query.
We can't upgrade into web sockets or like do a bunch of crazy infrastructure
stuff right now on the backend.
But if we could kind of upgrade the lifecycle into this
contract of sync engine, right?
What does it mean to be a sync engine for the front end?
Then you could technically upgrade your front end data reading and writing
experience to what feels like a sync engine, but behind the scenes, It
could just be going out and kind of using the same APIs that existed in
your company a year ago or whatever.
So I think that's the vision and to me that sounds like a least common
denominator approach to it to say, data could get here somehow, and we're gonna
send data out somehow and we're gonna build formalized contracts around that.
and then hopefully, we see adoption around adapters and patterns and utilities.
and possibly even around things like TanStack Query where maybe you
don't have web sockets or service and events or sync engine happening.
So maybe, maybe TanStack Query is the fulfiller of this contract, I think
that starts to look very interesting.
to be very blunt, that's kind of the, the envelope that's the bleeding edge of my
opinions and my knowledge on the topic.
everything honestly, from here forward is probably gonna be more, nuanced opinion
That is awesome.
And I think that really nicely closed the loop.
Something that stuck with me that you said, the beginning of our conversation is
that if you squint, React Query is already kind of like a mini sync engine is, the,
the benefit is it works with everything.
The downside is it only goes so far and doesn't handle all of those edge
cases in the most resilient way.
Right?
But with like Pareto principle style, like you do 20% of the
effort, you get 80%, of the outcome.
And now you're connecting this to, a variation of it where what React Query
already does is like, it's a Query part.
So what do you Query?
You Query from like something where data comes from and now you
basically say, actually that is.
Already very useful.
But where we are getting the data from, there's sort of like this
in-between stage where typically you resolve a Query to a database.
And so we only have that, we don't really acknowledge that there is a
database in the middle, but yet there is a database in the middle, right?
And once we have that, and once we acknowledge it and build all
the things around it, we can actually Query much more, much
better, much faster, much safer.
we get like super fast filtering.
We these updates, optimistic updates become simpler, et cetera.
Sort of like embracing that
when you, when you sprinkle schema into things, a lot of dev tools get better.
So, you know, the dev tools for Query are awesome, don't get me wrong.
They, I think they're, I think they're great.
But when you have schema.
And formalized interfaces on top of your data dev tooling
can get way more sophisticated.
in fact, I'm remembering all of the awesome stuff that I've seen
from LiveStore, you know, out, out of dev tooling that's like,
it would be impossible to do with a tool with just Query, right?
but, but you see some of that come into play when you know,
okay, GraphQL gets involved.
It's like, well, now we have schema.
Now we can do all this cool stuff.
it's kind of the sa it's kind of the same thing here.
Whenever you add schema into something and create stricter contracts, even if those
contracts are with yourself, like you can build much better tooling around it.
I couldn't agree more schemas, like nine out of 10 cases.
It's a great deal.
You put in a little bit of work and you get so much out of it constantly
in all of those different dimensions, types, validation, and like you can
also like, and I think as a industry we've only scratched the surface what
we can actually do with schemas, like at least as a JavaScript industry in
other program languages, schemas are like highly leveraged to, for example,
work with data in a more efficient way.
So this is where like Protobuf, JRPC, et cetera.
A lot of that is used to minimize the amount of data that we send
across the wires or have more stable contracts as we are evolving things.
And I think we're just scratching the surface of like what will be the
javaScript equivalent where we have, so right now, maybe we have something that
also gives us the benefit of something like Protobuf in let's say 2030.
I don't wanna be overly optimistic here.
Sounds accurate.
But, but yeah, I, I think this is super compelling what you're pitching here.
And like, I don't think this is just a, pitch, but it's actually happening.
And, Kyle, who we also had previously on the guest.
Who's now at Electric, is an excellent person to lead the charge on this, so
I'm really excited to, see that evolve.
I have many more questions that I would like to ask you or Kyle.
Let's do it.
But I'll, I'll, uh, I won't go too much into that there.
Just as you mentioned that you're, only so far in the weeds so far.
but one thing that I'm also curious about in regards to TanStack DB is do
you already have a hunch of like, what is that contract, that makes when you bring
a plugable, sync engine that you provide there as a data source, what does that
need to quack like, that it's a duck,
right?
yes, we do have a flexible and changing idea of what those, contracts look like.
in fact, in inside of, it's still at slash.
Still at TanStack slash optimistic on GitHub.
but we do already have, like some of the core hooks and logic set up in there
already to around collections, that the documentation obviously isn't there
yet, but if you dig into the code in the examples, you can start to see, kind
of the silhouette of what syncing is.
So, you know, we have some configuration.
there's like a sync option that takes a sync configuration.
So it has been formalized, for now in terms of what we believe
it needs to be, you know, to get a proof of concept out the door.
and you know, one of the good examples to go look at in there is there is
an Electric, there's an Electric sync configuration that now dog foods, that
that interface in that contract to kind of give you an idea of how that could feel.
Now things are gonna change, things are gonna get better, upgrade, you
know, we'll, we'll try and add more adapters and break our expectations.
So, the idea is that the, those sync contracts are going to evolve
drastically, over the next little while.
That sounds awesome.
And I'm particularly excited about all of those adapters since once you start
adjusting your own perspective, then almost anything can be a data source
or a sync engine for that matter.
It might not be inherently reactive, but then you throw polling on
it and until that data source is itself reactive, you can sort of,
paper over that through polling.
And just like a, let's say the GitHub, API could be actually
a sync engine implementation.
Absolutely.
And now you can build a local app that works with like GitHub data just as
it's local, like code, like is local.
That's the idea.
And, you know, going beyond that, I think, with Query right now, it's easy
to get trapped into thinking like, oh, I can just Query my, my one database.
Or you start thinking, well, I can Query multiple.
or even start Querying anything that is a promise.
So, so once you start thinking about the, the sync protocol or the sync contract
as just something to be fulfilled, it kind of opens up the same gate.
It's like a parable to when people are like, oh, I can use React Query to
use, like device APIs because they're just based on a promise, you know?
So I imagine the same thing will happen, for these sync contracts as we kind of
just learn that, you know, oh, anything that I can read and write to, I can turn
into a sync, like a sync configuration.
And I think it gets really exciting when you start looking at the ability to have
multiple sync configurations working together and potentially merging into
the same schema in your application.
and they might handle different responsibilities.
'cause the reality is that.
I mean, a lot of people would love offline.
You know, you can do offline for a lot of things, but I don't know of
any application that's providing a lot of value these days that doesn't
eventually need to connect to the server.
And like you said, eventually need very strict transactions on I did
this thing and did it happen, and we cannot proceed until it did.
Right?
So we're trying to make sure that we don't code ourselves into a corner
here and we wanna design it so that, you can do all of those things
kinda, you know, synchronous first.
you can have sync contracts that are very optimistic and just fire
and forget and we'll sync it later.
And when you need to.
You can kind of go deeper and say, okay, I'm finding off this mutation,
but I'd like to opt into some more strict confirmations around it to
make sure that we don't proceed.
You can lock things easier.
So I don't know, I like this future where it's, it's kind of like Query
for Query in a way where you know, we're just adding organization, we're
adding more intelligent lifecycle where we're adding a heartbeat to
what people experience today is react Query is like, oh, I'm syncing data.
We're just going to breathe a little bit more life into that engine,
without trying to control everything about the experience, about the
backend, and about the language that you use to do things and.
you know, if we can create that adapter economy there, I think that, we could
see some really cool stuff happen, we're working really closely with ElectricSQL
and also with Convex, you know, convex uses Query directly, which is amazing.
And we also have really good relationships with TRPC that uses Query.
So we have a lot of people involved in this, space to different varying degrees.
And I'm confident that that's, really why we think now is a good time
is because we have enough signal.
to design something that could be helpful to a majority of people.
We're trying to take a slow though, to be honest, because this is
not something you just rush into.
Oh, I completely agree.
Maybe using this very topic as an opportunity to pull back
the, the curtains a little bit.
what I see as just like the common threads through all of the, the projects, the
all the TanStack projects, is that they have a very, kinda like the, the TanStack
way of like how the API looks and feels.
It's like, it's very intuitive.
It's nicely modeled around the common scenarios, but then also allows for like
reaching for that extra configuration, that extra functionality once you need
it, but it doesn't overwhelm you upfront with like, needing to know of all of that.
And now you're going into a new field and in an existing field even deeper.
And so now you need to apply like that's.
At the end, there is a new TanStack DB products and library emerging,
and I'm certain that will feel just as intuitive and as nice
as the other TanStack libraries.
But that doesn't just happen, by itself.
But there's something, a lot of intuition, a lot of experience
that's going into that.
And I'm not sure whether you formalized that, but we, we got
some questions from the audience.
whether you have any sort of like process guidelines, your own
guidance, your inner guidance, intuition, how would you frame that?
that could also serve as advice to others who aspire to build tools,
like, like the ones you're working on?
Well, I like to think about it.
I like to approach it in a way of like, there's different tiers
of things that you can control.
So for me personally, if I'm working on a project.
Building it myself.
Like I can control a lot and I'm just very picky and, I try to
be my best customer in a way.
Like, I try to approach using my own software as if I don't know everything
about it and call me schizophrenic.
But like, you need to be able to kind of assume this other identity
to where you're like, okay, I don't know anything about this project.
I'm trying to use this API, this is confusing.
What does this even mean?
So you need to wear multiple hats at the same time and be able to switch
between them very quickly to say, oh, yeah, okay, now I'm gonna go back
to, architect Tanner and, and, change this to, make it easier to understand.
So.
A lot of it is just, I think just being very picky and just using your
own tools, like a lot, using your own tools a lot and showing other people
your tools before you release them and say, well what do you think about this?
And trying to teach your tool to people and they'll say, Hey, that's
really cool, but this is super weird.
Like, I don't agree with that.
So you just need to be getting feedback all the time and say,
always be shipping, right?
You can ship to a friend, you can ship to your company, you can ship somewhere.
It doesn't have to be NPM before, you know you can get feedback.
so that's kind of rule number one.
after that, I believe that at this point for TanStack, things
are also changing a little bit.
Like I said, I'm not the one who's the driving force between TanStack DB Kyle is.
and if you look at other libraries, the same thing has kind of been happening.
So.
TanStack form was, you know, the bulk of the entire project was spearheaded and
completed and done by Corbin Crutchley.
and it doesn't mean I didn't, I had a lot to do with the initial, like,
parts of TanStack form, you know, for the first little while, but I
can't be everywhere all at once.
So I've mostly been focusing on router and start for the last two years.
And so the next part of it is, you know, if you can't control everything
on your own, you need to be able to find people that you trust.
And that's really what it comes down to is I get petitions and, people every day
on Twitter and on GitHub who are like, Hey, I have this idea for a library.
We should do it.
Or I have this idea for a feature or whatever.
And.
that's excellent feedback when we take that feedback into consideration
for all, all everything that we see.
but the choice of letting somebody come in and start making decisions for
you is a really, really big decision.
And it just needs to be one that you trust.
And so if you see one of the, every single one of the core
maintainers and core contributors to TanStack, did not happen overnight.
except for Corbin Crutchley.
I met Corbin and I knew it in 10 minutes that, he was the right person for the job.
but it really comes down to trust.
And, and at the end of the day, I trust, you know, Dominic and
Kevin and Corbin, and Manuel, and Sean and Chris and Kyle, right?
I trust all these individuals and many more that I didn't
mention, because they understand.
The brand.
Now they understand our priorities and they understand what needs to happen.
You know, we, prioritize type safety above all else.
You know, we prioritize the 90% use case above all else, but we make it so that you
can gracefully opt into advance features.
it's not formalized in a document, but it is formalized in the experience that
you get using one of these libraries.
And if you know, you know, and if we're going to ship a new product,
everybody collectively understands that it needs to meet the same
standards as all the other products.
So, and the people that I, invite in or, want to come and help me
build stuff, those are people that I trust to execute on that vision.
So.
That is awesome.
I fully agree with that.
Thank you so much for, for sharing that.
you've mentioned TanStack Router and TanStack Start both of those projects.
I'm also using myself a lot.
I'm curious if you now extrapolate a little bit further.
TanStack Start is, just getting to a point where it's will hit I guess 1.0
at some point as well and if you're now extrapolate forward TanStack start
filling in all of those, features and, boxes that you have in mind.
and if you then take TanStack DB and you combine them, there's
possibly like some really interesting opportunities that weren't really
thinkable or possible before.
Are there any kind of napkin sketches, shower thoughts you can
share where you imagine like some new emerging, superpowers or kinda like
a new kind of framework that will be possible for this combination?
not in the sense of like some new monolithic enclosure around these
things, but like the vision that I have for it is that, already today you
can, build a TanStack Start project.
And when you build a Start project, you're not, just using start.
People don't understand this either.
So, I mean, I'll take the moment to explain it so that like, when you use
Next js right, you install next JS and the router is enclosed inside of next
js, and the server loading strategies are all enclosed inside of there.
The SSR tools and everything is just, monolithic.
It's, abstractions around a whole thing, right?
And there, there're dependencies inside of each other.
Now, TanStack start is very different.
It's weird because we say the framework is TanStack start, but it's not.
It's just a convenient marketing, term to make it sound different
than what TanStack router is.
So TanStack router is what you'll still import with a start application
that you've used it, you know this.
So when you import, most of the imports that you're making and the utilities
that you're calling with TanStack Start are actually coming from router.
there's actually very few that are coming from start until you need
those server side capabilities, right?
So when you have your server entry, or you want to write an API route, or
you have a server function or you need some middleware, or you need to access
request headers or something like that.
That's when you reach for Start.
And so it's interesting to think about Start and Router as actual
their parallel dependencies together.
and yes, Start does rely on like a peer dependency in a sense of TanStack Router.
So that's why we kind of say, oh, you're using TanStack Start
because it implies usage of Router.
But where they're together, I think that's the most interesting part because
you get into the app and you start building and you realize that you're
really just using these tools together.
And maybe you're using TanStack Router and you're like, oh, this caching is
really good in the router and I like this.
And then you get to a moment where you're like, oh, I really wish I had formalized
mutations around this thing, or that I could share data between routes.
So then you bring in TanStack Query and you know, you don't just turn
it on in the router, you bring in TanStack Query and they work together.
So.
They have interfaces that, integrate with each other and
they work alongside each other.
And my hope for something like TanStack DB around the router and start is
that it would be the same experience.
You would bring it in and you would use it alongside these other utilities.
but the solution should be that bringing in something like TanStack db, the end
result should be that you should be able to, with a little bit more work,
like you said, up at this top layer of producing, you know, providing some schema
and providing some, some structure that you would be able to then get rid of a
lot of the code, that you have in your.
data loading lifecycle points and your user interaction points, in your actual
business logic of your application.
the hope for something like TanStack DB would be similar to the experience of,
you know, somebody moving into TanStack Query, being able to get rid of all of
that manual data fetching code with fetch and useEffect and all this other stuff.
Moving to something like Query.
I want that same experience for TanStack DB if it's warranted, right?
So it's like you're unintentionally building schema and database and trying,
you know, it's like you're trying to formalize all these contracts, but you,
don't have the right tool to do it.
Moving to TanStack DB should be an event that removes the burden of a lot of code
that you've written and removes a lot of the burden of linking queries together and
linking mutations and queries together.
that should be the goal.
not only goal for the developer side of it, but also the user side of it,
where when you move to Query from something that's very manual, all
of a sudden your data is up to date.
Now it's fresher.
You can tell a website that's probably using React Query because you do something
and it updates and it's always there.
You focus the window and it's always there.
same thing for moving something like TanStack db.
You'll see better results around mutations.
You know, you'll click something it won't just be optimistic,
but it'll be synced everywhere.
and when things happen on the server.
And, you know, hopefully if you're using something like web sockets or some kind
of servers sent event, you'll just kind of get that synced to you automatically
without needing to invalidate or refocus the window or anything.
So, if we can move both of those chess pieces forward, you know, both
on the developer experience side of, Hey, I, get to delete code now and
have better contracts and a better experience as a developer and just
more confidence, in what I'm doing.
And as a user, you get to move forward to say things are faster, they're
more responsive, and the user also has more confidence that what they're
doing is happening and what they're seeing is up to date and real, right?
So I think that's, the end goal.
and if we can't accomplish that, we won't launch it.
that's the requirement,
That definitely resonates.
And I think that's sort of like a, a nice litmus test for a library that if
you adopt a library in your application and the library does some things
that you've previously done before, ideally the library should absorb
everything that is not intent, that is very specific about your application.
So everything that remains is like pure intent.
That's about my application.
Everything else is like, you've hopefully picked the right tool that like the
choice of the tool is part of your intent, but then you're assuming down like one
level, become even more meta about within the scope of this tool, this library.
Now I'm specifying my further intent when you pick a really, really
great tool, it's, you can notice it by, it removing even more code
that you had previously written.
It surprises you of like how concise you can express what you want to
do in a way that you didn't even expect how simple this can be.
And I think a really great library kinda like surprises you through its simplicity.
and so I wanna round out this conversation on one last topic that
I think you're a really excellent person to share your thoughts on this.
most TanStack projects are more client side centric, like TanStack table,
TanStack, form TanStack Query, et cetera.
those are all primitives that help us to build rich client side applications.
but if you're looking at the React ecosystem, on a larger scale, there's
been a lot of momentum and movement and developments more on the server side
spectrum of application development.
And I think it can be a bit confusing for developers who are not as
experienced on either side of the spectrum to what to kind of lean into.
So it's not everything is always compatible and, there's maybe some
applications that are being built that go heavily on server side
technologies, even though that's not the best fit for them and vice versa.
So I'm curious whether you can share some reflections on, that sort of
broadening spectrum of react covering the server as well, and whether you can
provide some guidance to developers, where to, focus their, attention on.
That's a hard question.
because there's a couple of different ways to look at that.
There's a personal way to look at it.
Like, what should you be learning yourself to, you know, be relevant?
and I think that you should know as much of the web platform as you can, right?
Whether that's client or server.
You should, you know, if you're a web developer, you need to know the web.
and that includes servers.
So, on a personal level, you need to be learning as much as you possibly can.
does that mean you need to be learning every language you can.
No.
but it means you need to know the concepts, to be able to at least
communicate with, people or with a team, you know, accurately.
So there's like this personal level thing that I, I think is really important.
Like, I'm definitely not an expert at, you know other languages and like server side
building, server side things, servers.
but I've worked with teams that have built very, very sophisticated systems and I've
helped architect some of those systems.
and you know, I've been able to work through that, those thought
processes and learn with them.
So I think that's very valuable.
Now, in, practice, I think practice is a little bit different.
and this is where it's like a big, it depends, because you might be at,
you know, Y Combinator startup where you just have to know everything and
you are building full stack because you don't have a choice, right?
and in that moment, your job requires you to do it all.
So you better do it all.
You better learn it, and you better in invest into everything that
you need to ship your product.
And I think that's really what it comes down to in practice is that, yes, you have
to be thinking about your career, right?
But not.
being negligent to the task at hand.
And if you work for a company where you're expected to be a, full stack
developer, then you better make sure that you're investing in both the
front end and the back end equally.
if you work for a company and you're a front end developer and you know that,
you know, pretty soon you're gonna, they're gonna start running React
server components and server technology.
Does it mean you need to become a database expert and learn SQL and learn
how to run Redis and, you know, and Kubernetes or just Docker or whatever?
No, it doesn't necessarily mean all of that, but it does mean that within
the realm of, of like JavaScript running on the server, you should
probably start getting familiar with JavaScript on the server.
You should probably start learning, you know, what those patterns look like.
And I think, you know, on, on the, really far end of the spectrum, which is more
common than you think, because there, there's companies out there that have been
around for a really long time and they're running technology that is, that's old
and outdated, and they move slow and they make a lot of money and they have a lot
of teams and a lot of employees, and maybe they're publicly traded, but that doesn't
mean that, you know, that they're even allowed to run JavaScript on the server.
I mean, there are companies out there that are, you know, billion dollar
companies that are not allowed to run JavaScript on the server yet.
So, in situations like that, it's like, well, do you need to focus on
learning React server components?
Sure, you can go check it out and, and learn how to do some things
with SSR and play around with it.
But if that's your job, your job is probably to be the best front
end engineer that you possibly can.
And if, that's the case, you just need to make sure that you're focusing
on what's important to your company.
So I don't want to sound like, you know, you need to sell out
your career to your company.
obviously I, you know, I like to stay on the bleeding edge of everything as well.
I'm just a really pragmatic person, and at the end of the
day, everybody wants to get paid.
Everybody needs to get paid, and we should not ignore that that is a reality.
And if your paycheck is important to you it's a, a critical piece of your life.
Then you need to be focusing on, on what's gonna make sure that that paycheck
keeps growing and getting bigger.
And if that paycheck isn't going to get bigger or grow with your effort, Then you
should be learning other technologies that will help you secure either a different
job or a promotion or whatever that's going to let you use that new knowledge
to grow yourself and grow your career.
That, that's kind of where I put it.
So it is, a lot of it depends, right?
totally.
I think that's fantastic advice.
We can leave it at that.
I know that, you only have so much time.
I just wanna highlight one point.
You've used the word pragmatic and this is really what, for me resembles that's the
essence of like the entire TanStack family of tools, like it's above everything else.
I think it's pragmatic.
So in case you ever wanna formalize that, that is like my
candidate I'm offering to you.
I wanna thank you so much for taking the time, sharing, everything.
That you've shared today.
and for all the loves, sweat and tears you're putting into all of
your projects for such a long time.
I'm really excited to see where all of this is going.
Particularly excited for TanStack DB and, thank you so much
for, coming on the show today.
Absolutely.
It's been a pleasure.
Thank you for listening to the localfirst.fm podcast.
If you've enjoyed this episode and haven't done so already, please
subscribe and leave a review.
Please also share this episode with your friends and colleagues.
Spreading the word about the podcast is a great way to support
it and to help me keep it going.
A special thanks again to Jazz for supporting this podcast.
I'll see you next time.