1
00:00:00,000 --> 00:00:03,163
What do you mean replicate the
whole data to the end client?

2
00:00:03,173 --> 00:00:03,959
Like, It's too big.

3
00:00:03,959 --> 00:00:04,719
Like, that can't work.

4
00:00:04,765 --> 00:00:06,635
So I understand the hesitation.

5
00:00:06,749 --> 00:00:10,039
But any like half step in that
direction, it just  a gateway to

6
00:00:10,039 --> 00:00:11,449
replicating more and more and more.

7
00:00:11,479 --> 00:00:13,469
Cause you just want more and
more and more to be instant.

8
00:00:13,479 --> 00:00:17,934
So I had a very traditional mindset
around it, which is, okay, we have an

9
00:00:17,934 --> 00:00:21,884
API, the API serves data and we're going
to like cache some of that locally.

10
00:00:22,144 --> 00:00:24,704
And I think a lot of people are already
doing this  stuff, like react-query

11
00:00:24,800 --> 00:00:28,650
put you in that direction where just
caching stuff and then  refetching.

12
00:00:28,850 --> 00:00:32,250
It kind of gives you some of this like
real time local-first feel, but then

13
00:00:32,250 --> 00:00:34,977
you start to hit the limits with that,
if you're looking for stuff that's not

14
00:00:34,987 --> 00:00:38,954
literally in the exact view, you're then
round tripping with the server again.

15
00:00:39,154 --> 00:00:42,547
The key thing to understand is  if
you're building an app that people

16
00:00:42,547 --> 00:00:46,717
are actually using every day, the
initial load time is really not

17
00:00:46,717 --> 00:00:48,047
something you need to care about.

18
00:00:48,483 --> 00:00:50,593
Welcome to the Local First FM podcast.

19
00:00:50,953 --> 00:00:53,673
I'm your host, Johannes Schickling,
and I'm a web developer, a

20
00:00:53,673 --> 00:00:56,833
startup founder, and love the
craft of software engineering.

21
00:00:57,253 --> 00:01:01,153
For the past few years, I've been on a
journey to build a modern, high quality

22
00:01:01,153 --> 00:01:02,873
music app using web technologies.

23
00:01:03,253 --> 00:01:07,233
And in doing so, I've been falling down
the rabbit hole of local first software.

24
00:01:07,733 --> 00:01:10,743
This podcast is your invitation
to join me on that journey.

25
00:01:11,663 --> 00:01:15,553
In this episode, I'm speaking to
Dax Rad, who is using local first

26
00:01:15,573 --> 00:01:19,303
in multiple projects, including the
serverless deployment tool, sst.

27
00:01:19,303 --> 00:01:23,313
dev, a healthcare app, and an
upcoming personal finance app.

28
00:01:23,953 --> 00:01:29,453
In this conversation, we explore how local
first simplifies app development, the UX

29
00:01:29,493 --> 00:01:34,173
and data patterns he's using, and how self
hosting could empower local first apps.

30
00:01:34,893 --> 00:01:38,253
Before getting started, also a
big thank you to Expo and Crab

31
00:01:38,253 --> 00:01:40,013
Nebula for supporting this podcast.

32
00:01:40,493 --> 00:01:42,313
And now my interview with Dax.

33
00:01:42,853 --> 00:01:44,273
Hey Dax, welcome to the show.

34
00:01:44,273 --> 00:01:44,863
How are you doing?

35
00:01:45,593 --> 00:01:45,963
Good.

36
00:01:45,973 --> 00:01:46,653
How are you doing?

37
00:01:47,023 --> 00:01:48,023
I'm doing great.

38
00:01:48,133 --> 00:01:49,813
Super excited to have you on the show.

39
00:01:50,093 --> 00:01:54,289
You're certainly also one of the
more, well known voices on Twitter

40
00:01:54,359 --> 00:01:56,149
sharing the local-first gospel.

41
00:01:56,539 --> 00:02:00,159
So, seems like you're not just working
on one project with local-first,

42
00:02:00,179 --> 00:02:04,509
but almost quite a portfolio of
local-first inspired projects.

43
00:02:04,799 --> 00:02:08,119
So super curious to hear more
about those, but maybe you want to

44
00:02:08,119 --> 00:02:11,879
share a bit of your story of like,
what has led you to local-first?

45
00:02:12,399 --> 00:02:13,539
yeah, so my name is Dax.

46
00:02:13,589 --> 00:02:17,489
My primary project that I work
on is a project called SST.

47
00:02:18,049 --> 00:02:19,909
Uh, we're a, we're a dev tool.

48
00:02:19,919 --> 00:02:21,679
Like, we help people ship applications.

49
00:02:21,679 --> 00:02:25,159
We help people deploy all kinds of
infrastructure to all kinds of places.

50
00:02:25,759 --> 00:02:29,199
And we have an adjacent project to it.

51
00:02:29,289 --> 00:02:32,809
Uh, so SST users get access to
this thing called the SST console.

52
00:02:33,649 --> 00:02:36,029
And that is a local-first application.

53
00:02:36,839 --> 00:02:38,319
I mean, I'm gonna say local-first.

54
00:02:38,339 --> 00:02:39,789
There's obviously, like, a spectrum.

55
00:02:39,789 --> 00:02:40,789
I would say it's a local-first.

56
00:02:41,249 --> 00:02:45,209
The least local-first thing with that
you could possibly have while still,

57
00:02:45,239 --> 00:02:48,869
I would say, embodying some of the
characteristics, but my history with it,

58
00:02:49,509 --> 00:02:54,179
like most people or like a lot of people,
I guess, uh, it started with, with Linear.

59
00:02:54,259 --> 00:02:55,249
I came across.

60
00:02:56,014 --> 00:03:00,654
The product probably like 2018 or 2019
somewhere, somewhere around there,

61
00:03:00,654 --> 00:03:02,054
probably 2019, something like that.

62
00:03:02,384 --> 00:03:06,944
And I found them fascinating
in a few dimensions.

63
00:03:07,414 --> 00:03:10,534
One, their attention to detail
was just kind of outrageous.

64
00:03:10,594 --> 00:03:11,904
Like there's all these little details.

65
00:03:12,624 --> 00:03:16,094
Outside of local-first stuff, just these
details that are in there that, you know,

66
00:03:16,124 --> 00:03:17,674
they're, they're like real craftsmen.

67
00:03:17,674 --> 00:03:20,324
They care about, uh, every
little aspect of their product.

68
00:03:20,714 --> 00:03:24,494
I found them really interesting from
a business perspective because they

69
00:03:24,494 --> 00:03:28,774
entered the most crowded and most
cliche space you can possibly think of.

70
00:03:28,804 --> 00:03:32,414
Everyone has had the idea of, I
hate my project management tool.

71
00:03:32,424 --> 00:03:36,104
Like I should build my own,
uh, the most boring, cliche,

72
00:03:36,144 --> 00:03:37,884
non innovative idea possible.

73
00:03:38,429 --> 00:03:40,909
They enter that space and
they absolutely crush it.

74
00:03:40,909 --> 00:03:42,629
Like no one really could
have predicted that.

75
00:03:42,629 --> 00:03:45,469
I think you would have, if you
just heard that idea, you're just

76
00:03:45,469 --> 00:03:49,389
been like, whatever, and they did
that purely from this aspect of.

77
00:03:49,834 --> 00:03:52,424
Really excellent quality and performance.

78
00:03:52,724 --> 00:03:55,984
And these are things that people will love
to say, like, oh, the user doesn't care.

79
00:03:56,004 --> 00:03:57,644
People, performance doesn't matter.

80
00:03:57,644 --> 00:04:00,834
Like, you know, they'll try to say that
it's something that you can do later.

81
00:04:00,954 --> 00:04:05,274
And this is a great example of a company
that's kind of violating that narrative.

82
00:04:05,784 --> 00:04:07,404
So I find them really fascinating.

83
00:04:07,554 --> 00:04:11,779
And I got obsessed with just digging
into how They built their stuff

84
00:04:11,859 --> 00:04:13,369
initially from like a UI perspective.

85
00:04:13,369 --> 00:04:16,039
But then I was like kind of looking
into how all this, how everything

86
00:04:16,039 --> 00:04:18,359
is super responsive and instant.

87
00:04:18,529 --> 00:04:21,249
And I started them so hard to the
point where I think I was really

88
00:04:21,249 --> 00:04:23,599
convinced at some point that I
knew more about their system than

89
00:04:23,599 --> 00:04:25,109
anybody that didn't work there.

90
00:04:25,379 --> 00:04:27,479
Like I understood like their
exact protocol, like how

91
00:04:27,479 --> 00:04:29,129
they sort stuff locally.

92
00:04:29,129 --> 00:04:32,099
Uh, I kind of just kept going
back to it to refer to it.

93
00:04:32,429 --> 00:04:34,969
And around the same time, my
wife and I were starting a new

94
00:04:34,969 --> 00:04:39,009
project in the healthcare space,
and this was a productivity tool.

95
00:04:39,029 --> 00:04:43,299
So it's the type of tool that people log
into the beginning of the day, use it

96
00:04:43,299 --> 00:04:45,639
all day until they finish their work.

97
00:04:45,689 --> 00:04:49,729
So these are the places where
I feel like the performance

98
00:04:49,769 --> 00:04:51,869
aspect is really understated.

99
00:04:52,539 --> 00:04:57,449
When you're using an app every single
second of the day to do your work,

100
00:04:57,904 --> 00:05:01,104
There's all those little paper cuts
where something takes a little bit longer

101
00:05:01,104 --> 00:05:02,574
to load, or there's like a spinner.

102
00:05:03,224 --> 00:05:04,484
These do weigh on you.

103
00:05:04,524 --> 00:05:07,164
If you talk to the user, they
probably won't articulate it.

104
00:05:07,464 --> 00:05:11,648
But if you ask them the question, does
it feel like a joy to do your work?

105
00:05:11,668 --> 00:05:13,228
Or does it feel draining to do your work?

106
00:05:13,478 --> 00:05:16,938
And they're going to say draining
unless you push things to this degree.

107
00:05:17,348 --> 00:05:20,608
and this never shows up in like
typical user research or like user

108
00:05:20,608 --> 00:05:21,878
feedback or any of that stuff.

109
00:05:22,108 --> 00:05:24,568
So because we were working on
something in this category, I

110
00:05:24,568 --> 00:05:25,948
was like, okay, we have to do it.

111
00:05:26,428 --> 00:05:29,118
We have to like set the, meet
the same bar that Linear met.

112
00:05:29,318 --> 00:05:31,978
And that's kind of when I started
digging into what are all the

113
00:05:31,978 --> 00:05:34,488
different ways that we can enable this.

114
00:05:34,638 --> 00:05:39,978
And we started from like a JSON
API using Orbit to like replicate

115
00:05:39,978 --> 00:05:43,728
the data locally, to GraphQL and
Urql to do something similar.

116
00:05:44,188 --> 00:05:47,008
Um, and then we eventually
ended up on Replicache after,

117
00:05:47,008 --> 00:05:48,398
like, trying a few of those.

118
00:05:48,428 --> 00:05:51,428
Uh, we also tried, I
think, RxDB at some point.

119
00:05:52,088 --> 00:05:55,258
Because we knew that, yeah, we
want to have almost every operation

120
00:05:55,408 --> 00:05:59,248
happen locally, if possible, so
that the feedback is instant.

121
00:05:59,718 --> 00:06:02,008
You know, searching, and this is in
the healthcare space, so searching

122
00:06:02,008 --> 00:06:03,398
through patients should be instant.

123
00:06:03,408 --> 00:06:05,958
Loading up their information
should be instant.

124
00:06:06,058 --> 00:06:10,443
Even if we had a really large data
set on the server, In terms of like,

125
00:06:10,513 --> 00:06:13,413
a single business might have, you
know, tens of thousands of patients.

126
00:06:14,003 --> 00:06:16,783
An individual doctor is
only seeing a small subset.

127
00:06:16,783 --> 00:06:19,713
So having the ability to like,
partially sync the data that

128
00:06:19,713 --> 00:06:21,073
we know the user cares about.

129
00:06:21,283 --> 00:06:24,253
So we spent like, through the
course of building this product,

130
00:06:24,273 --> 00:06:25,863
we tried so many different setups.

131
00:06:25,973 --> 00:06:31,113
And we've probably spent two years of
learning and trying how to do these

132
00:06:31,133 --> 00:06:35,363
patterns before we landed on something
where, one, like the tools, like

133
00:06:35,363 --> 00:06:36,303
I said, we ended up on Replicache.

134
00:06:36,303 --> 00:06:40,573
Replicache is a tool that we liked, and
two, like, As people building products,

135
00:06:40,573 --> 00:06:43,983
like we understood how to like, really
take advantage of it, how to structure

136
00:06:43,983 --> 00:06:45,393
things and where to pay attention.

137
00:06:45,753 --> 00:06:47,903
So that product is called Bumi.

138
00:06:48,683 --> 00:06:50,743
Uh, we actually ended up
deciding to pivot away from it.

139
00:06:50,743 --> 00:06:54,063
Uh, like we have, we have some customers,
but it just ended up not being a

140
00:06:54,063 --> 00:06:55,743
market that was particularly large.

141
00:06:56,133 --> 00:06:59,143
And so we wanted to switch to
something that was a lot more,

142
00:06:59,243 --> 00:07:01,643
like, wide, like anyone can use.

143
00:07:02,313 --> 00:07:05,413
And something that we personally
would use, I found that any product

144
00:07:05,413 --> 00:07:09,263
I build where I personally use it, it
just comes out like 10 times better.

145
00:07:09,683 --> 00:07:13,023
It's just way easier to understand the
problems and be motivated to fix them.

146
00:07:13,353 --> 00:07:15,483
So we're working on a new
product called Radiant now.

147
00:07:15,893 --> 00:07:18,923
And that is a personal finance
application, which again,

148
00:07:18,933 --> 00:07:21,333
there's thousands of, very
similar to the Linear story.

149
00:07:21,883 --> 00:07:25,133
But we really believe building,
like, a very power user

150
00:07:25,133 --> 00:07:27,358
productivity focused version of it.

151
00:07:27,528 --> 00:07:29,778
There's like interesting
room in the market for that.

152
00:07:30,018 --> 00:07:33,578
So the one other thing just to kind of
cap off the story is, uh, so between

153
00:07:33,578 --> 00:07:38,488
those two things, uh, working on SST, we
also kicked off a new project there, the

154
00:07:38,488 --> 00:07:40,148
SST console, which I mentioned earlier.

155
00:07:40,388 --> 00:07:43,998
Kind of a similar story where this
is a tool that you use alongside

156
00:07:43,998 --> 00:07:44,938
your day to day development.

157
00:07:44,948 --> 00:07:46,618
You're using all the time.

158
00:07:46,998 --> 00:07:51,468
Having every single thing be fast
really makes a difference in the end

159
00:07:51,468 --> 00:07:56,618
feeling that users have of the product,
so we decided to go with the same kind

160
00:07:56,618 --> 00:07:58,718
of local-first ish model for that.

161
00:07:58,888 --> 00:08:00,728
And that one is completely open source.

162
00:08:00,758 --> 00:08:02,548
We were really public about building it.

163
00:08:02,928 --> 00:08:07,433
I think a lot of people were exposed to
the idea of This pattern, and we've seen

164
00:08:07,433 --> 00:08:12,083
people like, kind of take that project
and like, use a basis, use it as a

165
00:08:12,083 --> 00:08:13,353
basis for things that they're building.

166
00:08:13,573 --> 00:08:16,983
So yeah, I think for me it's
always been about delivering

167
00:08:17,113 --> 00:08:19,963
a much higher user experience.

168
00:08:19,993 --> 00:08:25,073
I really feel like at some point
the web was really focused on how

169
00:08:25,073 --> 00:08:27,623
can we make the web feel native,
and that was like the obsession.

170
00:08:28,103 --> 00:08:33,178
And for some reason that like, kind of
went out of popularity, but I personally

171
00:08:33,178 --> 00:08:37,488
still care about that as an end user when
I use products and they're slow and laggy.

172
00:08:37,908 --> 00:08:39,318
I want everything to be my browser.

173
00:08:39,328 --> 00:08:41,888
I like that and I want people
building those things to care

174
00:08:41,888 --> 00:08:44,368
about those things because I'm
just going to be happier as a user.

175
00:08:44,388 --> 00:08:45,398
And it's kind of been my.

176
00:08:45,933 --> 00:08:48,813
My reasoning to really like, you know,
spread the word about this stuff.

177
00:08:49,203 --> 00:08:49,613
Yeah.

178
00:08:49,673 --> 00:08:52,673
Everything you've just said
deeply, deeply resonates with me.

179
00:08:52,713 --> 00:08:56,953
I'm similarly also very inspired
by, by the folks at Linear, how

180
00:08:56,953 --> 00:08:59,513
much value they put into the craft.

181
00:08:59,783 --> 00:09:03,363
I was actually just, uh, as a
little anecdote, I was just having

182
00:09:03,363 --> 00:09:08,033
drinks last night, uh, with Julian
from the, the, the Linear team.

183
00:09:08,083 --> 00:09:11,613
And we were also chatting about
this and similar to what you've

184
00:09:11,613 --> 00:09:13,863
described as that it's so tricky.

185
00:09:13,863 --> 00:09:18,423
It never shows up in your user interviews,
et cetera, that people say like, Oh,

186
00:09:18,423 --> 00:09:22,213
like I'm really annoyed that this
button takes like 300 milliseconds.

187
00:09:22,213 --> 00:09:26,093
But if it was instant, then I think
people will really, uh, share that.

188
00:09:26,363 --> 00:09:30,948
And it's basically like a, more of like
a death by a thousand paper cuts, and

189
00:09:30,998 --> 00:09:35,568
it's too hard to enumerate the thousand
paper cuts, but it's still kind of clear

190
00:09:35,588 --> 00:09:37,508
that the product is not very smooth.

191
00:09:37,798 --> 00:09:41,738
But once you really, once you're using
Linear, then there is no going back.

192
00:09:42,098 --> 00:09:44,668
And this seems to be also
still like a challenge in terms

193
00:09:44,668 --> 00:09:45,918
of communication for them.

194
00:09:46,188 --> 00:09:49,558
How do they articulate to someone
who has not tried it out yet?

195
00:09:49,808 --> 00:09:51,168
What the difference is?

196
00:09:51,543 --> 00:09:55,733
It's that overall quality and, but
I think they're doing a great job of

197
00:09:55,733 --> 00:09:59,733
just being sort of like the lighthouse
example now of like what that next

198
00:09:59,733 --> 00:10:03,833
generation category defining product
feels like and should be like.

199
00:10:04,223 --> 00:10:07,943
So I think they're, they've like
bootstrapped their way out of that, that

200
00:10:07,943 --> 00:10:13,593
problem and it's very inspiring for me
where I'm like my JIRA is kind of music

201
00:10:13,593 --> 00:10:18,613
apps where I am annoyed by the thousand
paper cuts that you have in when you're

202
00:10:18,613 --> 00:10:21,688
using Spotify or SoundCloud, et cetera.

203
00:10:22,018 --> 00:10:27,608
So many of those supposed apps feel
more like websites that really like

204
00:10:27,628 --> 00:10:32,198
Winamp was a, or iTunes back in the
golden days, that was a much superior

205
00:10:32,198 --> 00:10:34,048
user experience to what we have today.

206
00:10:34,048 --> 00:10:39,528
We have maybe a richer ecosystem in terms
of available music, but the actual user

207
00:10:39,538 --> 00:10:46,058
experience that has really suffered and
I similarly also care a lot about how

208
00:10:46,068 --> 00:10:48,348
native can you make a web app feel like.

209
00:10:48,518 --> 00:10:53,454
And not just, end up with your
ambitions on like a website level.

210
00:10:54,144 --> 00:10:56,264
So, uh, that deeply resonates.

211
00:10:56,504 --> 00:11:00,954
I think there is, it's both, uh, equally
exciting to explore that from a user

212
00:11:00,954 --> 00:11:02,604
experience, what really drove you.

213
00:11:02,974 --> 00:11:06,674
But I think there's also a lot
of potential from a developer

214
00:11:06,794 --> 00:11:11,414
experience point of view, where I
think there's also so much stuff

215
00:11:11,414 --> 00:11:12,959
we just put up with as a developer.

216
00:11:12,959 --> 00:11:17,999
So I'm also curious to hear more on that,
but yeah, you, you mentioned that you

217
00:11:18,009 --> 00:11:24,179
had a one to two years of explorations
early on that, where you figured out

218
00:11:24,189 --> 00:11:27,679
how not to do it, I'd love to hear a
bit more about those failed attempts.

219
00:11:28,554 --> 00:11:33,184
Yeah, so I think, the spectrum
really was just us dipping a toe to

220
00:11:33,184 --> 00:11:36,254
then going further and further and
further with how much is done locally.

221
00:11:36,714 --> 00:11:40,941
So, I think initially, it's, that
sounds weird to everyone, right?

222
00:11:40,941 --> 00:11:45,251
Like, what do you mean replicate
the whole data to the end client?

223
00:11:45,261 --> 00:11:46,091
Like, it's too big.

224
00:11:46,091 --> 00:11:46,851
Like, that can't work.

225
00:11:46,861 --> 00:11:47,871
Or like, what about this?

226
00:11:47,871 --> 00:11:48,251
What about that?

227
00:11:48,251 --> 00:11:48,721
What about that?

228
00:11:49,161 --> 00:11:51,321
Uh, so I understand the hesitation.

229
00:11:51,881 --> 00:11:55,691
But any like half step in that direction,
it just kind of a gateway to like, just

230
00:11:55,691 --> 00:11:57,101
replicating more and more and more.

231
00:11:57,131 --> 00:11:59,121
Cause you just want more and
more and more to be instant.

232
00:11:59,131 --> 00:12:03,586
So I had a very traditional mindset
around it, which is, okay, we have an

233
00:12:03,586 --> 00:12:07,706
API, the API serves data and like, we're
going to like cache some of that locally.

234
00:12:07,966 --> 00:12:09,586
And I think a lot of people
are already doing this.

235
00:12:09,586 --> 00:12:13,096
Like a lot of stuff, like react-query
like gives you this starts to like put

236
00:12:13,096 --> 00:12:17,696
you in that direction where just caching
stuff and then like refetching, you know,

237
00:12:17,696 --> 00:12:20,246
when the window becomes active again,
it kind of gives you some of this like

238
00:12:20,246 --> 00:12:24,956
real time local-first feel, but then you
start to hit the limits with that, where.

239
00:12:25,173 --> 00:12:28,049
If you're like, if you're looking
for stuff that's not literally in

240
00:12:28,049 --> 00:12:31,889
the exact view, you're then kind of
round tripping with the server again.

241
00:12:32,409 --> 00:12:37,459
And I think the key thing to understand
is, is if you're building an app that

242
00:12:37,459 --> 00:12:42,813
people are actually using every day,
the initial load time is really not

243
00:12:42,813 --> 00:12:44,143
something you need to care about.

244
00:12:44,273 --> 00:12:47,046
The first time they load the
app, like let's say they like

245
00:12:47,046 --> 00:12:49,316
log out or it's a new computer or
whatever, they're setting it up.

246
00:12:49,756 --> 00:12:52,906
Okay, like maybe they're downloading
a couple megabytes of stuff.

247
00:12:53,206 --> 00:12:57,769
That's going to be slower than You
visiting some public website that's

248
00:12:57,769 --> 00:13:02,209
like optimized around like the initial
load time, of course, but once that

249
00:13:02,209 --> 00:13:06,789
initial cost is paid, every single
interaction that they have going

250
00:13:06,789 --> 00:13:09,599
forward from there is insanely fast.

251
00:13:09,619 --> 00:13:13,589
And that trade off is so worth it for
apps that people actually use as a joke.

252
00:13:13,659 --> 00:13:17,699
I like to make out is that the
web has become so obsessed with

253
00:13:17,719 --> 00:13:21,849
optimizing for websites where people
visit and leave as fast as possible.

254
00:13:22,209 --> 00:13:25,284
I'm like, If you're working on
something like that, totally get it.

255
00:13:25,304 --> 00:13:27,894
Like totally get all the, the SSR stuff.

256
00:13:27,914 --> 00:13:31,434
Everyone's obsessed with all the, like
the infinite levels of like CDN caching

257
00:13:31,434 --> 00:13:32,514
and the little optimizations there.

258
00:13:32,514 --> 00:13:35,864
I totally understand that, like
minimizing bundle size, all that stuff.

259
00:13:36,314 --> 00:13:38,694
But a lot of people work on SaaS products.

260
00:13:38,724 --> 00:13:42,788
Most of the products that I use every
day are not, don't fit in that category.

261
00:13:42,788 --> 00:13:45,418
I'm using them every day, like
just preload stuff for me.

262
00:13:45,418 --> 00:13:48,068
And I feel this way about some
of the biggest products, right?

263
00:13:48,068 --> 00:13:49,238
Like think about GitHub.

264
00:13:49,408 --> 00:13:51,988
I'm an open source developer,
like, my day to day job is

265
00:13:52,008 --> 00:13:53,508
maintaining open source projects.

266
00:13:53,868 --> 00:13:57,498
I'm in GitHub all day, clicking
through issues, looking through

267
00:13:57,498 --> 00:13:58,938
commits, looking at PRs.

268
00:13:59,328 --> 00:14:03,458
It is so frustratingly slow how
almost every single interaction

269
00:14:04,038 --> 00:14:05,388
results in like a page load.

270
00:14:05,748 --> 00:14:09,748
GitHub knows, okay, you're not going
to send me all of GitHub to me locally.

271
00:14:10,118 --> 00:14:13,198
But you know there's these three
repos I work on every single day.

272
00:14:13,703 --> 00:14:15,483
Sync that locally, sync
that optimistically.

273
00:14:15,493 --> 00:14:19,033
Like that would save me so much
time and frustration and energy.

274
00:14:19,173 --> 00:14:20,213
And actually scratch that.

275
00:14:20,223 --> 00:14:21,353
It's not really about the time.

276
00:14:21,393 --> 00:14:22,873
It's really about the energy for me.

277
00:14:22,973 --> 00:14:27,013
You can spend four hours doing
work that saps your energy and four

278
00:14:27,013 --> 00:14:28,393
hours where you feel empowered.

279
00:14:28,443 --> 00:14:30,913
And to me, like good apps like this.

280
00:14:31,423 --> 00:14:33,803
I like feel super empowered
and it's not sapping my energy.

281
00:14:33,803 --> 00:14:35,483
I'm not drained after the four hours.

282
00:14:35,623 --> 00:14:37,273
I'm like ready to go on to my next thing.

283
00:14:37,273 --> 00:14:37,543
Right.

284
00:14:37,973 --> 00:14:40,773
And yeah, some of these biggest apps
that are productivity apps are so

285
00:14:40,783 --> 00:14:42,723
built like traditional websites.

286
00:14:43,533 --> 00:14:44,083
Definitely.

287
00:14:44,113 --> 00:14:44,403
Yeah.

288
00:14:44,403 --> 00:14:47,093
I mean, the, the use case that
you've mentioned in regards to

289
00:14:47,113 --> 00:14:49,743
GitHub is, is an excellent example.

290
00:14:49,753 --> 00:14:51,813
Like for, like you have those.

291
00:14:52,163 --> 00:14:58,523
units that are really self contained,
most repos don't have hundred of thousand

292
00:14:58,523 --> 00:15:03,418
of issues it's really easy, like takes
roughly the same amount of data that

293
00:15:03,438 --> 00:15:08,334
like your initial JavaScript bundles took
to just download the entire, thing as a

294
00:15:08,334 --> 00:15:13,034
SQLite database or like in another format,
and then just have it there available.

295
00:15:13,224 --> 00:15:17,484
Since you're navigating so much within
the scope of a GitHub repo, whether

296
00:15:17,484 --> 00:15:21,999
it's Between GitHub issues or going
to like a pull request or something

297
00:15:22,259 --> 00:15:27,439
and whatever paper cuts you experience
there, it really lowers your effort

298
00:15:27,439 --> 00:15:29,389
of like wanting to go the extra mile.

299
00:15:29,409 --> 00:15:32,879
Whether you want to respond to
someone's like, in a GitHub comment.

300
00:15:33,129 --> 00:15:37,659
I think, uh, Jamie Kyle, actually, I
think he ran a couple of experiments

301
00:15:37,659 --> 00:15:43,109
there that's literally faster on GitHub
to open a new tab for a link and have,

302
00:15:43,119 --> 00:15:46,934
get the server side rendered stuff than
dealing with like the, The, the rail

303
00:15:46,944 --> 00:15:50,114
style in navigation on the existing site.

304
00:15:50,194 --> 00:15:53,314
And that speaks exactly to,
to the symptoms that you've,

305
00:15:53,404 --> 00:15:54,394
that you've described.

306
00:15:54,594 --> 00:15:57,194
I will also call out a project.

307
00:15:57,214 --> 00:16:00,514
I don't fully remember the name
anymore, but someone on Twitter, I

308
00:16:00,524 --> 00:16:05,894
think was working on, on exactly that,
like a little GitHub client that is

309
00:16:05,894 --> 00:16:10,484
local-first inspired, that pulls down
your data that you're dealing with to

310
00:16:10,484 --> 00:16:12,224
make exactly these interactions fast.

311
00:16:12,224 --> 00:16:13,124
Maybe you know the name.

312
00:16:13,409 --> 00:16:15,479
Yeah, so I actually
tweeted asking about this.

313
00:16:15,479 --> 00:16:17,099
I remember seeing it and
I couldn't remember it.

314
00:16:17,099 --> 00:16:20,429
And I think it was, uh,
by Devin, the Parcel JS.

315
00:16:20,999 --> 00:16:22,789
Yeah, so I saw him
messing around with that.

316
00:16:22,789 --> 00:16:26,849
I don't know if he ever, like, finished
it or released it or anything, but

317
00:16:26,849 --> 00:16:29,079
yeah, this is so desperately needed.

318
00:16:29,584 --> 00:16:32,294
GitHub isn't going to do it, I don't
think, because it's so outside the

319
00:16:32,294 --> 00:16:33,494
scope of how their system works.

320
00:16:33,524 --> 00:16:36,994
But just someone, please, just
build a thing that syncs the

321
00:16:36,994 --> 00:16:39,494
issues and PRs optimistically.

322
00:16:39,494 --> 00:16:40,854
And you're going to save me so much.

323
00:16:40,884 --> 00:16:42,424
I'll pay for this product easily.

324
00:16:42,424 --> 00:16:45,304
I don't know how big the market is
for people that care this much, but it

325
00:16:45,304 --> 00:16:48,894
doesn't seem like that much work because
it's just a single repository view

326
00:16:48,894 --> 00:16:50,464
and some of the stuff that's in there.

327
00:16:51,224 --> 00:16:52,164
And you could totally do this.

328
00:16:52,204 --> 00:16:52,664
Yeah.

329
00:16:53,284 --> 00:16:54,604
This is kind of what I was saying before.

330
00:16:54,909 --> 00:16:57,419
I'm mostly speaking as a developer,
like building these things.

331
00:16:57,449 --> 00:17:00,869
But the end thing I
care about is as a user.

332
00:17:01,314 --> 00:17:03,604
I just want more of this
stuff out there in the world.

333
00:17:03,604 --> 00:17:04,674
So I'm not as frustrated.

334
00:17:04,994 --> 00:17:06,044
I definitely agree.

335
00:17:06,044 --> 00:17:10,464
And like, I applaud you for like going
that adventurous path and that extra

336
00:17:10,464 --> 00:17:16,444
mile with SST console, since I think you
had the right intuition there and it is

337
00:17:16,484 --> 00:17:21,924
paying off in terms of just how fast that
feels to use and how much, like you say,

338
00:17:21,924 --> 00:17:23,784
like it no longer drains your energy.

339
00:17:23,784 --> 00:17:23,944
Yeah.

340
00:17:24,059 --> 00:17:26,009
It gives you energy using that.

341
00:17:26,409 --> 00:17:30,879
And once you had that experience,
you'd really like every loading spinner

342
00:17:30,889 --> 00:17:34,879
that you see is so much more painful
afterwards when you're like using,

343
00:17:35,059 --> 00:17:38,129
for example, the, Cloudflare console,
it's like the same thing there.

344
00:17:38,129 --> 00:17:41,869
Like you're within a project , you
have that many deployed workers and

345
00:17:41,869 --> 00:17:43,819
you just want to navigate between that.

346
00:17:43,819 --> 00:17:46,049
It's fine that my logs stream in.

347
00:17:46,379 --> 00:17:49,539
But all the metadata around
that should just be instant.

348
00:17:49,719 --> 00:17:52,209
It's a tiny amount of data.

349
00:17:52,239 --> 00:17:55,819
And like the majority of apps, if you
really look at what data people are

350
00:17:55,819 --> 00:17:57,699
constantly going between, it is so small.

351
00:17:58,239 --> 00:18:02,889
So yeah, you figured out like the, the
patterns early on or rather that you've

352
00:18:02,919 --> 00:18:06,319
realized, okay, you started with a bit
of caching, a bit of more caching, a

353
00:18:06,319 --> 00:18:10,349
bit of more caching, and you didn't
quite find the right line to draw.

354
00:18:10,409 --> 00:18:11,459
So you just, okay.

355
00:18:11,559 --> 00:18:13,939
We're going to just
bring over all the data.

356
00:18:14,289 --> 00:18:18,659
Did you have other sort of learnings
where you had to rewire your brain?

357
00:18:19,026 --> 00:18:19,396
Yeah.

358
00:18:19,396 --> 00:18:24,633
So I think, uh, one other middle step
we had was we tried it through GraphQL.

359
00:18:24,743 --> 00:18:28,253
We weren't particularly
interested in the GraphQL part.

360
00:18:28,373 --> 00:18:32,213
It was, it just happened to be
that, uh, Urql, the GraphQL client.

361
00:18:32,983 --> 00:18:36,768
It implemented a lot of, uh, the
local-first stuff like you could

362
00:18:37,028 --> 00:18:40,168
replicate the whole database
locally and because GraphQL has a

363
00:18:40,168 --> 00:18:44,331
nice, idea of like relationships
between objects, the data format

364
00:18:44,331 --> 00:18:45,631
locally could be pretty intelligent.

365
00:18:45,631 --> 00:18:48,838
like, downloaded 1 thing, it knows
how it's related to another thing.

366
00:18:48,838 --> 00:18:52,048
So if you query it from a different
path, it can, like, resolve it locally.

367
00:18:52,158 --> 00:18:53,928
So there's just some
clever things that it did.

368
00:18:54,108 --> 00:18:55,358
And we thought that was really cool.

369
00:18:55,778 --> 00:19:00,558
But what ended up sucking was
we didn't really like GraphQL.

370
00:19:01,118 --> 00:19:06,428
And everything you did, even local
operations, required GraphQL as input.

371
00:19:06,838 --> 00:19:07,888
which again is fine.

372
00:19:07,898 --> 00:19:10,308
It's just, it just wasn't
really clicking for us.

373
00:19:10,358 --> 00:19:15,326
And again, it still had this, uh,
There was a limitation of like, it

374
00:19:15,326 --> 00:19:19,116
wasn't really meant or initially
designed to have all data locally,

375
00:19:19,116 --> 00:19:22,206
so it's all like, there's always like
some stealing or some performance

376
00:19:22,206 --> 00:19:23,876
issue or something you run into.

377
00:19:24,346 --> 00:19:28,256
So when we went all in on having,
okay, like we, the system is primarily

378
00:19:28,256 --> 00:19:30,056
designed around syncing the data locally.

379
00:19:30,306 --> 00:19:34,376
What we found actually, and I think the
Linear people talk about this too, is.

380
00:19:34,524 --> 00:19:38,124
The developer experience around
this became a lot more simple.

381
00:19:38,374 --> 00:19:42,994
So my wife, who I work on this
stuff with, she is not an engineer.

382
00:19:43,004 --> 00:19:44,724
She does everything else outside of it.

383
00:19:44,824 --> 00:19:48,554
But in the past couple of months, we're
like, why are we drawing that boundary?

384
00:19:48,554 --> 00:19:50,334
Just learn how to be more hands on.

385
00:19:50,774 --> 00:19:53,504
And so she's been learning like
how to actually like write the code

386
00:19:53,504 --> 00:19:56,394
and build these things and she's
making like fantastic progress.

387
00:19:56,924 --> 00:20:00,004
One of the things that's
been crazy helpful is.

388
00:20:00,554 --> 00:20:01,964
All the data's just there locally.

389
00:20:02,364 --> 00:20:05,844
So for her, even though she's a
beginner, it's such a simple model.

390
00:20:05,864 --> 00:20:10,014
She's not like figuring out the round trip
with the server, like syncing all that.

391
00:20:10,014 --> 00:20:14,064
Like, I handle all that, and I make sure,
like I figure out how the data looks like

392
00:20:14,064 --> 00:20:16,624
on the back end, and I make sure it's
all synced correctly to the front end.

393
00:20:17,074 --> 00:20:21,864
From there, there's not all this weird
like, loading states, or like fetching it,

394
00:20:21,864 --> 00:20:25,404
or like just a whole bunch of complexity
around getting data back and forth.

395
00:20:25,829 --> 00:20:28,309
It's solved in one part of your
app, and then you never have to

396
00:20:28,309 --> 00:20:29,369
think about it anywhere else.

397
00:20:29,849 --> 00:20:33,029
So just from like a team productivity
point of view, like she can build

398
00:20:33,239 --> 00:20:37,629
any feature she wants, even if I
didn't like explicitly think about

399
00:20:37,629 --> 00:20:40,759
it from the backend point of view,
because she has all the data locally.

400
00:20:41,149 --> 00:20:43,819
She's like, I want to create a view
that searches through this set of data.

401
00:20:43,869 --> 00:20:44,679
She can just go do that.

402
00:20:44,699 --> 00:20:45,419
All the data is there.

403
00:20:45,844 --> 00:20:47,144
Very, very straightforward.

404
00:20:47,304 --> 00:20:51,034
And it's actually wild how much of
a productivity boost that has on

405
00:20:51,034 --> 00:20:54,364
your team, because you're not like
constantly building these like back

406
00:20:54,364 --> 00:20:57,634
and forth with every new feature
you're not rebuilding another way to

407
00:20:57,644 --> 00:20:59,004
like sync that data back and forth.

408
00:20:59,494 --> 00:21:00,534
and it's been amazing.

409
00:21:01,204 --> 00:21:02,504
That's so liberating.

410
00:21:02,564 --> 00:21:06,794
Uh, we talked about this also in the
recent episode with Kyle, who drew the

411
00:21:06,794 --> 00:21:11,814
comparison of like going from jQuery to
React where React freed you up of like

412
00:21:11,824 --> 00:21:15,964
that manual view maintenance and now
going from like the, the manual state

413
00:21:15,974 --> 00:21:20,254
transfer across different environments
that frees you up of like that data

414
00:21:20,254 --> 00:21:22,004
management and you can now actually.

415
00:21:22,339 --> 00:21:25,949
Focus on what matters most, like
building a great user experience

416
00:21:25,969 --> 00:21:29,519
and putting the effort into the
pieces that do really matter.

417
00:21:29,899 --> 00:21:35,459
And that simplification that is just so,
so hard to overstate how nice that is.

418
00:21:35,539 --> 00:21:38,259
And I think that also unlocks
a whole bunch of like new.

419
00:21:38,489 --> 00:21:39,099
tooling.

420
00:21:39,109 --> 00:21:45,297
So for Overtone that I co developed
with the project Rffle, or now called

421
00:21:45,297 --> 00:21:48,829
LiveStore, it's always been a first
class citizen to have great dev tools.

422
00:21:49,119 --> 00:21:52,509
And one of the parts of the dev tools
is to have a data browser in there.

423
00:21:52,779 --> 00:21:56,359
So it basically feels like a
Google spreadsheet and really it

424
00:21:56,389 --> 00:21:57,939
also acts as a Google spreadsheet.

425
00:21:57,939 --> 00:22:00,039
You have, you have like visual view.

426
00:22:00,419 --> 00:22:04,079
on all of your data, if you change
something such as like a playlist

427
00:22:04,109 --> 00:22:09,269
title in that data browser, it like
automatically updates in your app.

428
00:22:09,339 --> 00:22:11,959
And there's no question of
like, Oh, do I not need to like

429
00:22:12,219 --> 00:22:14,299
send this to this REST request?

430
00:22:14,309 --> 00:22:18,009
But do I need to also like,
Invalidate this in Redis.

431
00:22:18,059 --> 00:22:20,689
No, you just like set
the data and there it is.

432
00:22:21,319 --> 00:22:21,919
Yeah, that's great.

433
00:22:21,919 --> 00:22:24,259
I mean, a local data route is actually
something that we're definitely

434
00:22:24,259 --> 00:22:29,249
missing, but that's a, yeah, it's like
it enables so many things like that.

435
00:22:29,399 --> 00:22:32,899
Just the debug ability and observability
of what's going on and just being

436
00:22:32,899 --> 00:22:35,799
able to change something in one place
and have it update everywhere, like

437
00:22:35,849 --> 00:22:38,819
in your view and in the backend,
it's just so, it's so much simpler.

438
00:22:38,819 --> 00:22:42,359
And it's weird because I feel like
apps used to kind of work this way.

439
00:22:42,359 --> 00:22:45,469
Like when I got started, I was
building desktop applications.

440
00:22:46,159 --> 00:22:49,516
And I guess there wasn't really
a cloud component in some of

441
00:22:49,516 --> 00:22:51,036
the initial things that I built.

442
00:22:51,176 --> 00:22:53,736
And they were this simple because
the data was just local and like

443
00:22:53,746 --> 00:22:56,436
you'd hit a button and you like
mutate the data and it's it's there.

444
00:22:56,436 --> 00:23:00,006
So yeah, to me it feels like
returning to a simplicity with like

445
00:23:00,396 --> 00:23:03,456
much more power and capabilities
that we didn't have back then.

446
00:23:03,956 --> 00:23:04,466
Exactly.

447
00:23:04,486 --> 00:23:07,956
Plus we now also get the power of
the cloud for collaboration and

448
00:23:07,966 --> 00:23:10,316
like a lot of the, the nice pieces.

449
00:23:10,716 --> 00:23:14,496
But I think there's just been an over
investment over the last 10 years

450
00:23:14,806 --> 00:23:19,816
into having everything be so cloud
centric that like you built like

451
00:23:19,826 --> 00:23:24,446
even a local calculator probably as
like a remote rendered server app.

452
00:23:24,976 --> 00:23:30,426
And, I think now also bringing more
investment into kind of back to the roots,

453
00:23:30,536 --> 00:23:35,206
uh, in, in this way of building, building
apps, I think this will also help more

454
00:23:35,206 --> 00:23:40,796
people who are not quite as adventurous as
you are to, to really explore this before

455
00:23:40,796 --> 00:23:45,286
others do, that this becomes a more viable
standard path that people build apps with.

456
00:23:45,841 --> 00:23:48,481
Yeah, and like there are, like
a lot of stuff becomes simpler.

457
00:23:48,491 --> 00:23:50,371
There's some new stuff you have
to learn, of course, like with

458
00:23:50,371 --> 00:23:52,651
any new paradigm, there's, things
that are a little bit different.

459
00:23:52,731 --> 00:23:57,661
I think some of those involve things
like, so in our case, in the Bumi example,

460
00:23:57,871 --> 00:24:01,721
we unfortunately had customers that
had too much data, where it wasn't as

461
00:24:01,721 --> 00:24:03,151
simple as just syncing it all locally.

462
00:24:03,711 --> 00:24:08,491
So we have to think of like some new
kind of like UX related patterns where

463
00:24:08,651 --> 00:24:12,394
we kind of optimistically sync stuff
that we think the user will care about.

464
00:24:12,394 --> 00:24:15,494
So like the first time you visit
a patient, it might take a little

465
00:24:15,494 --> 00:24:17,914
bit to load because we didn't
sync all the patients locally.

466
00:24:18,384 --> 00:24:23,314
We do sync like a shallow version of the
patient locally for everyone, so they can

467
00:24:23,324 --> 00:24:24,674
search through all of them really quickly.

468
00:24:25,134 --> 00:24:27,264
But to get into the full
details, like you might not.

469
00:24:27,346 --> 00:24:28,826
That's too much data to send to everyone.

470
00:24:29,156 --> 00:24:31,126
So the first time you go
there, it'll be a slow load.

471
00:24:31,126 --> 00:24:33,276
But from that point, we kind
of flag them as, Oh, this

472
00:24:33,276 --> 00:24:34,716
user cares about this patient.

473
00:24:35,156 --> 00:24:37,006
And from then on, we'll
constantly send them updates.

474
00:24:37,256 --> 00:24:40,466
If they haven't visited the patient's
profile for like two weeks or

475
00:24:40,466 --> 00:24:43,176
whatever, then we'll kind of unflag
it as something that they care about.

476
00:24:43,636 --> 00:24:46,256
These are like new patterns
that, you know, they don't really

477
00:24:46,366 --> 00:24:47,266
exist in a traditional app.

478
00:24:47,276 --> 00:24:52,526
But this mixture of local and cloud, you
can get pretty far with tricks like that.

479
00:24:52,536 --> 00:24:55,266
And we kind of have to learn some of
those tricks and some of those ideas.

480
00:24:55,266 --> 00:24:58,041
Because we have a whole like We
have, I forgot what we called it, but

481
00:24:58,041 --> 00:25:02,284
it's like, uh, We have like a system
where you can easily flag stuff as

482
00:25:02,284 --> 00:25:03,704
a user is interested in this thing.

483
00:25:03,754 --> 00:25:06,774
And if you flag it, it starts getting
synced and then it'll get unsynced

484
00:25:06,844 --> 00:25:08,414
after some window that you specify.

485
00:25:08,484 --> 00:25:10,644
So we kind of have to like, you
know, think about that and, and

486
00:25:10,764 --> 00:25:11,824
create a framework around it.

487
00:25:11,824 --> 00:25:12,874
But that's one.

488
00:25:12,874 --> 00:25:15,894
The second thing is like,
obviously handling, And this

489
00:25:15,894 --> 00:25:17,104
isn't unique to local-first.

490
00:25:17,124 --> 00:25:20,524
Anywhere you're doing optimistic
things, obviously there can be

491
00:25:21,159 --> 00:25:22,929
errors that happen on a delay.

492
00:25:23,049 --> 00:25:24,529
Again, it depends on
the type of application.

493
00:25:24,539 --> 00:25:27,639
Like a music player, probably, the
syncing is probably like pretty

494
00:25:27,639 --> 00:25:32,384
straightforward, but for something that's
Looks more like a traditional SaaS app.

495
00:25:32,434 --> 00:25:36,654
There might be sources of truth that
can't be validated entirely locally.

496
00:25:37,204 --> 00:25:40,544
So you'll end up with situations where
the user does something, then goes

497
00:25:40,544 --> 00:25:42,444
away, then the error shows up later.

498
00:25:42,464 --> 00:25:46,984
And like, you need like a whole different
UX pattern when you can't block the user.

499
00:25:47,304 --> 00:25:50,704
It's worth doing because 99 percent
of the time they don't hit that error.

500
00:25:51,014 --> 00:25:52,104
So it's good to let them move on.

501
00:25:52,544 --> 00:25:54,404
But you have to handle a
case where, where they do.

502
00:25:54,414 --> 00:25:57,784
So there's different problems that show
up, but again, it's all in the name

503
00:25:57,804 --> 00:26:00,004
of a better experience to the user.

504
00:26:00,004 --> 00:26:01,284
So totally worth it.

505
00:26:01,284 --> 00:26:03,678
So, let's say you have some kind of.

506
00:26:03,748 --> 00:26:06,918
You can create a new field that needs
to be globally unique in your system.

507
00:26:06,918 --> 00:26:10,438
So let's say, uh, I mean, we can
just use Linear as an example.

508
00:26:10,448 --> 00:26:12,888
Like, you can create a new project
in Linear, but the name of the

509
00:26:12,888 --> 00:26:14,248
project needs to be unique.

510
00:26:14,658 --> 00:26:19,768
there's an impossibly small chance that
you create it and you move on, but someone

511
00:26:19,878 --> 00:26:23,068
had created it at the same time, because
they thought it was their job to do it.

512
00:26:23,598 --> 00:26:26,618
And there's like an issue, because
your write maybe got rejected.

513
00:26:26,618 --> 00:26:30,893
in a typical UI, when you create the
project, you would see a spinner.

514
00:26:31,388 --> 00:26:31,918
Spinning.

515
00:26:32,288 --> 00:26:33,118
Okay, created.

516
00:26:33,468 --> 00:26:36,758
Because you have a spinner there, you
can, like, make sure stuff gets written

517
00:26:36,758 --> 00:26:39,638
correctly and then you don't let the
spinner come back till you know for sure.

518
00:26:40,208 --> 00:26:40,748
It's good.

519
00:26:41,278 --> 00:26:43,978
Um, so anywhere with this like
unique feel type of situation,

520
00:26:43,978 --> 00:26:45,328
we run into this problem.

521
00:26:45,678 --> 00:26:47,128
Our fix is actually pretty simple.

522
00:26:47,128 --> 00:26:49,978
We just have like some kind of
like context thing of like pending

523
00:26:50,228 --> 00:26:51,598
stuff that hasn't been confirmed.

524
00:26:52,078 --> 00:26:55,468
And if it comes back with an
error, we just pop up a toast that

525
00:26:55,468 --> 00:26:57,038
brings them back to the original.

526
00:26:57,363 --> 00:26:58,733
We, like, reload that original content.

527
00:26:58,773 --> 00:27:01,083
If they want, they can click back
and go back to where they were.

528
00:27:01,683 --> 00:27:05,666
And, like, you know, change
the issue that they had.

529
00:27:05,999 --> 00:27:08,369
So I think we found that
pattern to work pretty well.

530
00:27:08,389 --> 00:27:11,469
Obviously, it's like, the
example I gave is really stupid.

531
00:27:11,469 --> 00:27:13,479
Like, no one is ever
going to run into that.

532
00:27:14,219 --> 00:27:17,519
There's some examples that are a little
less stupid, where it is reasonably

533
00:27:17,519 --> 00:27:18,679
possible that it could happen.

534
00:27:18,679 --> 00:27:22,069
But we found this idea of, like,
preserving the context of the

535
00:27:22,079 --> 00:27:23,769
UI and bringing them back to it.

536
00:27:24,484 --> 00:27:26,924
If the error happens,
they can opt to go back.

537
00:27:27,228 --> 00:27:28,428
We found that to work pretty well.

538
00:27:28,848 --> 00:27:31,168
Yeah, I think that's a very
elegant solution for this.

539
00:27:31,198 --> 00:27:34,938
I mean, another possibly even
more aggressive solution to this

540
00:27:35,158 --> 00:27:39,058
would be to say to gate this
feature behind being online.

541
00:27:39,418 --> 00:27:44,428
And to actually like establish some
notion of like a global transaction for

542
00:27:44,428 --> 00:27:49,984
that and, only let the user pass through
this intentional bottleneck if that

543
00:27:49,994 --> 00:27:54,454
has happened, but the way how you've
designed this in a asynchronous way.

544
00:27:54,614 --> 00:27:56,084
I think it's also very elegant.

545
00:27:56,084 --> 00:28:00,984
but I think this is the nice thing that
like local-first affords you or forces

546
00:28:01,004 --> 00:28:05,014
you to do is like, it frees you up from
a whole bunch of stuff you no longer

547
00:28:05,014 --> 00:28:09,234
need to do, but it really forces you
to think about carefully, what are the

548
00:28:09,234 --> 00:28:12,954
domain requirements of your specific app?

549
00:28:13,319 --> 00:28:16,969
And if your domain expert from
the app says like, Hey, this is

550
00:28:16,969 --> 00:28:18,319
what's really important here.

551
00:28:18,319 --> 00:28:22,649
There cannot be two project
names with the same exact name.

552
00:28:23,049 --> 00:28:26,849
Then like you can actually put in
the extra efforts to enforcing that.

553
00:28:27,309 --> 00:28:29,679
And this is what makes
the app worth it later.

554
00:28:29,809 --> 00:28:30,179
Yeah.

555
00:28:30,249 --> 00:28:30,439
Yeah.

556
00:28:30,439 --> 00:28:31,659
And it's, yeah, it's not all or nothing.

557
00:28:31,659 --> 00:28:32,259
You can opt in.

558
00:28:32,259 --> 00:28:34,179
So the thing that you said,
we are in the SC console.

559
00:28:34,179 --> 00:28:37,059
We do that when you're creating a
new workspace, we actually do have a

560
00:28:37,059 --> 00:28:41,349
spinner there because it's like weird
to like, Create a new workspace and get

561
00:28:41,349 --> 00:28:42,849
kicked back 'cause the name was taken.

562
00:28:43,239 --> 00:28:45,489
So yeah, we, we hold you there
And that's like, you know, a more

563
00:28:45,489 --> 00:28:49,039
traditional experience and that's
fine 'cause that's like a very small

564
00:28:49,039 --> 00:28:53,049
percentage of the app where you're
like creating a new workspace.

565
00:28:53,049 --> 00:28:55,449
You do that once when you sign
up and you never do that again.

566
00:28:55,999 --> 00:28:59,239
So yeah, you can kind of granularly
pick where you want a more traditional

567
00:28:59,239 --> 00:29:02,149
blocking approach and where you
want an optimistic approach.

568
00:29:02,419 --> 00:29:05,579
And I think a lot of the people that
are maybe skeptical of the local-first

569
00:29:05,599 --> 00:29:09,399
thing, I think they tend to imagine
it in these extremes of like.

570
00:29:09,874 --> 00:29:12,494
You have to sync all of your data
and obviously that won't work.

571
00:29:12,494 --> 00:29:14,774
Or like you have to have everything
be optimistic and obviously

572
00:29:14,774 --> 00:29:18,184
everything can't be optimistic,
but you can really pick and choose.

573
00:29:18,184 --> 00:29:20,374
It's more about what you default to.

574
00:29:20,384 --> 00:29:23,094
And then you opt out of It's good
to default to optimistic first.

575
00:29:23,094 --> 00:29:24,274
Cause that's, what's great for the user.

576
00:29:24,454 --> 00:29:24,874
Right.

577
00:29:25,274 --> 00:29:29,424
I think in the, in your context of
building SaaS apps, I think there's

578
00:29:29,424 --> 00:29:31,114
kind of layers to this entire thing.

579
00:29:31,114 --> 00:29:33,084
There's like the global system.

580
00:29:33,359 --> 00:29:34,799
That you're still in control of.

581
00:29:34,809 --> 00:29:40,239
That global system is probably not
local-first by all the ideals, but once

582
00:29:40,239 --> 00:29:44,939
you create an account or once you've
created a project, and now you enter like

583
00:29:44,939 --> 00:29:49,859
a smaller scope of that overall system,
and that now is very much local-first

584
00:29:50,089 --> 00:29:51,769
because this is where it actually matters.

585
00:29:51,789 --> 00:29:54,049
It's okay if your users sign up.

586
00:29:54,254 --> 00:29:56,434
takes half a second to load.

587
00:29:56,724 --> 00:29:59,674
But once you're in your productivity
environment, this is where you

588
00:29:59,674 --> 00:30:03,194
want to really have unlock the
benefits that local-first gives you.

589
00:30:03,614 --> 00:30:04,234
Yeah, exactly.

590
00:30:04,234 --> 00:30:06,134
The data, what is the
day to day workflow like?

591
00:30:06,134 --> 00:30:09,564
And that should be, that should be,
you know, an excellent experience.

592
00:30:09,814 --> 00:30:15,694
I think the other area, and we talked
about this a little, is there's also the

593
00:30:15,694 --> 00:30:20,644
desire for apps that don't die because
a company went out of business or like,

594
00:30:20,654 --> 00:30:23,354
you know, They were forced to find a
business model that didn't make sense

595
00:30:23,354 --> 00:30:24,914
for the idea that they were working on.

596
00:30:25,524 --> 00:30:27,464
And I think this does make
a lot of sense, I think.

597
00:30:27,814 --> 00:30:30,624
If you think about something
like a, like a video game.

598
00:30:30,624 --> 00:30:33,924
I mean, video games are different now,
but like, you know, there was a time

599
00:30:33,924 --> 00:30:35,484
where you would buy the video game.

600
00:30:35,514 --> 00:30:39,214
It was a finished product, and it
was on, like, a physical thing, and

601
00:30:39,214 --> 00:30:40,584
you could just run it and play it.

602
00:30:41,254 --> 00:30:41,854
And.

603
00:30:42,379 --> 00:30:43,509
You had that forever.

604
00:30:43,929 --> 00:30:47,479
So, but I mean, now you have like some
games that require you to be online

605
00:30:47,479 --> 00:30:48,989
or it's a, it's a hybrid of both.

606
00:30:48,989 --> 00:30:53,249
And like, you can imagine how at some
point this game won't be playable anymore.

607
00:30:53,249 --> 00:30:55,009
And that's happened to a few things.

608
00:30:55,169 --> 00:30:57,329
I think people feel that way
about applications as well.

609
00:30:57,329 --> 00:30:58,189
And I totally get that.

610
00:30:58,659 --> 00:31:02,009
I personally don't work on anything
where that's like the critical

611
00:31:02,173 --> 00:31:06,313
burning desire where like, you
want it to like really run locally.

612
00:31:06,313 --> 00:31:08,603
You want, you care about the
privacy, you care about whatever.

613
00:31:08,963 --> 00:31:10,353
I like totally get all of that.

614
00:31:10,383 --> 00:31:13,673
It just hasn't intersected with
like the areas that I focus on.

615
00:31:13,843 --> 00:31:18,033
So for me, it's been more about,
uh, just the experience side of it.

616
00:31:18,213 --> 00:31:22,263
And I think the reason is a little bit
tricky to go to that extreme in SaaS.

617
00:31:22,818 --> 00:31:27,674
is a lot of like a portion of your
value is in the end experience.

618
00:31:27,684 --> 00:31:30,044
And like we talked about, I think
people are under delivering there,

619
00:31:30,364 --> 00:31:35,574
but usually it's also tapping into
some kind of bigger data set or bigger

620
00:31:35,574 --> 00:31:38,214
capability that can't really run locally.

621
00:31:38,244 --> 00:31:39,864
So it's usually a mix of the two things.

622
00:31:40,084 --> 00:31:43,378
So I typically will have to
mutate the data outside of

623
00:31:43,378 --> 00:31:44,588
the user interacting with it.

624
00:31:44,598 --> 00:31:47,468
So if you look at something like,
uh, like Radiance, so this is

625
00:31:47,488 --> 00:31:48,798
going to be a personal finance app.

626
00:31:49,028 --> 00:31:51,678
You can totally build a fully
local-first version of this

627
00:31:51,688 --> 00:31:52,838
that runs entirely locally.

628
00:31:53,278 --> 00:31:55,738
That whoever's building the app, it can
be totally encrypted where they don't even

629
00:31:55,738 --> 00:31:57,368
have access to seeing any of this stuff.

630
00:31:57,368 --> 00:31:59,238
And there's like value in
building something like that.

631
00:31:59,668 --> 00:32:04,801
But, you know, with all these advancements
in AI and LLMs, those can actually impact

632
00:32:05,151 --> 00:32:08,821
Personal finance apps a lot in terms of
like making sure that data is cleaned

633
00:32:08,821 --> 00:32:11,941
up correctly, auto categorizing, like
all the things that sucked historically

634
00:32:11,941 --> 00:32:16,808
about these applications, LMS have
a lot of potential to fix that, but

635
00:32:17,288 --> 00:32:20,538
there's not really a good way to do that
in a local-first way, at least today.

636
00:32:20,768 --> 00:32:23,008
So that's why for us, you
know, for building this thing,

637
00:32:23,018 --> 00:32:24,438
it's not going to be this.

638
00:32:25,068 --> 00:32:27,438
thing that runs entirely locally
because we still want the ability to

639
00:32:27,438 --> 00:32:31,848
like process your data using tools
and technologies that, you know,

640
00:32:32,158 --> 00:32:34,238
unfortunately can't run locally today.

641
00:32:34,618 --> 00:32:38,198
Yeah, I think you've touched on a couple
of really interesting points there.

642
00:32:38,218 --> 00:32:43,608
So the, I think right now, the canonical
definition of like, what is local-first

643
00:32:43,628 --> 00:32:48,568
software is as according to the Ink and
Switch essay that lays out the seven

644
00:32:48,598 --> 00:32:53,298
ideals of local-first and I think you're,
You're, nicely sticking to the first four,

645
00:32:53,298 --> 00:32:57,228
which is like about the loading spinners
and that it works offline and so on.

646
00:32:57,528 --> 00:33:01,738
And I think what you've just hinted
at, what you don't do yet is what

647
00:33:01,738 --> 00:33:07,138
local-first calls like the long now
that your app like lives on, even if the

648
00:33:07,168 --> 00:33:09,468
creators are no longer working on it.

649
00:33:09,748 --> 00:33:11,138
And that's very understandable.

650
00:33:11,158 --> 00:33:14,548
That takes a lot of time
to, and effort to put into.

651
00:33:14,883 --> 00:33:17,983
And given that you just have so
much time to work on the app,

652
00:33:18,193 --> 00:33:19,783
that is not your highest priority.

653
00:33:19,973 --> 00:33:25,003
However, what I think is still nice and
a glimmer of hope there for the entire

654
00:33:25,003 --> 00:33:30,323
category of local-first inspired software
is that if at some point you say like,

655
00:33:30,333 --> 00:33:36,233
okay, I'm winding down development on
this app, then you could still much more

656
00:33:36,233 --> 00:33:38,203
easily to put in a bit of extra effort.

657
00:33:38,748 --> 00:33:42,828
to now round up the project
in a local-first way.

658
00:33:42,868 --> 00:33:46,818
I think we've seen a really nice example
of that with another personal finance

659
00:33:46,838 --> 00:33:49,348
app called Actual Budget by James Long.

660
00:33:49,938 --> 00:33:56,428
And so as he no longer had time to work
on that project, it was so much easier now

661
00:33:56,428 --> 00:34:00,788
to transition the app from something that
he hosted as a cloud service to something

662
00:34:00,788 --> 00:34:02,538
that people can just run by themselves.

663
00:34:02,998 --> 00:34:07,898
If you build like those monstrosities
of like giant Kubernetes cloud things,

664
00:34:08,178 --> 00:34:13,828
it's really, really hard to like, tell
someone how to easily just download a DMG

665
00:34:13,848 --> 00:34:18,368
and run this on your MacBook, whereas if
your app is local-first to begin with.

666
00:34:18,608 --> 00:34:23,181
Then, I think it's much easier to
repackage the app that you've built.

667
00:34:23,551 --> 00:34:26,671
And you can trim away a lot of
like the multi tenant stuff that

668
00:34:26,671 --> 00:34:30,921
you need about SaaS and just
package the, the productivity

669
00:34:30,921 --> 00:34:32,991
aspect of the core of your app.

670
00:34:33,081 --> 00:34:39,141
And then I think it's actually quite nice
and easy to achieve lasting software.

671
00:34:39,771 --> 00:34:40,671
Yeah, I agree.

672
00:34:40,671 --> 00:34:41,171
I think so.

673
00:34:41,171 --> 00:34:44,341
And with Radiant, we're
actually, so because we can't.

674
00:34:44,523 --> 00:34:46,923
Do this thing where it's like end
to end encrypted and because of

675
00:34:46,923 --> 00:34:51,533
what, what our goals are, instead,
we're making it dead simple to

676
00:34:51,533 --> 00:34:54,753
fully run the whole system yourself.

677
00:34:54,793 --> 00:34:58,473
If you care about hosting yourself and you
want all the data and a big part, and to

678
00:34:58,473 --> 00:35:00,613
be honest, that's a lot of what SST does.

679
00:35:00,613 --> 00:35:05,003
SST helps you ship very complex software
multiple times in multiple environments.

680
00:35:05,513 --> 00:35:09,513
and so, because Radiant is an SST
app, it is very easy to point it

681
00:35:09,543 --> 00:35:12,633
at your own private infrastructure
and say, I'm just going to have

682
00:35:12,633 --> 00:35:14,373
a self hosted version of this.

683
00:35:14,383 --> 00:35:18,744
And it's, and we're making sure it's
like, As simple as it can be to do

684
00:35:18,744 --> 00:35:23,124
that, and get as close to, like, using
the hosted version because there's

685
00:35:23,124 --> 00:35:24,674
like some weird benefits of that.

686
00:35:24,674 --> 00:35:28,114
Like, so this version that we're building
is going to be mostly built on Cloudflare.

687
00:35:28,464 --> 00:35:31,084
If a lot of people end up self
hosting it, that's great because

688
00:35:31,104 --> 00:35:33,624
Cloudflare is paying for the usage.

689
00:35:33,624 --> 00:35:37,389
Like, The free tier is coming out
of each individual's deployment.

690
00:35:37,429 --> 00:35:39,299
They're like self deploying
it into CloudFlare.

691
00:35:39,509 --> 00:35:42,409
And that's like an interesting model
for, I don't think for radiant, it's

692
00:35:42,409 --> 00:35:45,673
like particularly interesting, but
if you look at, um, there's another

693
00:35:45,673 --> 00:35:49,933
project by, uh, Ben Vinegar, he
works at Sentry, called CounterScale.

694
00:35:50,473 --> 00:35:54,073
So this is a classic, like Google
analytics type product, right?

695
00:35:54,073 --> 00:35:57,003
It does like this web analytics,
the basics, and it's very early on.

696
00:35:57,543 --> 00:35:59,033
But it's not a hosted project.

697
00:35:59,043 --> 00:36:01,463
It's just something that deploys
into your own CloudFlare account.

698
00:36:01,873 --> 00:36:05,283
So he can have a million users
using it for free without ever

699
00:36:05,283 --> 00:36:08,823
really, you know, paying for that
because, you know, CloudFlare is

700
00:36:08,823 --> 00:36:10,793
much more set up to offer that.

701
00:36:11,093 --> 00:36:12,813
I'm very interested in that model.

702
00:36:12,853 --> 00:36:14,803
Uh, cause I think for a lot
of infrastructure pieces

703
00:36:14,803 --> 00:36:15,873
like that, it is a nice.

704
00:36:16,191 --> 00:36:18,221
To have it alongside the
rest of your infrastructure.

705
00:36:18,411 --> 00:36:21,321
I worked a lot in healthcare
environment, which has a lot

706
00:36:21,321 --> 00:36:23,461
of compliance requirements.

707
00:36:23,761 --> 00:36:26,991
And oftentimes I couldn't use the
tool I wanted to use because it

708
00:36:26,991 --> 00:36:29,191
wasn't hostable in my own environment.

709
00:36:29,191 --> 00:36:33,061
So, um, we're pretty excited about
like letting people do more of that.

710
00:36:33,791 --> 00:36:34,471
I love that.

711
00:36:34,501 --> 00:36:37,661
And I think this is like intuitively.

712
00:36:37,944 --> 00:36:42,474
It should be easy to self host your
own software, like whether it's like

713
00:36:42,484 --> 00:36:46,564
some company running it or whether
I just like take the software, put

714
00:36:46,564 --> 00:36:52,148
it on my Raspberry Pi, put it on, on
Cloudflare or AWS, but in reality,

715
00:36:52,168 --> 00:36:53,628
that's very much the exception.

716
00:36:54,058 --> 00:36:57,128
I'd be curious whether you can share
a bit more of like the reasons that

717
00:36:57,138 --> 00:37:00,868
you see why that's so hard and how
you're trying to make that easier.

718
00:37:01,413 --> 00:37:05,663
Yeah, I think, uh, it's funny
because there's a weird alignment

719
00:37:05,673 --> 00:37:06,873
if you think about this.

720
00:37:07,043 --> 00:37:08,313
We are a small team.

721
00:37:08,583 --> 00:37:11,703
If our system is really complicated
to run, that sucks for us.

722
00:37:12,013 --> 00:37:15,543
If we can make our system really easy to
run and really low overhead and we care

723
00:37:15,543 --> 00:37:18,773
about that more than everything, it kind
of starts to look like something that's

724
00:37:18,773 --> 00:37:21,073
easy to self host by anyone, right?

725
00:37:21,073 --> 00:37:24,873
So I think for us, like, a lot of times
we'll choose architectures that look

726
00:37:24,883 --> 00:37:28,904
weird because they're like, Oh, that
looks like the fourth option on the list

727
00:37:28,904 --> 00:37:30,334
of the ways they could have built it.

728
00:37:30,804 --> 00:37:37,898
But it's because we really, really care
about, low operation overhead long term.

729
00:37:38,088 --> 00:37:41,278
So even if it's like, you know, 20
percent harder to build up front, if

730
00:37:41,278 --> 00:37:46,008
it results in like less babysitting on
our end, we'll like choose that option.

731
00:37:46,218 --> 00:37:49,818
And it's because we're very committed
to continuing to be a really small team.

732
00:37:49,898 --> 00:37:52,858
And so we'll, we'll end up picking
those options and those options happen

733
00:37:52,858 --> 00:37:57,118
to align with like, what's, what's
simplest for, for the end end user,

734
00:37:57,118 --> 00:38:00,928
if they're self hosting, I will say
like there is a version of doing

735
00:38:00,928 --> 00:38:03,018
this, which we don't do, which is.

736
00:38:03,883 --> 00:38:06,943
Building your stuff in the most,
like, neutral way possible, so it

737
00:38:06,943 --> 00:38:08,563
can run in literally any environment.

738
00:38:09,003 --> 00:38:14,403
I definitely get that, but you
do end up having to run a lot of

739
00:38:14,443 --> 00:38:18,053
infrastructure on your own to, like,
get any complicated application working.

740
00:38:18,233 --> 00:38:20,093
If you do it in a totally neutral way.

741
00:38:20,493 --> 00:38:24,833
We kind of picked a middle ground where
it's like, we do rely a lot on, like,

742
00:38:24,863 --> 00:38:28,448
in this example, like, we're going to be
using CloudFlare, we're going to be using

743
00:38:28,448 --> 00:38:29,913
workers, we're going to be using their
queues, we're going to be using their

744
00:38:29,933 --> 00:38:31,693
PubSub, all the CloudFlare native things.

745
00:38:32,088 --> 00:38:37,218
So, yeah, if you want to go take
that and run it inside, like, just

746
00:38:37,218 --> 00:38:40,258
a standard server you have, it's
going to be a little bit challenging.

747
00:38:40,518 --> 00:38:42,968
And like, there are adapters and
stuff, and you can figure that out.

748
00:38:43,428 --> 00:38:49,078
But we're starting with just making it
runnable in your own cloud environment.

749
00:38:49,078 --> 00:38:51,418
So you can sign up for a
Cloudflare account and run it.

750
00:38:51,938 --> 00:38:54,448
I know that doesn't like hit the
exact extreme of like being able

751
00:38:54,448 --> 00:38:57,028
to fully run it yourself, but we
think it's like a nice middle ground

752
00:38:57,038 --> 00:38:58,798
for a lot of companies, right?

753
00:38:58,848 --> 00:39:01,298
Companies typically are already
using some form of this.

754
00:39:01,888 --> 00:39:03,778
Getting this stuff deployed
into their own account.

755
00:39:03,868 --> 00:39:05,188
I think it works well.

756
00:39:05,498 --> 00:39:08,588
What's weird is you ask, like,
why isn't this more common?

757
00:39:08,958 --> 00:39:13,118
I think it's actually common in this
weird way that people don't expect.

758
00:39:13,213 --> 00:39:16,573
A lot of companies build
SaaS software, right?

759
00:39:16,593 --> 00:39:20,023
They'll build like, I don't know, let's
say, let's take some random common

760
00:39:20,023 --> 00:39:21,663
thing, like Auth as a service, right?

761
00:39:21,753 --> 00:39:25,143
Like, I'm going to build Auth as
a service that people can use.

762
00:39:25,143 --> 00:39:28,333
And they initially launched
that as like a hosted product.

763
00:39:28,923 --> 00:39:32,203
And nobody uses it except for
people that have no money.

764
00:39:32,643 --> 00:39:35,323
So they have like a lot of users, but
you know, these users don't pay a lot.

765
00:39:35,993 --> 00:39:38,213
They start to try to move up, up market.

766
00:39:38,556 --> 00:39:40,656
They end up with bigger
companies, you know, medium sized

767
00:39:40,686 --> 00:39:42,096
companies, enterprise companies.

768
00:39:42,473 --> 00:39:45,983
They'll all love the product, but
refuse to use a hosted service.

769
00:39:46,543 --> 00:39:49,493
So then they're forced to figure
out how to make their stuff run

770
00:39:49,753 --> 00:39:51,943
inside the customer's AWS accounts.

771
00:39:52,313 --> 00:39:54,463
So if you do look at a lot of
these companies, they kind of

772
00:39:54,463 --> 00:39:57,363
do have this hidden, like thing
that they eventually figured out.

773
00:39:57,813 --> 00:40:00,633
I think companies should realize they're
going to end up in this place anyway.

774
00:40:00,703 --> 00:40:04,953
Like it's very hard to build a big
business purely off of a hosted thing.

775
00:40:04,963 --> 00:40:08,273
Like some people do it when you
really have like a large market,

776
00:40:08,493 --> 00:40:09,623
but oftentimes you're forced to.

777
00:40:09,841 --> 00:40:11,671
Bring yourself inside
someone else's environment.

778
00:40:11,671 --> 00:40:14,351
So I think one way or another,
you're likely to hit that.

779
00:40:14,361 --> 00:40:17,281
So it's good to plan for that upfront and
assume that you're going to run into that.

780
00:40:17,461 --> 00:40:20,461
And we, because we're like, We're
more in the infrastructure space.

781
00:40:20,461 --> 00:40:23,441
We kind of expected that from the
beginning, which is why we care a little

782
00:40:23,441 --> 00:40:25,921
bit more about making all that possible.

783
00:40:26,611 --> 00:40:32,021
So let's imagine I want to follow
this paradigm for Overtone.

784
00:40:32,071 --> 00:40:35,781
And I do think that Cloudflare could
be a very interesting fit for that in

785
00:40:35,781 --> 00:40:41,111
terms of the modern primitives that it
provides, so what would I need to do as

786
00:40:41,121 --> 00:40:45,091
the application developer of Overtone
who buys into that vision and says

787
00:40:45,101 --> 00:40:49,421
like, Hey, I don't want to operate like
the cloud thing for that, but I want

788
00:40:49,421 --> 00:40:54,031
to empower every user to deploy their
own for the benefits that it provides.

789
00:40:54,511 --> 00:40:58,421
What would I as the application
developer need to do to make that happen?

790
00:40:58,781 --> 00:41:00,501
And then also follow up question.

791
00:41:00,561 --> 00:41:04,831
What does someone who wants to deploy
that Which sort of additional stuff

792
00:41:04,831 --> 00:41:08,391
do they need to deal with as opposed
to just using something like Spotify?

793
00:41:08,741 --> 00:41:09,101
Yeah.

794
00:41:09,141 --> 00:41:09,401
Yeah.

795
00:41:09,401 --> 00:41:09,701
Cool.

796
00:41:09,711 --> 00:41:13,348
So I think,  I think the simplest way
to think about it is how hard is it you

797
00:41:13,348 --> 00:41:17,048
for you to spin up a staging environment
for your own application, right?

798
00:41:17,158 --> 00:41:20,648
You want to create an exact copy
of your environment, but you

799
00:41:20,648 --> 00:41:22,108
know, just the staging version.

800
00:41:22,348 --> 00:41:24,468
So this requires bringing up
all the same infrastructure.

801
00:41:24,478 --> 00:41:27,058
It requires like, you know,
running your database migrations

802
00:41:27,058 --> 00:41:28,138
to get the schemas running.

803
00:41:28,158 --> 00:41:29,598
Um, requires a bunch of things.

804
00:41:29,758 --> 00:41:32,528
And, you know, the obvious thing is
you should be using infrastructure

805
00:41:32,528 --> 00:41:33,748
as code to help you do this.

806
00:41:33,748 --> 00:41:36,988
You define all your infrastructure as
code so you can point it at different

807
00:41:36,988 --> 00:41:38,968
environments and run entire copies of it.

808
00:41:39,448 --> 00:41:40,738
That's like the bare minimum.

809
00:41:41,008 --> 00:41:45,398
If you yourself can quickly create
another environment for yourself,

810
00:41:45,438 --> 00:41:46,778
you've kind of solved the problem.

811
00:41:46,778 --> 00:41:49,268
Now someone else can
follow those same steps.

812
00:41:49,678 --> 00:41:51,688
Where they're just cloning
your project and running.

813
00:41:52,198 --> 00:41:55,038
You might be using Terraform, you
might be using SST, whatever it is.

814
00:41:55,088 --> 00:41:58,208
Uh, you can do a thing,
deploy with your credentials.

815
00:41:58,248 --> 00:42:00,508
And the same thing ends
up in your account.

816
00:42:00,718 --> 00:42:03,018
Where this is a little bit
challenging is updates.

817
00:42:03,198 --> 00:42:05,348
So obviously, you know,
you have new versions.

818
00:42:05,348 --> 00:42:07,798
People can clone and redeploy, whatever.

819
00:42:07,908 --> 00:42:11,098
But there's sometimes
operationally challenging updates.

820
00:42:11,098 --> 00:42:12,768
Like you might have like a schema change.

821
00:42:13,128 --> 00:42:15,968
You might have, uh, like
data needs to be migrated.

822
00:42:16,418 --> 00:42:21,133
So, ultimately, the thing to always
go back to is how do you make it

823
00:42:21,133 --> 00:42:22,773
easy for your own team to do that?

824
00:42:23,013 --> 00:42:24,983
Are there programmatic
ways of doing all this?

825
00:42:25,023 --> 00:42:29,116
Or, like, if you need to do ad hoc
random stuff and that's part of your

826
00:42:29,126 --> 00:42:32,136
workflow, it's going to be annoying
for your end user to self host because

827
00:42:32,136 --> 00:42:34,556
then you need to, like, send them
the instructions, they need to do it,

828
00:42:34,886 --> 00:42:36,246
they might, like, do it incorrectly.

829
00:42:36,456 --> 00:42:39,136
So, if everything is tracked
in code and is automated and is

830
00:42:39,136 --> 00:42:40,999
programmatic, It's good for your team.

831
00:42:41,099 --> 00:42:42,896
That's good for the end user.

832
00:42:43,266 --> 00:42:46,116
and for an end user, in terms of
what they should expect, if you are

833
00:42:46,116 --> 00:42:51,233
using some version of the cloud, you
should hope that the thing you're self

834
00:42:51,243 --> 00:42:55,473
hosting is taking advantage of as many
managed services as possible, right?

835
00:42:55,863 --> 00:42:57,403
So I had this issue with PostHog.

836
00:42:57,743 --> 00:42:59,693
So PostHog is an open
source analytics tool.

837
00:43:00,358 --> 00:43:02,808
And when I was exploring it for
my healthcare thing, I was like,

838
00:43:02,808 --> 00:43:04,408
okay, we'd have to self host it.

839
00:43:04,838 --> 00:43:06,628
Let me go look at the
first self hosting steps.

840
00:43:07,058 --> 00:43:08,818
Step one, set up Kubernetes.

841
00:43:09,168 --> 00:43:14,548
Right, immediately there, I'm like, I
like, found a way to finally free myself

842
00:43:14,548 --> 00:43:16,638
of Kubernetes for my main application.

843
00:43:16,648 --> 00:43:19,098
I don't want to like go, have to
go manage a Kubernetes cluster

844
00:43:19,098 --> 00:43:20,948
again, just for this thing.

845
00:43:21,168 --> 00:43:24,628
So you should hope that, you
should pick tools that use

846
00:43:25,168 --> 00:43:27,818
managed, versions of these things.

847
00:43:27,828 --> 00:43:30,998
That's why, like, we typically focus
a little bit more on some of the

848
00:43:31,018 --> 00:43:33,278
serverless stuff, because it's very easy.

849
00:43:33,658 --> 00:43:37,338
If our app just runs as a Lambda
function inside of someone's

850
00:43:37,338 --> 00:43:41,088
AWS account, or as a Cloudflare
worker, there's almost no overhead.

851
00:43:41,098 --> 00:43:44,318
You're not like, you don't have
to like set up like Datadog

852
00:43:44,398 --> 00:43:46,808
to like monitor the memory and
like scale this up, up and down.

853
00:43:47,188 --> 00:43:52,058
It sucks to do that for like a small
tool that you're adding to your project.

854
00:43:52,208 --> 00:43:56,358
So we try to make use of managed servers
as much as possible so that the end user

855
00:43:56,358 --> 00:43:59,098
doesn't have as much operational overhead.

856
00:43:59,528 --> 00:44:01,338
and again, some people
are willing to do that.

857
00:44:01,378 --> 00:44:04,558
It's just, uh, it's obviously a
spectrum with all of these things.

858
00:44:04,948 --> 00:44:09,128
I do think it's a double edged sword while
it like really takes away that operational

859
00:44:09,188 --> 00:44:11,678
burden and operational overhead.

860
00:44:11,948 --> 00:44:17,563
It's not just about, uh, deployment cycles
and like the update cycles of the app

861
00:44:17,563 --> 00:44:22,333
that you're deploying, you potentially
also need to update a, like from database

862
00:44:22,353 --> 00:44:26,703
version A to database version B of like
just a database server that's running or

863
00:44:26,703 --> 00:44:28,483
like your analytics server or whatever.

864
00:44:28,813 --> 00:44:30,983
So that certainly takes a lot more effort.

865
00:44:31,393 --> 00:44:36,473
However, on a longer time horizon,
if you do rely on managed services,

866
00:44:36,953 --> 00:44:40,763
they might just at some point send
out a notice and say like, Hey, next

867
00:44:40,763 --> 00:44:44,158
quarter We're shutting down like
that plan that you're relying on.

868
00:44:44,478 --> 00:44:47,808
So you're also in some regards
might be building on quicksand.

869
00:44:48,138 --> 00:44:53,078
I think the, the larger a services
such as Cloudflare, I think the

870
00:44:53,078 --> 00:44:57,298
chances that the rug is being pulled
underneath you are probably lower.

871
00:44:57,928 --> 00:44:59,818
But it's always a double edged sword.

872
00:44:59,868 --> 00:45:04,808
And so my preference typically is in
terms of the architecture that I'm using

873
00:45:05,058 --> 00:45:07,088
is like to go as simple as possible.

874
00:45:07,108 --> 00:45:11,298
This, for example, why I'm also very
drawn to SQLite and I love the, all

875
00:45:11,298 --> 00:45:16,298
of the, the new tooling being built
around SQLite since SQLite that's, no

876
00:45:16,298 --> 00:45:17,798
one's going to take that away from me.

877
00:45:17,798 --> 00:45:19,258
It's just like a little file.

878
00:45:19,688 --> 00:45:22,578
That I can put on a SD card or whatever.

879
00:45:22,908 --> 00:45:27,638
And, uh, that's still gonna like similar
to that computer game from like the 1980s.

880
00:45:28,038 --> 00:45:30,388
that's still gonna
work, in, in the future.

881
00:45:30,388 --> 00:45:33,508
And I think that's a great way
to preserve data and you can

882
00:45:33,518 --> 00:45:35,328
still do so much with that.

883
00:45:35,488 --> 00:45:39,618
So I think that's sort of like
a third option, uh, instead of

884
00:45:39,648 --> 00:45:44,278
going with like hosted or, Very
scary self hosted infrastructure.

885
00:45:44,498 --> 00:45:48,738
If you make the self hosted
infrastructure just that simple to

886
00:45:48,738 --> 00:45:52,728
rely on something like, like something
that's almost serverless by default,

887
00:45:53,048 --> 00:45:57,468
like SQLite, I think that's a,
that's a very attractive idea for me.

888
00:45:57,773 --> 00:45:58,763
Yeah, no, I agree.

889
00:45:58,763 --> 00:46:01,063
And with everything I'm saying,
it's always like you have

890
00:46:01,063 --> 00:46:02,193
to exercise your judgment.

891
00:46:02,193 --> 00:46:05,183
I'm speaking from the things that
I typically have worked on and

892
00:46:05,183 --> 00:46:06,813
I think this is where we landed.

893
00:46:06,863 --> 00:46:09,863
but yeah, if I was working on something
that had different requirements,

894
00:46:09,863 --> 00:46:13,843
like, yeah, having like the
simplest approach, uh, makes sense.

895
00:46:13,843 --> 00:46:17,423
The only reason that we have to do
this is because we work on stuff

896
00:46:17,423 --> 00:46:20,203
that is like one of our tools is.

897
00:46:20,398 --> 00:46:23,138
Like, uh, like issues, like,
kind of like how Sentry offers,

898
00:46:23,148 --> 00:46:24,308
like, issues that extracts.

899
00:46:24,738 --> 00:46:28,608
So we need to process, like, a
large amount of logs, uh, because

900
00:46:28,608 --> 00:46:31,208
some people have, like, you know,
like, billions of invocations a day.

901
00:46:31,658 --> 00:46:34,468
So it's not the type of thing that we
can really simplify, like, we can't

902
00:46:34,468 --> 00:46:36,238
just give you, like, a single container.

903
00:46:36,553 --> 00:46:38,533
And this, because that's going
to get overloaded very quickly.

904
00:46:38,933 --> 00:46:42,773
So the options for us are some
crazy Kubernetes thing, or we

905
00:46:42,773 --> 00:46:45,913
just take advantage of AWS Kinesis
and all these things that are

906
00:46:45,913 --> 00:46:47,253
built in that are lower overhead.

907
00:46:47,273 --> 00:46:49,833
Um, but, you know, if those
weren't my requirements, I would

908
00:46:49,833 --> 00:46:51,636
probably opt for something similar.

909
00:46:51,636 --> 00:46:54,876
And yeah, at the day, it always just
comes down to like, have good judgment.

910
00:46:55,496 --> 00:46:56,296
With whatever you're doing.

911
00:46:57,166 --> 00:46:57,556
Yeah.

912
00:46:57,926 --> 00:47:04,486
I think it's just as web developers, we're
just so like in, in our like dependency

913
00:47:04,686 --> 00:47:09,606
fury in a way where like, we just like
npm install this, npm install that, and

914
00:47:09,606 --> 00:47:14,556
we also not just package dependencies,
but we also like add infrastructure

915
00:47:14,556 --> 00:47:19,073
dependencies left and right to something,
I think is a big contributor, contributor.

916
00:47:19,358 --> 00:47:24,408
Why the long now aspect of local-first
software is so hard to achieve.

917
00:47:24,818 --> 00:47:29,738
So I'm always, uh, trying as hard
as possible to avoid dependencies,

918
00:47:29,748 --> 00:47:33,268
whether it's package dependencies
or whether it's like infrastructure

919
00:47:33,268 --> 00:47:35,118
dependencies as much as possible.

920
00:47:35,348 --> 00:47:38,328
But it's always a trade off
since they do sometimes can

921
00:47:38,328 --> 00:47:39,588
really save you a lot of time.

922
00:47:39,868 --> 00:47:40,258
Yeah.

923
00:47:40,308 --> 00:47:40,498
Yeah.

924
00:47:40,498 --> 00:47:42,728
I think for us, we kind of land
in this middle ground where

925
00:47:42,728 --> 00:47:44,518
we'll commit to one thing.

926
00:47:44,933 --> 00:47:46,733
But then we'll reject a
bunch of other things.

927
00:47:46,743 --> 00:47:51,863
So, there's this phenomena happening
right now, where, uh, you have these large

928
00:47:51,863 --> 00:47:53,623
cloud providers that offer these services.

929
00:47:53,673 --> 00:47:57,908
The services aren't like, The
best, most wonderful things to use.

930
00:47:58,258 --> 00:48:01,958
There's a bunch of companies that'll
like, make a copy of just that one

931
00:48:01,958 --> 00:48:04,018
service, but do it like 10 times better.

932
00:48:04,178 --> 00:48:08,068
It's often really compelling, and like
you, I can see why people are tempted

933
00:48:08,068 --> 00:48:11,258
to adopt every single one of these, and
people end up with a stack where it's

934
00:48:11,258 --> 00:48:16,716
like, It's my application and sitting on
top of like 10 different other vendors.

935
00:48:17,296 --> 00:48:21,136
And these 10 vendors are also startups,
you know, like it's unclear if they're

936
00:48:21,386 --> 00:48:22,666
going to be around for a while.

937
00:48:22,936 --> 00:48:25,016
So for us, we like as tempting as it is.

938
00:48:25,016 --> 00:48:28,456
And some of it has nice as some of these
offerings are like, we never use those.

939
00:48:28,456 --> 00:48:32,656
We just stick to the most lowest level
primitives that we can be sure are

940
00:48:32,656 --> 00:48:34,076
going to be around for a long time.

941
00:48:34,666 --> 00:48:35,606
And we'll commit to those.

942
00:48:35,636 --> 00:48:37,736
Like, we're going to accept
the fact that if something

943
00:48:37,736 --> 00:48:38,786
happens to them, we're screwed.

944
00:48:39,216 --> 00:48:40,866
More likely we're going
to die before they do.

945
00:48:40,866 --> 00:48:44,176
So that makes sense, but like, you know,
we won't, we won't apply that everywhere.

946
00:48:44,176 --> 00:48:46,739
So again, it just comes down to
like having the right judgment

947
00:48:46,739 --> 00:48:50,279
and picking things and low
dependency is very important.

948
00:48:50,739 --> 00:48:51,839
That makes a lot of sense.

949
00:48:52,069 --> 00:48:56,289
So you mentioned in terms of the
deployment cycle, also the update cycle

950
00:48:56,309 --> 00:48:58,424
of your application, and now in the.

951
00:48:59,104 --> 00:49:03,754
local-first way, there is, uh, primarily
you need to think about how do I

952
00:49:03,774 --> 00:49:06,414
update the local-first app itself?

953
00:49:06,774 --> 00:49:10,874
So some certain things are easy
to deploy, like a, a new component

954
00:49:10,874 --> 00:49:13,294
version of your UI that's, that's easy.

955
00:49:13,604 --> 00:49:18,064
But now that also all of your data
lives in the client, the schema of your

956
00:49:18,064 --> 00:49:22,304
data or like the shape of your data is
possibly also going to evolve over time.

957
00:49:22,304 --> 00:49:23,984
And there's different
ways to deal with that.

958
00:49:24,294 --> 00:49:26,204
So I'm curious how you've handled that.

959
00:49:26,644 --> 00:49:30,804
as well as possibly also the same
problem applied to your cloud component.

960
00:49:31,284 --> 00:49:31,694
Yeah.

961
00:49:31,694 --> 00:49:35,374
So in terms of the data locally, we've
never done anything sophisticated here.

962
00:49:35,374 --> 00:49:36,834
We've always just blown it all away.

963
00:49:36,874 --> 00:49:41,674
If we have to do some kind of severe
breaking change, we will just update like

964
00:49:41,674 --> 00:49:46,524
the big version number and the app will
erase everything locally and re sync.

965
00:49:46,524 --> 00:49:47,254
It's not a huge deal.

966
00:49:47,254 --> 00:49:49,444
It's never like massive amount of data.

967
00:49:49,844 --> 00:49:53,284
I think I can see a world where this
is, and already it's actually not

968
00:49:53,294 --> 00:49:56,004
too different than changing your
back end database schema because

969
00:49:56,004 --> 00:49:57,094
you have similar issues, right?

970
00:49:57,094 --> 00:50:01,014
Like you want to make backwards compatible
changes as much as you can because

971
00:50:01,014 --> 00:50:03,584
you don't want to have to like force
changes in your application code and

972
00:50:03,584 --> 00:50:05,124
force deployments of those together.

973
00:50:05,394 --> 00:50:08,914
So similarly, most of the time you
can do something backwards compatible.

974
00:50:09,084 --> 00:50:11,694
If you totally mess something up,
which obviously happens sometimes,

975
00:50:11,964 --> 00:50:13,044
yeah, we just blow it away.

976
00:50:13,044 --> 00:50:15,734
We haven't really found the need
to do anything more sophisticated

977
00:50:15,744 --> 00:50:16,464
in what we have, like.

978
00:50:17,104 --> 00:50:19,034
Migration scripts that
run locally or anything.

979
00:50:19,324 --> 00:50:23,614
I can see how that's a case for if you're
like running, I guess, if it's like end

980
00:50:23,614 --> 00:50:27,434
to end encrypted or something where you
can't really do that and the true state of

981
00:50:27,434 --> 00:50:30,064
the data is what's on the person's device.

982
00:50:30,354 --> 00:50:32,374
I can see how you have to like
think about that a little bit more.

983
00:50:32,524 --> 00:50:34,484
I think it kind of reminds me of
WhatsApp a little bit because like with

984
00:50:34,484 --> 00:50:37,704
WhatsApp, it feels like you're like
shuffling your data across your devices.

985
00:50:37,804 --> 00:50:41,024
You get a new device, you like
Move the data from one to another.

986
00:50:41,024 --> 00:50:44,074
So I imagine they deal with things
like this, but yeah, personally don't

987
00:50:44,074 --> 00:50:46,294
have a ton of experience with that.

988
00:50:46,984 --> 00:50:51,544
Yeah, I mean WhatsApp is also one
of the OG local-first apps that

989
00:50:51,549 --> 00:50:55,144
really like followed this pattern
out of necessity that defined

990
00:50:55,144 --> 00:50:56,974
why WhatsApp is so attractive.

991
00:50:57,634 --> 00:51:01,664
But I think the, the trade off that you've
landed on, I think makes a lot of sense.

992
00:51:01,664 --> 00:51:06,974
It's very pragmatic and given that you're
in this hybrid mode of like some parts of

993
00:51:06,974 --> 00:51:11,354
your app are cloud oriented, some parts
of your app are local-first, now you can

994
00:51:11,354 --> 00:51:15,654
also reap the benefits of the best of both
worlds that allows you to move quickly.

995
00:51:16,084 --> 00:51:19,684
I think if at some point you want to
move further on the local-first side.

996
00:51:19,764 --> 00:51:23,174
Spectrum, then I think maybe
you can't quite afford just

997
00:51:23,174 --> 00:51:24,794
blowing all the local data away.

998
00:51:24,994 --> 00:51:29,524
I'm kind of exploring some patterns in
that regard where I'm kind of keeping

999
00:51:29,554 --> 00:51:32,084
two versions of the data around locally.

1000
00:51:32,304 --> 00:51:35,234
One version that is more
of like an event log.

1001
00:51:35,714 --> 00:51:39,274
And one that is more of
like a typical app database.

1002
00:51:39,614 --> 00:51:44,454
And the app database is just a projection
on aggregate from the event log.

1003
00:51:44,524 --> 00:51:49,484
So I also get the benefits and luxury
of, in the case of a schema migration,

1004
00:51:49,484 --> 00:51:50,974
I can just blow away the app DB.

1005
00:51:51,304 --> 00:51:54,714
But instead of talking to the
server, I can just replay it locally.

1006
00:51:55,064 --> 00:51:58,804
Sometimes takes a little bit of time,
but, uh, you get a lot of different

1007
00:51:58,814 --> 00:52:03,484
options here that you can choose depending
on your requirements and how much time

1008
00:52:03,484 --> 00:52:06,094
you can afford to put some effort into.

1009
00:52:06,294 --> 00:52:07,314
Yeah, yeah, that makes sense.

1010
00:52:07,314 --> 00:52:11,864
And what's interesting is this feels
very different, but it just kind of

1011
00:52:11,904 --> 00:52:15,544
echoes the same things you do with
like a database in the back end.

1012
00:52:15,554 --> 00:52:16,694
It's ultimately the same thing.

1013
00:52:16,694 --> 00:52:20,014
It just happens to be that the
node of the database is running.

1014
00:52:20,331 --> 00:52:22,791
In someone's machine, so you
end up with like almost all

1015
00:52:22,791 --> 00:52:24,831
the same scenarios and options.

1016
00:52:25,561 --> 00:52:30,311
Did you run into any situation where
you feel like, okay, this was really

1017
00:52:30,361 --> 00:52:34,431
easier in the way how you've built
software in the past that's now

1018
00:52:34,471 --> 00:52:39,941
like either currently harder with
local-first or like just categorically

1019
00:52:39,951 --> 00:52:41,861
inherently harder with local-first?

1020
00:52:42,631 --> 00:52:45,051
Well, it's really that one scenario
I talked about before where

1021
00:52:45,051 --> 00:52:46,731
you do want to block the user.

1022
00:52:46,741 --> 00:52:51,111
Since the default is inverted, whenever,
like you never, you never think like

1023
00:52:51,111 --> 00:52:55,571
holding the user up until the backend
verifies something has happened.

1024
00:52:56,101 --> 00:52:58,621
99 percent of developers would never
think about that as complicated.

1025
00:52:58,651 --> 00:53:00,691
It's like, obviously, that's
like how everything works.

1026
00:53:01,091 --> 00:53:04,041
But when you invert the default, that
becomes a little bit more challenging

1027
00:53:04,411 --> 00:53:08,511
and Yeah, we just have to come up with,
like, certain patterns around, like, if

1028
00:53:08,511 --> 00:53:13,676
you do an action, and a server rejects the
action, the natural s thing that'll happen

1029
00:53:13,676 --> 00:53:18,236
is your state locally will revert to the
state it was at before you did the action.

1030
00:53:18,736 --> 00:53:21,906
But that state has no record of
you trying to do the action, so

1031
00:53:21,906 --> 00:53:25,376
the UI won't have like any error
or like information about this.

1032
00:53:25,386 --> 00:53:28,856
So, doing an action where there was
an error on the backend and preserving

1033
00:53:28,856 --> 00:53:34,016
that error, it just ends up being
more steps than it would be otherwise.

1034
00:53:34,146 --> 00:53:37,096
But again, like we talked about, like this
is a minority of cases, so it doesn't come

1035
00:53:37,096 --> 00:53:38,786
up, but it's just a funny thing where.

1036
00:53:39,531 --> 00:53:43,231
Something so straightforward in
the traditional situation is like

1037
00:53:43,231 --> 00:53:45,731
so weirdly complicated in this.

1038
00:53:46,151 --> 00:53:47,331
So that's one thing that comes up.

1039
00:53:47,331 --> 00:53:50,559
I think the second thing that comes up
is Kind of going back to this thing about

1040
00:53:50,559 --> 00:53:55,799
like the doing migrations of data locally
or the schema changes, there's always

1041
00:53:55,839 --> 00:53:59,289
a chance, and it's happened more when
I was earlier on in doing this stuff.

1042
00:53:59,289 --> 00:54:02,719
So I think it was just me, like, not
doing stuff well, or like not having

1043
00:54:03,409 --> 00:54:04,569
the right approach to certain things.

1044
00:54:04,579 --> 00:54:09,264
But, um, Sometimes you would just end
up with, like, data that was bad and

1045
00:54:09,264 --> 00:54:12,654
messing up the user's state locally.

1046
00:54:12,894 --> 00:54:17,144
And with any other app, hitting refresh
means, start over, you're, like, rebooting

1047
00:54:17,144 --> 00:54:20,944
your computer, you're, like, back to,
back to ground, like, back to zero.

1048
00:54:21,594 --> 00:54:24,374
But with local-first, you might hit
refresh and the local data is still there.

1049
00:54:24,724 --> 00:54:28,344
That's causing the bug, preventing, like,
you know, the fix from being applied.

1050
00:54:28,944 --> 00:54:32,024
So, just like the, you lose the
ease of, like, wiping everything

1051
00:54:32,074 --> 00:54:34,124
and there's no, like, built in user.

1052
00:54:34,434 --> 00:54:38,474
Habits around like, oh, like,
let me try clearing my index

1053
00:54:38,474 --> 00:54:39,834
DB and my browser, right?

1054
00:54:39,834 --> 00:54:41,244
That's like not a thing
that anyone thinks about.

1055
00:54:41,604 --> 00:54:43,904
So just like guarding those
things so you never end up in a

1056
00:54:43,904 --> 00:54:46,314
state where it's unrecoverable.

1057
00:54:46,734 --> 00:54:47,654
I think that's, that's for good.

1058
00:54:47,654 --> 00:54:49,674
Again, it's usually handled on
a lower level, so you're not

1059
00:54:49,674 --> 00:54:50,884
dealing with this constantly, but.

1060
00:54:51,499 --> 00:54:53,169
It is a technical possibility.

1061
00:54:53,619 --> 00:54:56,489
Yeah, I like that, uh,
that observation a lot.

1062
00:54:56,539 --> 00:54:59,009
This is also something I'm
currently thinking a lot about.

1063
00:54:59,469 --> 00:55:01,899
How can I make that
easier through LiveStore?

1064
00:55:01,949 --> 00:55:07,579
Since I also, as working both on
LiveStore and Overtone, I do discover

1065
00:55:07,609 --> 00:55:11,799
those behaviors, whether it's like
still me as a developer driving the

1066
00:55:11,819 --> 00:55:16,499
user experience where it didn't pop open
the console and like throw away, like

1067
00:55:16,509 --> 00:55:18,759
all the, the locally persisted data.

1068
00:55:19,099 --> 00:55:22,279
But I can't expect an app
user to do the same thing.

1069
00:55:22,529 --> 00:55:26,979
So I need to build like some sort of,
um, guards or some sort of detection

1070
00:55:26,979 --> 00:55:31,629
of like, Hey, it seems like the app is
in sort of like a really tough spot.

1071
00:55:31,849 --> 00:55:33,029
What should we do about this?

1072
00:55:33,219 --> 00:55:36,489
Should we try to just like
delete a little bit of stuff

1073
00:55:36,509 --> 00:55:38,699
that might cause the blockage?

1074
00:55:39,064 --> 00:55:40,744
Or what should we do about that?

1075
00:55:40,744 --> 00:55:45,264
And so where, where I'm currently at
is I think a mixture of user experience

1076
00:55:45,304 --> 00:55:48,994
affordances, as well as technical
detections, whether something is

1077
00:55:48,994 --> 00:55:53,514
wrong, I think transactions can help
with that in regards to the technical

1078
00:55:53,514 --> 00:55:58,064
abilities, but then in terms of the
user experience, similar to like a

1079
00:55:58,114 --> 00:56:02,124
React error boundary that you have to
detect whether something has gone wrong.

1080
00:56:02,844 --> 00:56:07,544
I want to have a similar pattern that
allows you to, you know, Click a button

1081
00:56:07,554 --> 00:56:12,314
that wipe everything, but it before
it does wipe everything, download

1082
00:56:12,384 --> 00:56:16,654
a snapshot of your full database
that in case something catastrophic

1083
00:56:16,654 --> 00:56:18,624
happens, you can, you still have that.

1084
00:56:18,874 --> 00:56:22,874
You can hand that to an app developer
and you can also later re import

1085
00:56:22,924 --> 00:56:26,274
your app state from there so
that you can go back where you've

1086
00:56:26,274 --> 00:56:28,014
left off in case you wiped it.

1087
00:56:28,374 --> 00:56:32,414
So those are like some, some primitives
and some, some patterns I'm exploring

1088
00:56:32,414 --> 00:56:35,674
right now, but I'm, I'm excited
to see what other figures out.

1089
00:56:36,119 --> 00:56:37,419
Yeah, that makes sense.

1090
00:56:37,779 --> 00:56:42,969
It's also great that you're like,
building an actual thing with the tool.

1091
00:56:43,249 --> 00:56:46,489
There's just like, no better
way to like, really understand

1092
00:56:46,489 --> 00:56:47,649
what problems you need to solve.

1093
00:56:48,149 --> 00:56:51,669
With SST, like, our
console is built with SST.

1094
00:56:52,179 --> 00:56:56,069
So, any change we make comes
from problems we discover.

1095
00:56:56,209 --> 00:56:57,479
The actual product that we're building.

1096
00:56:57,769 --> 00:57:01,899
That's why it's so fun to work on like,
developer tools, because you are the user.

1097
00:57:02,579 --> 00:57:05,879
So you're never like, how do
I get in the mind of a user?

1098
00:57:05,899 --> 00:57:07,269
Like, that's, that problem isn't there.

1099
00:57:07,299 --> 00:57:08,429
Like, you are the user.

1100
00:57:08,639 --> 00:57:11,809
It's very easy to figure out what
problems there are, um, and discover that.

1101
00:57:11,809 --> 00:57:14,704
You kind of skip that whole,
like, discovery process that

1102
00:57:14,704 --> 00:57:15,684
usually needs to happen.

1103
00:57:16,374 --> 00:57:20,494
So if you have someone who's
currently like, by default, building

1104
00:57:20,524 --> 00:57:22,304
a new app with something like Next.

1105
00:57:22,304 --> 00:57:27,514
js or Ruby on Rails, and they, they hear
about your story and now they're like

1106
00:57:27,554 --> 00:57:31,334
curious about local-first, but they're
not quite sure where to get started.

1107
00:57:31,694 --> 00:57:34,644
Do you have some tactical
suggestions for them?

1108
00:57:34,914 --> 00:57:38,694
And also in terms of mindset,
what do they need to.

1109
00:57:39,009 --> 00:57:43,729
switch in their brain, uh, that they're
successful and can hit the ground

1110
00:57:43,729 --> 00:57:45,869
running in a local-first mindset.

1111
00:57:46,259 --> 00:57:46,829
Yeah.

1112
00:57:47,179 --> 00:57:50,699
You know, it's, I don't think I've
really thought about like, what's

1113
00:57:50,729 --> 00:57:54,509
the right onboarding path for
people doing this type of thing.

1114
00:57:54,539 --> 00:57:57,449
I'm like, I know the tools that I
use, like I said, we're, we're, we've

1115
00:57:57,479 --> 00:58:00,569
centered around Replicache at this
point, but you know, local-first website

1116
00:58:00,569 --> 00:58:02,419
obviously has a ton of other options.

1117
00:58:03,129 --> 00:58:05,609
And there's a spectrum of like
what you care about and like how

1118
00:58:05,609 --> 00:58:08,339
easy it is and how incremental you
can add it and things like that.

1119
00:58:08,379 --> 00:58:12,979
But the mindset I think really is, it
really has nothing to do with local-first.

1120
00:58:12,999 --> 00:58:14,879
And I think it's a good
mindset for everyone.

1121
00:58:14,919 --> 00:58:19,219
I feel like there has been this shift
away from like caring about UX and

1122
00:58:19,219 --> 00:58:22,849
almost, I feel like there's like a weird
proudness to like not caring about UX,

1123
00:58:22,859 --> 00:58:24,309
which I think is fundamentally wrong.

1124
00:58:24,629 --> 00:58:26,169
And what I mean by that is.

1125
00:58:26,366 --> 00:58:29,736
There's a whole meme of like, Oh, if
you did this, you shipped too late.

1126
00:58:29,876 --> 00:58:32,576
Or like people are proud
of like shipping bad stuff.

1127
00:58:32,586 --> 00:58:35,646
Cause they're signaling that
like, I'm just someone that

1128
00:58:35,646 --> 00:58:37,296
like tries to get stuff done.

1129
00:58:37,296 --> 00:58:43,066
I'm not like wasting time on stupid stuff,
which the Linear people had a great write

1130
00:58:43,066 --> 00:58:48,806
up about this and it's this whole concept
around the idea of an MVP is stupid and

1131
00:58:48,806 --> 00:58:52,096
it's been stupid for a while, but for
some reason, people haven't realized this.

1132
00:58:52,591 --> 00:58:55,841
I definitely will acknowledge maybe
back when I was starting out, like

1133
00:58:55,841 --> 00:58:59,231
in the startup world, like, I guess
it's been like 10 or 11 years, things

1134
00:58:59,231 --> 00:59:02,051
were definitely different back then
where there wasn't a lot of software.

1135
00:59:02,511 --> 00:59:05,131
So anything was better than nothing.

1136
00:59:05,361 --> 00:59:09,071
So you could really ship something pretty
quick and like get validation and move on.

1137
00:59:09,231 --> 00:59:11,896
It's like that whole like mindset
kind of made sense back then.

1138
00:59:12,246 --> 00:59:14,216
But it hasn't been that
way in a long time.

1139
00:59:14,366 --> 00:59:17,276
So many people ship like something
they built in a week and they're

1140
00:59:17,276 --> 00:59:18,356
like, Oh, it didn't work.

1141
00:59:18,356 --> 00:59:19,446
Let me move on to the next thing.

1142
00:59:19,739 --> 00:59:23,989
To be honest, nothing good can
really be shipped that fast.

1143
00:59:23,989 --> 00:59:25,079
It's just not possible.

1144
00:59:25,469 --> 00:59:29,999
Uh, and you really need to have a strong
sense of here's a problem I'm solving.

1145
00:59:30,509 --> 00:59:31,899
I have good taste around it.

1146
00:59:31,929 --> 00:59:35,849
I'm going to put in a lot of effort
and make a really great experience.

1147
00:59:36,379 --> 00:59:36,929
And.

1148
00:59:37,509 --> 00:59:41,529
Whether or not my idea is going
to work, you can't know that

1149
00:59:41,539 --> 00:59:43,129
until you've hit that bar.

1150
00:59:43,379 --> 00:59:47,409
And as a Linear people wrote up a whole
thing about this on like, we're so

1151
00:59:47,409 --> 00:59:49,829
obsessed with these like little tiny MVPs.

1152
00:59:50,209 --> 00:59:52,189
And that's like the weird default
that we're all like kind of

1153
00:59:52,189 --> 00:59:54,689
proud to say that we follow that.

1154
00:59:54,709 --> 00:59:59,549
Um, and the mindset shift is with
local-first, it's getting easier all

1155
00:59:59,549 --> 01:00:03,959
the time, but it's going to be a lot
harder than a lot of things that you've

1156
01:00:03,959 --> 01:00:08,229
done before because you have so much
time to focus on these little details.

1157
01:00:08,329 --> 01:00:09,909
And you really have to focus on details.

1158
01:00:09,909 --> 01:00:14,019
You have to enjoy Letting them and
caring about them and making that

1159
01:00:14,019 --> 01:00:17,829
feel good because that's what that's
where the bar is now, whether people

1160
01:00:17,829 --> 01:00:23,079
realize it or not, the fact is Linear,
Linear exists now that it exists.

1161
01:00:23,089 --> 01:00:26,459
How can you possibly ship
anything not at that level?

1162
01:00:26,459 --> 01:00:26,629
Right?

1163
01:00:26,629 --> 01:00:29,929
How, like, sure, in the short term,
I'm sure you can, but the long term,

1164
01:00:29,939 --> 01:00:32,099
obviously that becomes a new bar.

1165
01:00:32,429 --> 01:00:36,589
So, for me, the mindset shift is like,
there is a new bar go use products that

1166
01:00:36,589 --> 01:00:40,459
are like this, like, Linear is one, like,
superhuman is like a smaller example.

1167
01:00:40,986 --> 01:00:42,296
of stuff that's kind of gotten bigger.

1168
01:00:42,716 --> 01:00:45,476
That is the bar, and you have
to accept that that is a bar.

1169
01:00:45,636 --> 01:00:48,516
And if you really accept that,
then you'll be motivated to like

1170
01:00:48,516 --> 01:00:50,196
go and figure out all this stuff.

1171
01:00:50,356 --> 01:00:53,706
Yeah, it's quite different from where
I think the mindset is currently.

1172
01:00:54,163 --> 01:00:58,798
I think you've very succinctly
Summarized my last two and a

1173
01:00:58,798 --> 01:01:00,488
half years working on Overtone.

1174
01:01:00,708 --> 01:01:03,148
I'm exactly inspired by that high bar.

1175
01:01:03,198 --> 01:01:08,458
Sometimes I might even raise it a bit
higher just for, for the challenge, but

1176
01:01:08,498 --> 01:01:13,058
it's so fun to see like all of those
details just compounding and, and I

1177
01:01:13,078 --> 01:01:14,878
like much smoother product experience.

1178
01:01:15,568 --> 01:01:19,413
And, uh, yeah, I love the the
blog posts that you've pointed

1179
01:01:19,413 --> 01:01:21,103
out from the, the Linear blog.

1180
01:01:21,463 --> 01:01:25,423
And I think the only exception really
to where the bar needs to be higher is

1181
01:01:25,423 --> 01:01:27,853
like for just categorically new things.

1182
01:01:28,123 --> 01:01:32,283
Maybe an exception here is like
AI products, uh, like AI products.

1183
01:01:32,313 --> 01:01:34,883
There is no, no prior version to that.

1184
01:01:34,893 --> 01:01:38,923
So maybe it is really speed that,
that matters most, but I think

1185
01:01:38,933 --> 01:01:42,753
for every software that replaces
something that was there before.

1186
01:01:43,213 --> 01:01:46,823
I think it's, you have to
really, really care about craft.

1187
01:01:46,843 --> 01:01:52,023
Um, Arc is another example as like
to really innovate on a browser.

1188
01:01:52,063 --> 01:01:55,733
Like the browser is still the same,
what it is before, but now it's

1189
01:01:55,763 --> 01:01:59,563
like all the compound effect of all
of like getting the details right.

1190
01:02:00,043 --> 01:02:02,303
And that really, that really excites me.

1191
01:02:02,543 --> 01:02:04,753
So thank you so much for
that wonderful summary.

1192
01:02:05,473 --> 01:02:05,743
Yeah.

1193
01:02:05,743 --> 01:02:07,613
And there's so much
opportunity to do this.

1194
01:02:07,613 --> 01:02:10,903
Like I'm unhappy with so much of
the things that I use every day.

1195
01:02:10,993 --> 01:02:14,373
So yeah, I just want more people to get
excited about doing this type of thing.

1196
01:02:14,656 --> 01:02:15,496
Thank you so much.

1197
01:02:15,536 --> 01:02:17,136
This has been really, really fun.

1198
01:02:17,246 --> 01:02:18,526
Thank you so much for coming on.

1199
01:02:19,276 --> 01:02:20,586
Yeah, appreciate having me.

1200
01:02:20,616 --> 01:02:21,716
I, I, it was good.

1201
01:02:21,716 --> 01:02:23,766
I actually don't get to get
into some of these details.

1202
01:02:24,096 --> 01:02:26,266
I don't, I've actually never gotten
a lot of these details before.

1203
01:02:26,266 --> 01:02:27,586
So yeah, it was great.

1204
01:02:27,737 --> 01:02:30,277
Thank you for listening to
the localfirst.fm podcast.

1205
01:02:30,517 --> 01:02:34,247
If you've enjoyed this episode and haven't
done so already, please subscribe and

1206
01:02:34,247 --> 01:02:36,007
leave a review wherever you're listening.

1207
01:02:36,377 --> 01:02:37,807
Please also tell your friends about it.

1208
01:02:37,817 --> 01:02:41,387
If you think they could be interested
in local-first, if you have feedback,

1209
01:02:41,427 --> 01:02:45,167
questions or ideas for the podcast,
please get in touch via hello at

1210
01:02:45,167 --> 01:02:50,947
localfirst.fm or use the feedback form on
our website, special thanks to Expo and

1211
01:02:50,947 --> 01:02:52,997
Crab Nebula for supporting this podcast.

1212
01:02:53,397 --> 01:02:54,157
See you next time.