1
00:00:00,000 --> 00:00:03,659
Well, can I just say that, you know,
from the point of view of exhaustiveness,

2
00:00:04,079 --> 00:00:08,670
there are many, many unsolved
problems in the local-first space.

3
00:00:09,109 --> 00:00:13,289
And   I have a horrible feeling
that it's easy to think that

4
00:00:13,309 --> 00:00:14,799
synchronization is the problem.

5
00:00:14,859 --> 00:00:17,309
And then once you've solved
synchronization, you're good.

6
00:00:17,905 --> 00:00:19,594
Well, I don't think that's true.

7
00:00:20,014 --> 00:00:23,154
I think we all got hung up on, oh,
once we crack CRDTs, we'll be good.

8
00:00:23,584 --> 00:00:24,944
no, no, no, no, that's the easy part.

9
00:00:25,174 --> 00:00:28,304
It's not state management, it's the
state of the state management in a way.

10
00:00:28,304 --> 00:00:30,784
It's like, should I be
synchronizing this data?

11
00:00:31,045 --> 00:00:35,094
Because this person isn't logged in,
or is logged in, or is online, or is

12
00:00:35,094 --> 00:00:39,034
offline, or has shared this document,
or hasn't shared this document, and

13
00:00:39,174 --> 00:00:41,734
that is actually unsolved, I think.

14
00:00:42,301 --> 00:00:44,381
Welcome to the localfirst.fm podcast.

15
00:00:44,661 --> 00:00:47,711
I'm your host, Johannes Schickling,
and I'm a web developer, a

16
00:00:47,711 --> 00:00:50,801
startup founder, and love the
craft of software engineering.

17
00:00:51,221 --> 00:00:55,111
For the past few years, I've been on a
journey to build a modern, high quality

18
00:00:55,111 --> 00:00:57,131
music app using web technologies.

19
00:00:57,571 --> 00:01:01,401
And in doing so, I've been falling down
the rabbit hole of local-first software.

20
00:01:01,921 --> 00:01:04,841
This podcast is your invitation
to join me on that journey.

21
00:01:05,121 --> 00:01:09,801
In this episode, I'm speaking to James
Pearce, the author of TinyBase, a reactive

22
00:01:09,801 --> 00:01:12,121
datastore library for local-first apps.

23
00:01:12,491 --> 00:01:16,231
In this conversation, we explore
how TinyBase works, including its

24
00:01:16,231 --> 00:01:20,021
custom query system, the various
persistence and syncing integrations,

25
00:01:20,271 --> 00:01:22,391
as well as James plans for the future.

26
00:01:22,724 --> 00:01:25,904
Before getting started, also a
big thank you to Rosicorp and

27
00:01:25,914 --> 00:01:28,014
Expo for supporting this podcast.

28
00:01:28,334 --> 00:01:30,284
And now my interview with James.

29
00:01:31,168 --> 00:01:32,268
Hey, welcome James.

30
00:01:32,648 --> 00:01:34,818
Nice to meet you and nice
to have you on the show.

31
00:01:34,828 --> 00:01:35,428
How are you doing?

32
00:01:35,616 --> 00:01:36,396
I'm doing great.

33
00:01:36,506 --> 00:01:37,706
Thank you so much for having me.

34
00:01:37,806 --> 00:01:40,746
Huge privilege to have a
chance to come along and chat

35
00:01:40,746 --> 00:01:41,976
about all things local-first.

36
00:01:42,406 --> 00:01:43,546
yeah, very excited to be here.

37
00:01:43,756 --> 00:01:47,406
It's safe to say that you're the
first guest so far in the podcast,

38
00:01:47,476 --> 00:01:52,916
who's calling in from a boat, which
I think is very on brand for what

39
00:01:52,916 --> 00:01:55,286
local-first software should enable.

40
00:01:55,696 --> 00:01:59,886
and I think Maybe there's a sort of
romantic pitch for why you're doing

41
00:01:59,886 --> 00:02:02,336
local-first, or, or maybe not so much.

42
00:02:02,346 --> 00:02:07,486
I think we'll get to that in a moment,
but the first time, I've took notice of

43
00:02:07,486 --> 00:02:12,256
you is like when you've been at Facebook
back then taking care of overseeing a

44
00:02:12,256 --> 00:02:13,826
whole bunch of open source projects.

45
00:02:13,836 --> 00:02:18,276
So would you mind taking a step back,
briefly introducing yourself and sharing

46
00:02:18,276 --> 00:02:20,276
more about, your time at Facebook?

47
00:02:20,513 --> 00:02:20,943
Sure.

48
00:02:21,033 --> 00:02:21,553
Certainly.

49
00:02:21,573 --> 00:02:22,643
So, I'm James.

50
00:02:22,643 --> 00:02:27,170
I did have a career before Facebook
slash Meta, fairly long time ago.

51
00:02:27,170 --> 00:02:28,350
I'm from the UK originally.

52
00:02:28,376 --> 00:02:30,706
I've been in tech nearly
all of my professional life.

53
00:02:31,406 --> 00:02:38,986
Moved to California in about, 2010, and
started work at Facebook and worked on a

54
00:02:38,996 --> 00:02:40,896
variety of things during my time there.

55
00:02:40,896 --> 00:02:44,476
I was at the company for just over
10 years, but, you know, one of the

56
00:02:44,476 --> 00:02:46,156
highlights for sure was working on.

57
00:02:46,566 --> 00:02:51,193
The open source program, as I'm sure
most of the listeners are aware Meta

58
00:02:51,333 --> 00:02:55,923
does have quite a large investment in
open source whether it's on the client

59
00:02:55,993 --> 00:03:02,573
JavaScript technology side or on DevTools
or on data infrastructure and of course

60
00:03:02,573 --> 00:03:07,323
now on AI, ML and LLM technologies.

61
00:03:07,433 --> 00:03:10,873
And   so yeah, it was a, an
awesome period of time for me.

62
00:03:10,873 --> 00:03:14,473
It was between about 2014 and 2017.

63
00:03:14,763 --> 00:03:18,173
So I helped out with a bunch of
the launches of things like React

64
00:03:18,213 --> 00:03:24,263
and   PyTorch and   HHVM and various
build tools and a whole bunch of things

65
00:03:24,263 --> 00:03:26,063
that people are probably aware of.

66
00:03:26,523 --> 00:03:31,763
And  yeah, it was a super exciting time,
just in terms of helping to develop how

67
00:03:31,763 --> 00:03:36,413
the company thought about open source and
what open source could do for the company.

68
00:03:36,748 --> 00:03:38,501
Wasn't the only thing I did
whilst I was at Facebook.

69
00:03:38,551 --> 00:03:42,311
Also worked on Portal, which was the
smart speaker device that the company had.

70
00:03:43,331 --> 00:03:46,441
, sadly now discontinued, but, it was,
that was pretty awesome working on,

71
00:03:46,811 --> 00:03:48,171
on a hardware project for a bit.

72
00:03:48,621 --> 00:03:52,781
And  also spent some time in the data
infrastructure team, working on some of

73
00:03:52,781 --> 00:03:57,101
the large data warehouse technologies,
that also Meta is fairly well known for.

74
00:03:57,101 --> 00:04:01,190
So, yeah, one of the great things,
maybe underappreciated, features of

75
00:04:01,190 --> 00:04:04,430
being an employee at Facebook is you,
you do get to, move around a lot.

76
00:04:04,430 --> 00:04:08,103
There are lots of mobility opportunities,
and I took the greatest advantage of

77
00:04:08,108 --> 00:04:11,216
that, that I could, and worked on a
wide, wide range of different things.

78
00:04:11,276 --> 00:04:16,496
but yeah, enjoyed, every minute
of it   and then in about 2022.

79
00:04:16,646 --> 00:04:20,210
So yeah, just coming up on two years
ago, figured it was a, a good opportunity

80
00:04:20,210 --> 00:04:21,500
to try something completely different.

81
00:04:21,910 --> 00:04:26,740
And so, Moved on, moved on board Scout,
which is the boat that you see me on now.

82
00:04:27,110 --> 00:04:31,140
And, sold up, my house
and   life in Silicon Valley.

83
00:04:31,140 --> 00:04:35,090
And I've been sailing on the ocean
waves   ever since writing open source

84
00:04:35,090 --> 00:04:36,486
software, so that's where we are.

85
00:04:36,730 --> 00:04:38,290
That sounds quite incredible.

86
00:04:38,330 --> 00:04:40,953
And I mean, Facebook is certainly.

87
00:04:41,123 --> 00:04:46,183
One of the companies that comes to
mind is like how to have a positive sum

88
00:04:46,193 --> 00:04:49,143
vision on how to do open source at scale.

89
00:04:49,473 --> 00:04:53,753
, I can't really think of another
company that has had such an, such a

90
00:04:53,753 --> 00:04:56,923
positive impact on our web ecosystem.

91
00:04:56,973 --> 00:05:00,558
and in particular With
React, with GraphQL.

92
00:05:00,588 --> 00:05:05,218
I'm not as deep on the AI side,
but I mean, the recent releases,

93
00:05:05,228 --> 00:05:09,491
et cetera, around Llama, et cetera,
this is all, I think a great example

94
00:05:09,541 --> 00:05:15,041
of how a large company can have a
very positive impact on the, the

95
00:05:15,041 --> 00:05:17,551
ecosystem beyond its own benefits.

96
00:05:17,561 --> 00:05:21,871
So it's great to hear that you must've
had like a very positive impact on that.

97
00:05:22,101 --> 00:05:22,371
Yeah.

98
00:05:22,371 --> 00:05:23,041
It's a lot of this.

99
00:05:23,536 --> 00:05:24,526
took time to develop.

100
00:05:24,526 --> 00:05:29,546
I mean  you could argue we stumbled into
some of these benefits inadvertently.

101
00:05:29,846 --> 00:05:32,376
I think early on it just seemed
like the right thing to do.

102
00:05:32,386 --> 00:05:36,186
The company had been built on other
people's open source when, you know,

103
00:05:36,186 --> 00:05:37,496
Mark Zuckerberg started the site.

104
00:05:38,051 --> 00:05:40,711
PHP, running on Apache with MySQL.

105
00:05:41,061 --> 00:05:44,331
And so there was always this sense of
standing on the shoulders of other giants.

106
00:05:44,681 --> 00:05:49,268
And so there was a, an almost  cultural
obligation to share back things like

107
00:05:49,318 --> 00:05:53,048
Memcached and, you know, some of the early
things that the company was working on.

108
00:05:53,438 --> 00:05:57,608
but then it began to become apparent that
it was more than just that obligation.

109
00:05:57,618 --> 00:06:01,738
It was also, starting to help lead
the industry because as Facebook

110
00:06:01,828 --> 00:06:06,348
grew, it was experiencing problems
that other apps or other sites

111
00:06:06,378 --> 00:06:07,988
weren't, just because of its scale.

112
00:06:07,988 --> 00:06:11,608
And so it was like the advanced guard
of finding out what happens when you

113
00:06:11,608 --> 00:06:13,258
build really complicated web apps.

114
00:06:13,558 --> 00:06:16,198
and so that was what gave birth
to React, you know, at the

115
00:06:16,198 --> 00:06:17,548
time that React was launched.

116
00:06:18,153 --> 00:06:22,123
You know, most web apps were still
MVC   that was kind of the prevailing

117
00:06:22,123 --> 00:06:27,023
pattern   and it was still, still super
easy to have inconsistencies between

118
00:06:27,023 --> 00:06:29,093
state across a big complicated app.

119
00:06:29,493 --> 00:06:32,743
And so, you know, React's innovation
was, you know, how do we make sure that

120
00:06:32,753 --> 00:06:36,783
the, the user interface is always a pure
function of data that's gone into it.

121
00:06:37,053 --> 00:06:40,893
And, you know, at the time it seemed
heretical, but pretty quickly other

122
00:06:40,893 --> 00:06:42,103
people started to hit the same.

123
00:06:42,563 --> 00:06:45,703
scaling issues with, with MVC
apps and, and, and realized

124
00:06:45,703 --> 00:06:46,873
that React was maybe a way out.

125
00:06:46,913 --> 00:06:50,553
And that's the pattern I think at Facebook
over and over again, whether it's data

126
00:06:50,553 --> 00:06:55,641
infrastructure or or even ML, you know,
the, the company is experiencing problems

127
00:06:55,651 --> 00:06:57,221
that others will face, but haven't yet.

128
00:06:57,271 --> 00:07:02,611
And so it has a chance to maybe share back
some of its solutions from the future, so

129
00:07:02,611 --> 00:07:06,001
to speak, so that others then benefit from
those as they experience those challenges.

130
00:07:06,521 --> 00:07:09,131
Um, so that was, that was one
of the big drivers, I think.

131
00:07:09,381 --> 00:07:10,951
Obviously, it helps
with recruiting, right?

132
00:07:10,951 --> 00:07:13,341
Because you're demonstrating the
kinds of problems that you're solving

133
00:07:13,651 --> 00:07:16,611
and that gets people excited to
come and help solve those problems.

134
00:07:16,911 --> 00:07:20,871
and it also kind of opens the windows
onto the kind of code that people are

135
00:07:20,871 --> 00:07:22,391
building at a company like Facebook.

136
00:07:22,721 --> 00:07:26,051
And obviously, there are lots of world
class engineers there, and there's no

137
00:07:26,081 --> 00:07:29,241
better way of learning that than seeing
the kind of code that they're writing.

138
00:07:29,601 --> 00:07:34,326
, and so it kind of gives you that little
bit of visibility into the, the caliber of

139
00:07:34,326 --> 00:07:35,946
the, the engineers that are working there.

140
00:07:35,946 --> 00:07:39,206
And   yeah, so there, there were
benefits coming back to the company

141
00:07:39,206 --> 00:07:42,940
and just in terms of engineering brand
and recruiting, that over time became,

142
00:07:43,080 --> 00:07:45,570
that became so obvious that it was
like, okay, now we need to just keep

143
00:07:45,570 --> 00:07:46,830
investing in all of these things.

144
00:07:47,230 --> 00:07:50,950
Um, and it's now more than just
a thing that we're doing for fun.

145
00:07:50,950 --> 00:07:53,960
It's now something that's actually
bringing real value to the business.

146
00:07:54,280 --> 00:07:54,850
Exactly.

147
00:07:54,860 --> 00:08:01,230
And I think there's no coincidence that
now some of the most prolific, open

148
00:08:01,230 --> 00:08:05,790
source and tool builders, actually used
to work at Facebook, like thinking of

149
00:08:05,790 --> 00:08:10,640
the people who invented GraphQL, now
building other technologies or Matt

150
00:08:10,640 --> 00:08:14,870
Wonlaw, who was just on the show, was
also at Facebook for, for a while.

151
00:08:15,050 --> 00:08:17,410
So I think really like this deep culture.

152
00:08:17,655 --> 00:08:21,075
around great developer experience
and very principled thinking,

153
00:08:21,085 --> 00:08:22,685
like marrying those two together.

154
00:08:22,985 --> 00:08:27,145
I think this is what, what makes
tools really successful and sticky.

155
00:08:27,505 --> 00:08:32,248
And I think this is what the internal,
Facebook engineering culture has

156
00:08:32,258 --> 00:08:33,788
sort of like brought to light.

157
00:08:34,015 --> 00:08:36,565
I will say it's not as easy as it sounds.

158
00:08:36,615 --> 00:08:38,805
there are lots of things you have
to do behind the scenes and as

159
00:08:38,815 --> 00:08:40,115
someone that was responsible.

160
00:08:40,445 --> 00:08:44,485
for the the overall program rather
than individual projects, you know, I

161
00:08:44,485 --> 00:08:49,715
needed to think about how we I guess
sell this concept internally, right?

162
00:08:49,715 --> 00:08:53,305
Because if you're an engineering manager
and you're running a team and they've

163
00:08:53,305 --> 00:08:57,065
decided they want to spend 20 percent of
their time supporting their project on

164
00:08:57,075 --> 00:09:00,635
github You're like wait, but now i'm down
20 percent in terms of like my internal

165
00:09:00,655 --> 00:09:05,115
goals So a lot of it was a lot of the
challenges were internally Making sure

166
00:09:05,115 --> 00:09:09,465
that everybody was on board with the,
the macro global benefits, even if at a

167
00:09:09,465 --> 00:09:11,985
local level, it seemed like it was a cost.

168
00:09:12,158 --> 00:09:14,398
but we got around that in a
variety of different ways.

169
00:09:14,428 --> 00:09:16,978
, one of the ways that, you know,
perhaps isn't obvious, but I will

170
00:09:16,988 --> 00:09:20,378
state it because I think it was, it
was  perhaps even innovative at the

171
00:09:20,378 --> 00:09:25,226
time, is make sure you're using exactly
the same code from GitHub internally

172
00:09:25,448 --> 00:09:28,158
and I see lots of companies that,
you know, are doing open source, but

173
00:09:28,158 --> 00:09:31,388
it's a fork that they've thrown over
the wall from a couple of years ago.

174
00:09:31,598 --> 00:09:34,078
And now they've diverged and they're doing
something completely different internally.

175
00:09:34,541 --> 00:09:38,231
and that never works because of course
that always gets forgotten about relative

176
00:09:38,231 --> 00:09:39,651
to the thing that's being used internally.

177
00:09:39,991 --> 00:09:44,511
But I think it's pretty awesome that
you go to GitHub and you look at slash

178
00:09:44,551 --> 00:09:46,671
react, and then you go to facebook.

179
00:09:46,871 --> 00:09:48,101
com and you view source.

180
00:09:48,451 --> 00:09:52,468
And you will see exactly the same code,
because the, the internal version of

181
00:09:52,478 --> 00:09:56,168
React and the external version are
being synchronized   commit by commit.

182
00:09:56,501 --> 00:09:58,471
and so that means that
you never get out of sync.

183
00:09:58,761 --> 00:10:01,111
It means that the engineers who
are working internally get to

184
00:10:01,111 --> 00:10:04,221
see their value immediately going
to the community and vice versa.

185
00:10:04,221 --> 00:10:07,631
The community gets to see their value,
appearing on the world's largest website.

186
00:10:07,681 --> 00:10:11,735
So,  those things are hard, like,
infrastructurally to get working, but

187
00:10:11,745 --> 00:10:15,345
those are the kinds of things that, that
then help the whole open source machine

188
00:10:15,375 --> 00:10:17,585
work inside a large company like that.

189
00:10:18,225 --> 00:10:24,735
So in 2022, you mentioned you sold your
house, you, like, made a drastic change to

190
00:10:24,735 --> 00:10:26,801
your life, and you moved onto your boat.

191
00:10:27,141 --> 00:10:29,698
how Did that lead you to local-first?

192
00:10:29,718 --> 00:10:35,178
It seems to coincide a bit timing
wise to, to also, start like working

193
00:10:35,208 --> 00:10:37,468
on TinyBase as your primary project.

194
00:10:37,678 --> 00:10:38,788
Can you share more about that?

195
00:10:39,038 --> 00:10:42,098
Yeah, I guess with the benefit
of hindsight, you can rework the

196
00:10:42,098 --> 00:10:45,058
origin story a little bit and say,
Oh yeah, it was all intentional.

197
00:10:45,298 --> 00:10:46,438
it wasn't, of course.

198
00:10:46,488 --> 00:10:46,938
I had.

199
00:10:47,068 --> 00:10:52,238
Some good milestones in my life   you
know, my, my kids were leaving home and

200
00:10:52,238 --> 00:10:57,528
had reached my 10 year  anniversary at
Facebook and the boat that we had been

201
00:10:57,538 --> 00:10:59,628
dreaming about, you know, was, was ready.

202
00:10:59,898 --> 00:11:02,998
and so it seemed like it was a good idea
to do all these, these things at the same

203
00:11:02,998 --> 00:11:05,498
time in terms of my, my life choices.

204
00:11:05,928 --> 00:11:10,615
but as regards local-first and TinyBase,
which is the project that I've been

205
00:11:10,615 --> 00:11:15,105
working on that I'm sure we'll, we'll talk
about, that was somewhat Coincidental,

206
00:11:15,130 --> 00:11:18,150
that was something that I had been, you
know, thinking about for a long time.

207
00:11:18,550 --> 00:11:23,310
but I think, yeah, then once you
move on a boat, the, a number of the

208
00:11:23,310 --> 00:11:27,210
benefits of, of building local-first
apps suddenly become acutely clear.

209
00:11:27,500 --> 00:11:30,290
It's like, wait, Oh, sometimes I
really just don't have a cloud.

210
00:11:30,340 --> 00:11:33,660
And sometimes even if I do,
my network is pretty bad.

211
00:11:34,150 --> 00:11:38,112
And it really throws into perspective
the difference between the apps that

212
00:11:38,112 --> 00:11:44,245
I native apps, right, that do have
much better local support and the web

213
00:11:44,285 --> 00:11:46,115
apps, which just now fail to load.

214
00:11:46,295 --> 00:11:50,555
And   it really threw into stark relief
the difference between them at the

215
00:11:50,555 --> 00:11:55,315
same time, as I said, I was working on
TinyBase and maybe I can reverse the local

216
00:11:55,825 --> 00:11:59,960
local-first principle into into the origin
story of TinyBase because it does seem

217
00:11:59,960 --> 00:12:01,450
to help support those kinds of things.

218
00:12:01,860 --> 00:12:05,420
and then like almost within a month,
I then read the Ink and Switch article

219
00:12:05,420 --> 00:12:07,270
and I saw the essay about Rffle.

220
00:12:07,320 --> 00:12:12,540
I'm like, okay, all my, all these
things are converging and  , and

221
00:12:12,540 --> 00:12:13,680
it all suddenly made sense.

222
00:12:13,690 --> 00:12:16,980
So there was a lot of serendipity
involved in kind of weaving

223
00:12:17,160 --> 00:12:18,670
these narratives   together.

224
00:12:18,836 --> 00:12:22,958
But   yeah, certainly life on a
boat does, does make you think about

225
00:12:23,178 --> 00:12:26,676
local-first a lot more than   living
in some, you know, high density,

226
00:12:26,756 --> 00:12:28,896
high network connectivity lifestyle.

227
00:12:28,896 --> 00:12:33,316
So, yeah, no, it definitely helped inform
my thinking about this and has encouraged

228
00:12:33,336 --> 00:12:36,576
me to, to keep working on, on TinyBase
and other, other projects like it.

229
00:12:36,716 --> 00:12:38,916
So you mentioned keep working on TinyBase.

230
00:12:38,936 --> 00:12:43,581
So something must've led you to
start working on TinyBase to begin

231
00:12:43,581 --> 00:12:48,241
with, and later you oriented more
around local-first, what was the

232
00:12:48,361 --> 00:12:50,501
impetus to start working on TinyBase?

233
00:12:50,821 --> 00:12:54,801
So, well, maybe I should just
like rewind a little bit in case

234
00:12:54,801 --> 00:12:55,911
it's not blindingly obvious.

235
00:12:56,071 --> 00:13:01,171
I love building stuff and all of
my life, I guess, I've been, you

236
00:13:01,171 --> 00:13:02,371
know, surrounded by computers.

237
00:13:02,371 --> 00:13:06,621
I was programming when I was a kid
and, you know, grew up always trying to

238
00:13:06,621 --> 00:13:12,961
create things with code and I guess the
lifestyle of a manager or a director at

239
00:13:12,991 --> 00:13:17,271
Meta is that you tend to get a little
further and further away from the code

240
00:13:17,271 --> 00:13:22,731
base, which I found sad because even
though I love managing teams and people

241
00:13:22,731 --> 00:13:27,461
and helping grow teams, Organizations
and so forth, like some part of me,

242
00:13:27,741 --> 00:13:31,071
like a primeval part of me still needs
to be building something of my own.

243
00:13:31,521 --> 00:13:36,031
And so, that, that was really the origin
of just doing something, anything.

244
00:13:36,031 --> 00:13:39,251
I just needed to be able to
keep building   even if it was

245
00:13:39,251 --> 00:13:40,801
just a small project for myself.

246
00:13:41,601 --> 00:13:44,821
And then obviously once I left the
company and I started to find I had

247
00:13:44,821 --> 00:13:49,201
more time, I was able to start investing
a little bit more effort into it.

248
00:13:49,636 --> 00:13:55,206
And yeah, the, the original kind of story
for, for building TinyBase was that I

249
00:13:55,216 --> 00:13:59,376
had an idea in my mind of an app that
would be really cool, but I knew that

250
00:13:59,426 --> 00:14:03,186
in order to build that app, I was going
to need to have something like TinyBase.

251
00:14:03,266 --> 00:14:06,006
So, you know, without going into too
much detail, you know, when we were

252
00:14:06,006 --> 00:14:11,046
at   when I was at Facebook, I, I, I
needed a way to manage the state of

253
00:14:11,096 --> 00:14:12,736
hundreds of open source projects, right?

254
00:14:12,736 --> 00:14:18,511
And   so we built some internal tools
that allowed us to, Pull from GitHub, you

255
00:14:18,511 --> 00:14:22,381
know, the state of all of the repos, how
many pull requests, issues, and so forth.

256
00:14:22,451 --> 00:14:26,451
And um, That tooling really made
it easy for us to look at this

257
00:14:26,451 --> 00:14:29,301
huge portfolio and figure out what
was going well and what wasn't.

258
00:14:29,881 --> 00:14:33,641
But I felt like the world itself
could benefit from something like

259
00:14:33,651 --> 00:14:36,891
that So I thought maybe maybe there's
a there's an app out there somewhere

260
00:14:36,891 --> 00:14:40,661
which would be , a GitHub at scale
kind of interface that would let you

261
00:14:40,661 --> 00:14:42,091
manage your open source portfolio.

262
00:14:42,861 --> 00:14:45,611
And so anyway, I thought, well, if I
needed an app like that, and I'd need

263
00:14:45,621 --> 00:14:49,161
to put it in a browser, and I'd need
to have some kind of way of storing

264
00:14:49,171 --> 00:14:53,941
the tables of repos and issues and pull
requests, you know, how would I do that?

265
00:14:53,951 --> 00:14:57,291
Like, what is a good tabular data
store that runs in the browser?

266
00:14:57,291 --> 00:15:02,276
And there isn't, well, back then
anyway, 2021 2022, there wasn't

267
00:15:02,276 --> 00:15:04,406
really an obvious way to do that.

268
00:15:04,406 --> 00:15:07,826
And so I thought, well, rather than
building the app, I'll start off by

269
00:15:07,826 --> 00:15:12,916
building a state management library that
allows me to store tabular data that in

270
00:15:13,096 --> 00:15:16,546
the future will store this data that I
need in this app that I haven't built yet.

271
00:15:16,696 --> 00:15:20,276
And   yeah, that, that, that's
where TinyBase originally came from.

272
00:15:20,276 --> 00:15:24,706
I knew it needed sort of database
semantics, but didn't actually

273
00:15:24,706 --> 00:15:25,856
need to be a database, right?

274
00:15:25,856 --> 00:15:28,386
It could still be considered
an in memory data store.

275
00:15:28,386 --> 00:15:31,446
and I'm sure everyone's familiar
with the idea of a, you know,

276
00:15:31,576 --> 00:15:33,056
kind of a store in a React app.

277
00:15:33,686 --> 00:15:36,296
But I wanted it to kind of look and
feel a little bit like a database.

278
00:15:36,296 --> 00:15:38,946
I wanted it to feel like it
had tables and rows and cells.

279
00:15:39,446 --> 00:15:42,206
I wanted to do queries against it, and
I wanted to be able to do aggregates

280
00:15:42,286 --> 00:15:45,206
of the data so I could count up
the number of stars or commits in a

281
00:15:45,206 --> 00:15:46,506
repo and all those kinds of things.

282
00:15:47,023 --> 00:15:51,243
so yeah, that was the original, idea
of TinyBase, you know, something

283
00:15:51,243 --> 00:15:55,973
that wasn't a database, but sort of
had database conceptual semantics.

284
00:15:56,256 --> 00:15:57,636
and that's where it popped up.

285
00:15:57,966 --> 00:16:01,286
And then of course I stumbled
into the Rffle And   you

286
00:16:01,286 --> 00:16:02,846
know, Ink and Switch material.

287
00:16:03,186 --> 00:16:06,076
And I obviously spotted that you
were doing something similar with,

288
00:16:06,456 --> 00:16:09,156
with a SQLite approach, which is
obviously literally a database.

289
00:16:09,416 --> 00:16:11,806
So you literally get
the database semantics.

290
00:16:12,026 --> 00:16:14,516
but   yeah, by that point I'd
kind of committed myself to

291
00:16:14,556 --> 00:16:16,536
doing an in memory approach.

292
00:16:17,416 --> 00:16:20,036
So I thought, well, let's, let's try both.

293
00:16:20,436 --> 00:16:23,146
, and I, and so I kept pushing,
pushing forward with TinyBase.

294
00:16:23,736 --> 00:16:25,676
Now the story has obviously
evolved a lot since then.

295
00:16:25,676 --> 00:16:29,516
TinyBase is now a lot better about
integrating with real databases.

296
00:16:29,516 --> 00:16:30,656
We can come on to talk about that.

297
00:16:30,966 --> 00:16:33,306
Um, but yeah, that was,
that was the origin story.

298
00:16:33,306 --> 00:16:34,976
It was just something I needed for myself.

299
00:16:35,146 --> 00:16:37,386
I thought the world needed,
and I went and built it.

300
00:16:37,456 --> 00:16:40,786
And then once I found I had more
time, I guess I kept building.

301
00:16:41,026 --> 00:16:41,776
that is amazing.

302
00:16:41,816 --> 00:16:46,556
I think there's a lot of similarities
in terms of your motivations, et cetera.

303
00:16:46,796 --> 00:16:50,946
Maybe a few different technical
decisions along the way, but for me,

304
00:16:51,090 --> 00:16:56,280
starting to work on Overtone would
have not been feasible without having

305
00:16:56,340 --> 00:17:01,425
a very substantial State, local state
management foundation to build on top of.

306
00:17:01,695 --> 00:17:05,365
And this is how I then like got
to know Jeffrey, et cetera, and

307
00:17:05,365 --> 00:17:06,915
started getting involved with Rffle.

308
00:17:07,265 --> 00:17:12,715
So it seems like there is a clear parallel
to you wanting to build your own app

309
00:17:12,785 --> 00:17:17,540
and realizing, okay, that's going to
be terrible working on that app without

310
00:17:17,550 --> 00:17:19,280
those primitives that you have in mind.

311
00:17:19,480 --> 00:17:22,970
So obviously you got to start
building your, your own state

312
00:17:22,970 --> 00:17:24,320
management system first.

313
00:17:24,730 --> 00:17:26,450
so, and kudos to you.

314
00:17:26,500 --> 00:17:31,680
I think TinyBase is one of the most
polished and, sophisticated solutions

315
00:17:31,690 --> 00:17:37,650
that is already out there where I think
a lot of technologies are, maybe have

316
00:17:37,650 --> 00:17:39,720
really great ideas, but are still.

317
00:17:40,030 --> 00:17:43,820
pretty early in terms of being
approachable and having the

318
00:17:43,820 --> 00:17:45,460
supporting resources around it.

319
00:17:45,780 --> 00:17:48,560
So, for example, LiveStore
is not yet open source.

320
00:17:48,570 --> 00:17:52,480
It's available to GitHub sponsors,
but it doesn't have documentation yet.

321
00:17:52,480 --> 00:17:53,640
It doesn't have guides yet.

322
00:17:53,650 --> 00:17:56,966
It doesn't have, like, all of those,
supporting material around it.

323
00:17:57,026 --> 00:18:00,696
Whereas TinyBase has a gorgeous website.

324
00:18:00,991 --> 00:18:04,801
Really polished docs, lots
of examples, lots of guides.

325
00:18:05,071 --> 00:18:09,541
you keep, releasing  regularly,
like new versions, integrations

326
00:18:09,541 --> 00:18:11,171
with different other technologies.

327
00:18:11,481 --> 00:18:14,291
So really, really exciting
how far you've come.

328
00:18:14,571 --> 00:18:18,461
I'm now looking forward to trying to
understand better the different details.

329
00:18:18,641 --> 00:18:19,031
Right.

330
00:18:19,091 --> 00:18:22,001
Well, just firstly, a bit, a
little bit of a meta point on

331
00:18:22,001 --> 00:18:23,431
the, on the kind of the polish.

332
00:18:23,531 --> 00:18:28,451
so a side kind of motivation for
this was to see what it was like

333
00:18:28,451 --> 00:18:32,921
to build software where I didn't
have to make any major compromises.

334
00:18:33,356 --> 00:18:36,886
and I'm sure you and, and, and the
people listening or watching, you

335
00:18:36,886 --> 00:18:40,966
know, have, have written software where
you're under a deadline or there's

336
00:18:40,966 --> 00:18:44,906
some set of constraints and you just
start cutting corners, you know, ah,

337
00:18:44,906 --> 00:18:47,546
you know, this bit of code is really
crappy or, well, we didn't have time

338
00:18:47,546 --> 00:18:50,496
to finish the test coverage or, no,
just, we've got to ship it, right?

339
00:18:50,726 --> 00:18:52,616
Cause that's, and actually that's fine.

340
00:18:52,616 --> 00:18:52,846
Right.

341
00:18:52,846 --> 00:18:54,846
I mean   that, that, that's life.

342
00:18:56,046 --> 00:18:57,266
I always feel like some.

343
00:18:57,711 --> 00:19:02,031
Sort of perfectionist part of my brain
is always like, ah, like next time,

344
00:19:02,081 --> 00:19:03,811
next time, I'm going to make it perfect.

345
00:19:03,831 --> 00:19:06,841
Next time, you know, the
architecture is going to be perfect.

346
00:19:06,861 --> 00:19:08,951
Next time the test coverage is
going to be a hundred percent.

347
00:19:09,521 --> 00:19:13,211
And so given that I now had this
project that only I was working on,

348
00:19:13,501 --> 00:19:15,101
I was really only my only customer.

349
00:19:15,561 --> 00:19:16,911
I had a bunch of spare time.

350
00:19:17,521 --> 00:19:17,961
I figured.

351
00:19:18,616 --> 00:19:20,976
, if I'm ever going to have a chance
to build, quote, what I thought was

352
00:19:21,016 --> 00:19:23,566
perfect software, and of course that's
subjective, it's just my view that it's

353
00:19:23,606 --> 00:19:25,546
perfect   then this was going to be it.

354
00:19:25,606 --> 00:19:30,236
So, can I build a piece of software that
has, you know, 100 percent test coverage,

355
00:19:30,476 --> 00:19:36,671
is refactored, like, so iteratively that
eventually it can't be refactored anymore.

356
00:19:36,671 --> 00:19:39,491
, it's got all the documentation
you could ever need.

357
00:19:39,491 --> 00:19:43,521
It's got the best website that me
and my crappy web design can manage.

358
00:19:43,781 --> 00:19:47,021
Um, and I, you know, I don't
have a deadline, right?

359
00:19:47,081 --> 00:19:48,571
I don't have somebody
breathing down my neck.

360
00:19:48,571 --> 00:19:51,331
I don't have some investors
I got to keep happy.

361
00:19:51,331 --> 00:19:53,981
It's like, no, it's like, I'm
going to polish this thing.

362
00:19:54,041 --> 00:19:59,301
It's, and it's a beautiful, feeling
of kind of craftsmanship, which I have

363
00:19:59,301 --> 00:20:01,031
rarely had before in my professional life.

364
00:20:01,071 --> 00:20:03,031
You know, often you feel
like you're a tradesman.

365
00:20:03,321 --> 00:20:06,101
You're just like knocking stuff out
for a customer or for a deadline.

366
00:20:06,481 --> 00:20:09,501
But suddenly I could feel
like, sounds pretentious, but

367
00:20:09,511 --> 00:20:10,411
almost like an artist, right?

368
00:20:10,861 --> 00:20:14,281
You know, artisanal software
that's like perfectly polished

369
00:20:14,301 --> 00:20:16,181
to my, to my specification.

370
00:20:16,471 --> 00:20:18,611
And that was an interesting
journey in its own right.

371
00:20:18,661 --> 00:20:22,556
By the way, it's also a curse because
you could just end up polishing and

372
00:20:22,556 --> 00:20:25,503
polishing and polishing and then
forgetting to actually share it with

373
00:20:25,503 --> 00:20:27,913
you, share it with the rest of the world.

374
00:20:27,913 --> 00:20:30,591
So, you know, there are
downsides to this as well.

375
00:20:30,591 --> 00:20:35,611
But no, I always wanted to invest
in   test coverage, and documentation.

376
00:20:35,861 --> 00:20:39,821
And by the way, and this is an interesting
side story we may not have time for,

377
00:20:39,821 --> 00:20:44,431
but like, as a result, you build lots
of tools to help you do that too, right?

378
00:20:44,431 --> 00:20:48,231
So I've now got tools that help me
generate the documentation, tools

379
00:20:48,241 --> 00:20:50,151
that help me  generate test cases.

380
00:20:50,571 --> 00:20:53,951
The documentation, as you identified,
has lots of examples and sample code.

381
00:20:54,236 --> 00:20:57,236
Each piece of sample code
is also a unit test, right?

382
00:20:57,236 --> 00:20:59,406
It'll actually take the code
out of the documentation and run

383
00:20:59,406 --> 00:21:02,736
it   which is obviously stuff
that I had to go and build myself.

384
00:21:02,996 --> 00:21:06,556
but that was all me, you know,
thinking, well, I don't want to, I

385
00:21:06,556 --> 00:21:09,256
don't want a piece of code in the
documentation that doesn't actually run.

386
00:21:09,626 --> 00:21:11,896
Like, you know, what happens
if I refactor the code and I

387
00:21:11,896 --> 00:21:12,856
forget that it was in the docs?

388
00:21:13,360 --> 00:21:15,200
I know exactly what you're talking about.

389
00:21:15,420 --> 00:21:17,320
There's a little thing that comes to mind.

390
00:21:17,320 --> 00:21:21,550
I'm not sure where I've seen it, but
I think it was along the lines of

391
00:21:21,570 --> 00:21:27,200
like a yuck   yuck tree, like the,
the concept of like yuck shaving and

392
00:21:27,200 --> 00:21:31,350
like a tree of dependencies or like
how you would try to do one thing.

393
00:21:31,710 --> 00:21:36,120
And to do that, you had to like
diverge into a different side

394
00:21:36,120 --> 00:21:40,370
project and then your side project
has a side project and you see like

395
00:21:40,370 --> 00:21:42,750
a dependency tree of Yuck Shaving.

396
00:21:43,100 --> 00:21:45,220
So I know exactly what
you're talking about.

397
00:21:45,370 --> 00:21:45,940
That's right.

398
00:21:46,300 --> 00:21:47,800
That's right.

399
00:21:47,800 --> 00:21:50,390
And   each one of those tools for
the tools for the tools, each one

400
00:21:50,390 --> 00:21:51,710
of them has to be perfect as well.

401
00:21:51,710 --> 00:21:51,920
Right?

402
00:21:51,920 --> 00:21:53,780
So, anyway, it's probably a fractal thing.

403
00:21:54,200 --> 00:21:57,920
, but   yeah, that, that, that itself has
been a really interesting journey trying

404
00:21:57,920 --> 00:22:02,750
to build the, the software that   I
really always yearned to be able to,

405
00:22:03,200 --> 00:22:07,070
to build   even as it scales, which
is, you know, tricky   to be honest.

406
00:22:07,970 --> 00:22:11,180
And obviously once people start using
it too, because then now you've got

407
00:22:11,230 --> 00:22:15,540
opinions coming from people outside
saying, Oh, well, you know, you

408
00:22:15,540 --> 00:22:18,130
might think it's perfect that you do
this, but we don't like it like that.

409
00:22:18,490 --> 00:22:20,590
You're like, ah, now
I've got this dilemma.

410
00:22:20,690 --> 00:22:24,120
Like, am I going to break my
perfect thing to do the thing

411
00:22:24,120 --> 00:22:25,240
that actually a customer wants?

412
00:22:25,540 --> 00:22:28,010
Well, of course, you know,
because if no one's using it,

413
00:22:28,010 --> 00:22:29,670
then then what was the point?

414
00:22:29,680 --> 00:22:33,130
So there is a a whole set of
interesting trade offs that

415
00:22:33,140 --> 00:22:34,970
you then start, start making.

416
00:22:34,970 --> 00:22:38,220
But   no, just again, true to its
name, I would say the most interesting

417
00:22:38,220 --> 00:22:43,020
part of that is how did, how do
you make it as small as possible?

418
00:22:43,246 --> 00:22:46,836
and I, maybe that's not so important these
days in the world of, faster internet

419
00:22:46,836 --> 00:22:48,856
connections, et cetera, and good bundlers.

420
00:22:48,906 --> 00:22:53,786
But like, I wanted to see, like, could
I make this like as almost, you know,

421
00:22:53,796 --> 00:22:55,256
infinitely as small as I could make it?

422
00:22:55,283 --> 00:22:57,473
and so I spent a lot of time
thinking about minification,

423
00:22:57,473 --> 00:22:58,903
a lot of time thinking about.

424
00:22:59,533 --> 00:23:03,093
you know, how to refactor the code in
a way that, you know, made it compress

425
00:23:03,093 --> 00:23:05,723
really small and, you know, it's still,
it's still pretty small for what it does.

426
00:23:05,893 --> 00:23:06,673
so I'm pretty pleased with it.

427
00:23:06,876 --> 00:23:07,696
That is awesome.

428
00:23:07,766 --> 00:23:11,796
I highly encourage everyone who's
watching this to also check out

429
00:23:11,796 --> 00:23:16,356
your beautiful website and the
documentation, the examples, et cetera.

430
00:23:16,406 --> 00:23:18,646
I think you've laid it out very clearly.

431
00:23:18,976 --> 00:23:23,666
but given this is a podcast where
most people listen to, would you

432
00:23:23,676 --> 00:23:29,386
mind in words, trying to describe
what TinyBase is, like, for example,

433
00:23:29,386 --> 00:23:31,236
in the context of a React app.

434
00:23:31,516 --> 00:23:31,926
Okay.

435
00:23:32,226 --> 00:23:34,376
Well, firstly, TinyBase.

436
00:23:34,406 --> 00:23:38,376
org will do a better job of
explaining it than I will do now,

437
00:23:38,436 --> 00:23:40,136
so definitely go, go check that out.

438
00:23:40,166 --> 00:23:41,576
, it's very nice that
you say it's beautiful.

439
00:23:41,886 --> 00:23:45,276
I'm no graphic designer and   I
actually think the website

440
00:23:45,276 --> 00:23:46,286
could do with a bit of love.

441
00:23:46,286 --> 00:23:49,406
So if anybody would like to come
along and make it look a little nicer,

442
00:23:49,756 --> 00:23:51,216
they are very welcome to file some.

443
00:23:51,796 --> 00:23:54,696
CSS pull requests on me, I would
be very happy to take those.

444
00:23:54,876 --> 00:23:59,466
But, that all said  yeah, look,
the basic idea or the strap line

445
00:23:59,716 --> 00:24:05,146
is that TinyBase is a reactive
data store for local-first apps.

446
00:24:05,376 --> 00:24:08,656
And I'm very careful to say
data store, not database.

447
00:24:08,696 --> 00:24:11,286
I don't want anyone thinking
that it literally is a database.

448
00:24:11,606 --> 00:24:15,566
it's a data store, but it just has
characteristics that are perhaps

449
00:24:15,566 --> 00:24:19,136
familiar to people who have thought
about relational databases in the past.

450
00:24:19,202 --> 00:24:24,131
I also say that it's for local-first
apps because I'm riding on the back

451
00:24:24,131 --> 00:24:27,661
of the cool local-first movement
that's happening right now.

452
00:24:27,881 --> 00:24:31,381
I guess there's no obligation to
only use it on local-first apps.

453
00:24:31,411 --> 00:24:35,841
I think, you know, even a permanently
online app that wants some tabular

454
00:24:35,871 --> 00:24:41,121
data store in the browser would
still be able to use TinyBase.

455
00:24:41,121 --> 00:24:42,891
But yeah, that's the principle.

456
00:24:43,051 --> 00:24:44,051
It's in memory.

457
00:24:44,721 --> 00:24:49,986
So the data is either loaded up from
some local you know, to the browser,

458
00:24:50,236 --> 00:24:55,366
some local storage, or session
storage, or   IndexedDB, and then

459
00:24:55,366 --> 00:24:59,246
it's loaded into memory, and then
you build your app on top of it in

460
00:24:59,246 --> 00:25:04,656
a way that is fully reactive to the
changes that happen to that data store.

461
00:25:04,706 --> 00:25:11,966
So, in a way, you have delegated all
of the data provisioning, loading,

462
00:25:11,976 --> 00:25:16,476
synchronization, whatever, to TinyBase,
and you just build your app as a pure

463
00:25:16,476 --> 00:25:20,596
function of the TinyBase contents, and
I will take care of getting all that

464
00:25:20,596 --> 00:25:22,056
data updated in the background for you.

465
00:25:22,206 --> 00:25:27,406
Whether I'm pulling it from the web, or
I'm synchronizing it with CRDTs, or I'm

466
00:25:27,406 --> 00:25:32,776
pulling it out of a local store, or I'm
firing it over PartyKit WebSockets to your

467
00:25:32,826 --> 00:25:35,186
friends   you know, I'll do all of that.

468
00:25:35,316 --> 00:25:41,156
All you have to do is build a UI that
hooks into tables or rows or cells or

469
00:25:41,156 --> 00:25:43,686
key value pairs in, in the TinyBase data.

470
00:25:43,956 --> 00:25:47,666
and your app will always be
reacting to, to those changes.

471
00:25:48,366 --> 00:25:49,706
So that's the basic principle.

472
00:25:49,926 --> 00:25:51,586
It doesn't have to use
React, incidentally.

473
00:25:51,616 --> 00:25:54,686
Like, there's nothing to stop you
just, you know, listening to changes

474
00:25:54,746 --> 00:25:57,616
in the data directly, and then
just, I don't know, document dot

475
00:25:57,616 --> 00:25:58,966
writing out stuff if you want to.

476
00:25:59,386 --> 00:26:02,156
But React does work well because,
obviously, that also has a

477
00:26:02,156 --> 00:26:03,326
sort of reactive principle.

478
00:26:03,676 --> 00:26:08,856
And so you can use hooks to attach
your components to any of the

479
00:26:09,731 --> 00:26:11,911
elements of the, the, the store.

480
00:26:11,931 --> 00:26:13,811
And by the way, you can do
that at any granularity.

481
00:26:13,841 --> 00:26:17,031
So you could have a component that was
just watching one cell of one row of one

482
00:26:17,041 --> 00:26:21,241
table, or you could have a component that
was watching a whole set of tables, or

483
00:26:21,271 --> 00:26:24,191
one set of key value pairs, what have you.

484
00:26:24,481 --> 00:26:25,631
Lots of different ways to listen.

485
00:26:26,021 --> 00:26:31,636
And  you know, TinyBase will make the,
or do the job of, you know, alerting you

486
00:26:31,636 --> 00:26:35,046
when just that thing that you've looked,
you're looking at has, has changed.

487
00:26:35,466 --> 00:26:38,776
And  the same then goes for queries
against the database, by the way.

488
00:26:38,776 --> 00:26:42,126
So if you want to do something more
interesting than just watching raw data,

489
00:26:42,126 --> 00:26:46,956
you also want to look at aggregates
or  you know, relationships between

490
00:26:46,956 --> 00:26:48,061
data, or in fact, just queries.

491
00:26:48,611 --> 00:26:50,011
construct arbitrary queries.

492
00:26:50,271 --> 00:26:53,581
You can then attach your app to
listen to the results of those.

493
00:26:53,871 --> 00:26:56,811
And again, I'll take care of all
the reactivity behind the scenes

494
00:26:57,051 --> 00:27:01,231
and your app will update when,
when  when those results do.

495
00:27:01,361 --> 00:27:05,081
So I guess when I explain it like that, it
sounds like TinyBase is doing quite a lot.

496
00:27:05,471 --> 00:27:09,191
and that's probably why, you know,
we're two years in and it's taken me

497
00:27:09,311 --> 00:27:10,581
quite a long time to get to this point.

498
00:27:10,881 --> 00:27:12,621
But yeah, that's the basic principle.

499
00:27:12,981 --> 00:27:16,868
And I would say, I think this is
kind of an interesting approach

500
00:27:17,118 --> 00:27:22,213
to apps, whereby You know, how the
data gets into the memory of the app

501
00:27:22,313 --> 00:27:24,563
is kind of, like, delegated away.

502
00:27:24,873 --> 00:27:29,493
And you, as an app builder, now
don't need to worry about things like

503
00:27:29,503 --> 00:27:33,623
going on or offline, or things like
synchronizing, or things like storing.

504
00:27:33,683 --> 00:27:37,523
Like, you should expect your data
storage layer to kind of handle

505
00:27:37,523 --> 00:27:42,883
that for you, and you are then just
painting your app out of the palette

506
00:27:42,893 --> 00:27:45,553
of data that is provided to you.

507
00:27:46,143 --> 00:27:49,613
because As I'm sure you know, and
I'm sure many of the listeners know,

508
00:27:50,313 --> 00:27:54,313
the acts of synchronization and
storage and dealing with all these

509
00:27:54,313 --> 00:27:56,073
network conditions is just horrible.

510
00:27:56,433 --> 00:28:00,623
And rather a small number of people
deal with those problems than have

511
00:28:00,683 --> 00:28:03,943
everybody trying to build a local-first
app having to re solve those problems

512
00:28:03,973 --> 00:28:06,163
is probably the long way to go.

513
00:28:06,613 --> 00:28:09,483
and so I, I, I guess that's
what I'm hoping happens.

514
00:28:09,523 --> 00:28:11,923
And it's not just TinyBase, of course,
there are lots of other people in this

515
00:28:11,923 --> 00:28:14,873
space, yourself included, but, you
know, many other vendors at this point

516
00:28:14,873 --> 00:28:16,393
who are trying to crack these problems.

517
00:28:16,733 --> 00:28:19,823
and I think it's because it's hard
and we know that we have to get

518
00:28:19,873 --> 00:28:25,053
this layer of infrastructure going
before the, oh  the local-first

519
00:28:26,013 --> 00:28:27,903
ecosystem, you know, really takes off.

520
00:28:28,523 --> 00:28:32,003
I suspect that at the moment we
may have more vendors building

521
00:28:32,003 --> 00:28:34,123
solutions than we actually have apps.

522
00:28:34,203 --> 00:28:34,613
That's.

523
00:28:35,143 --> 00:28:38,923
Bit of an offhand assessment there,
but, you know, there are a lot of

524
00:28:38,923 --> 00:28:40,163
people trying to solve these problems.

525
00:28:40,503 --> 00:28:42,323
And I think it's because
it's genuinely hard.

526
00:28:42,593 --> 00:28:45,003
And what I really hope is that
we can make it easy enough

527
00:28:45,123 --> 00:28:49,073
collectively that  that people can
build these apps much more simply.

528
00:28:49,233 --> 00:28:52,063
And you get the benefits of local-first
without having to have a degree in

529
00:28:52,063 --> 00:28:53,953
computer science for synchronization.

530
00:28:54,523 --> 00:28:55,473
That's what we're all trying to get.

531
00:28:56,307 --> 00:28:56,677
Totally.

532
00:28:56,697 --> 00:29:01,357
And, and I think we're getting really
close to, to that where I think right

533
00:29:01,397 --> 00:29:07,187
now the de facto, solution for state
management on the client might rather look

534
00:29:07,187 --> 00:29:12,283
something like MobX or some people might
still like use Redux or Redux toolkit,

535
00:29:12,283 --> 00:29:14,823
et cetera, or, or like React query.

536
00:29:15,143 --> 00:29:20,913
and I think it's hard enough to build
an app that works in the right way.

537
00:29:20,923 --> 00:29:25,463
And most developers don't, dare
yet to think about persistence

538
00:29:25,463 --> 00:29:28,997
and working offline, trying to
make it work, just like that.

539
00:29:29,367 --> 00:29:35,477
And I think a technology like TinyBase
can really, raise the, the floor quite a

540
00:29:35,477 --> 00:29:39,237
lot in terms of what a state management
solution can give you out of the box.

541
00:29:39,497 --> 00:29:44,917
It gives you all of the things something
like MobX does, but also on top of it

542
00:29:44,947 --> 00:29:49,337
gives you persistence, gives you offline
functionality, gives you syncing.

543
00:29:49,747 --> 00:29:52,827
So I think we just,
yeah, raised the floor.

544
00:29:53,147 --> 00:29:57,187
So in terms of the different
responsibilities, I'm curious to hear

545
00:29:57,187 --> 00:30:01,582
a little bit more, and I think what
stands out about TinyBase here is is

546
00:30:01,592 --> 00:30:05,552
that you really went above and beyond
to make things flexible and pluggable.

547
00:30:05,872 --> 00:30:11,682
So for the persistence path, I think
you do allow a whole different range of

548
00:30:11,712 --> 00:30:15,872
different options to persist, whether
it's IndexedDB or, or other options

549
00:30:15,882 --> 00:30:17,522
as well as for, for the syncing.

550
00:30:17,792 --> 00:30:20,942
So would you mind sharing a little
bit more about the details and

551
00:30:21,182 --> 00:30:22,472
the thoughts you have around that?

552
00:30:22,968 --> 00:30:23,758
Yeah, certainly.

553
00:30:23,758 --> 00:30:29,933
So  in the very first instance, I
was just jSON serializing the content

554
00:30:29,933 --> 00:30:34,553
of the store and writing it to local
storage, or to session storage, or to

555
00:30:34,553 --> 00:30:38,083
file, because you can obviously run
TinyBase on a node server as well.

556
00:30:38,483 --> 00:30:45,078
And, that's great, and in 2022 that
seemed like the Basically, you know,

557
00:30:45,418 --> 00:30:49,768
when you're thinking about small stores
anyway  that seems like a fine array of

558
00:30:49,768 --> 00:30:53,538
ways to do it, but Obviously people start
to push the boundaries of what you can

559
00:30:53,548 --> 00:30:56,688
store in those media and just serialize
JSON isn't necessarily the way to go

560
00:30:56,908 --> 00:31:00,778
So I think IndexedDB was probably the
next one that I tackled was not as easy.

561
00:31:00,778 --> 00:31:05,758
, just Just as a small side
note, IndexedDB is not the most

562
00:31:05,758 --> 00:31:08,018
enjoyable API to work with.

563
00:31:08,428 --> 00:31:12,488
Most notably, it lacks any form of
reactivity whatsoever that I know of.

564
00:31:12,548 --> 00:31:14,748
I think there were some proposals
that never went anywhere.

565
00:31:15,408 --> 00:31:16,588
But there's no observability.

566
00:31:17,038 --> 00:31:22,028
So it's kind of Crappy to have
to poll for changes, but  , yeah,

567
00:31:22,028 --> 00:31:24,128
I do now have that as well.

568
00:31:24,128 --> 00:31:29,258
So you can either save your in
memory store to IndexedDB or load

569
00:31:29,258 --> 00:31:33,558
it or automatically save to it when
changes happen or automatically load

570
00:31:33,558 --> 00:31:34,908
from it with a polling mechanism.

571
00:31:35,628 --> 00:31:40,238
so that, that, that, that's there as
well and  and then around the same

572
00:31:40,268 --> 00:31:43,878
time, in fact, it was  Matt Wonlow
that   I know it was on your show a

573
00:31:43,878 --> 00:31:50,198
little while back he was working on his
CR SQLite solution and I started to see

574
00:31:50,198 --> 00:31:53,108
that SQLite  was starting to emerge.

575
00:31:53,468 --> 00:31:56,688
as as a browser opportunity.

576
00:31:57,088 --> 00:32:00,878
And so I figured, well, you know, there'll
be people who want to store it in the

577
00:32:00,878 --> 00:32:03,368
browser on, on a SQLite database as well.

578
00:32:03,698 --> 00:32:06,198
So I went down the path
of supporting that.

579
00:32:06,208 --> 00:32:10,168
So the tables that were in your
memory store in TinyBase can

580
00:32:10,168 --> 00:32:14,438
now be literally written out
to tables in a SQLite instance.

581
00:32:14,678 --> 00:32:18,698
Or read in, and again,
reactivity is not perfect.

582
00:32:19,418 --> 00:32:23,768
, some APIs are better than others,
but  you know, do what I can to, to

583
00:32:23,768 --> 00:32:25,778
keep that as synchronized as possible.

584
00:32:26,598 --> 00:32:31,308
And that then opened the door
to support things like PowerSync

585
00:32:31,878 --> 00:32:36,858
and, uh Turso and ElectricSQL.

586
00:32:37,523 --> 00:32:37,763
, I also did.

587
00:32:38,090 --> 00:32:41,660
PartyKit along the way, which is
not a SQLite store, but it's a

588
00:32:42,220 --> 00:32:46,690
kind of a WebSocket based way of
storing data up in a durable object,

589
00:32:46,760 --> 00:32:48,540
and so it supported that also.

590
00:32:49,070 --> 00:32:52,610
So yeah, there was a period, probably
over the last year or so, that the

591
00:32:52,610 --> 00:32:56,620
version 4 series of TinyBase, if you like,
where each major release was me adding

592
00:32:56,780 --> 00:33:02,160
support for one of these new storage
technologies or synchronization platforms.

593
00:33:02,530 --> 00:33:08,560
The other two that are very worthy of
note are AutoMerge and YJS, so those

594
00:33:08,600 --> 00:33:13,605
are more classic CRDT technologies,
but you can store TinyBase into a

595
00:33:13,605 --> 00:33:17,805
Yjs document, or load it from a Yjs
document, or into an automerge document.

596
00:33:18,185 --> 00:33:20,345
And then, of course, you've
got the benefit of those two

597
00:33:20,345 --> 00:33:23,865
platforms synchronizing in
whatever way they want to.

598
00:33:23,885 --> 00:33:28,145
So, yeah, I guess you could say
I, am providing a lot of options.

599
00:33:28,205 --> 00:33:28,995
Maybe too many.

600
00:33:29,105 --> 00:33:31,568
I, Suspect that when you go to
the website and you see all these

601
00:33:31,568 --> 00:33:34,628
baffling options, you're like, Oh
yeah, but which do I actually choose?

602
00:33:34,968 --> 00:33:38,508
so what I'm hoping to do actually fairly
soon is write a guide for, you know,

603
00:33:38,518 --> 00:33:39,948
this is the kind of app I'm building.

604
00:33:39,948 --> 00:33:42,968
This is the kind of platform I should
use, or this is how I should synchronize.

605
00:33:43,238 --> 00:33:46,668
Do I do the synchronization myself or
do I rely on some third party to do it?

606
00:33:47,318 --> 00:33:51,558
And at the same time, obviously we've
seen companies like PowerSync and

607
00:33:51,558 --> 00:33:54,698
ElectricSQL, you know coming forward
with their, their solutions here.

608
00:33:54,698 --> 00:33:58,128
And so, yeah, if people are using
TinyBase and they want to Provide

609
00:33:58,128 --> 00:34:01,473
a a gateway to those systems,
then that's that option as well.

610
00:34:01,693 --> 00:34:04,433
So yeah, I have  tried to
be as flexible as possible.

611
00:34:04,692 --> 00:34:07,392
One of the privileges, I guess, of
working on this as a hobby is that,

612
00:34:07,522 --> 00:34:12,122
you know, I can be open to working with
as many of these partners as possible,

613
00:34:12,122 --> 00:34:15,242
whether they're commercial startups
or just open source projects, right?

614
00:34:15,242 --> 00:34:17,352
I'm not in competition with anybody.

615
00:34:18,132 --> 00:34:21,402
And so if I'm providing a way for
developers to onboard onto these

616
00:34:21,402 --> 00:34:22,832
different things, then that's great.

617
00:34:22,922 --> 00:34:26,152
I definitely have a view that
the, the tide is rising up.

618
00:34:26,372 --> 00:34:30,482
I'm saying that on a boat but the local
tide is rising, local-first tide is

619
00:34:30,482 --> 00:34:34,822
rising, and I'm happy to see all boats
go with it  even in the long term.

620
00:34:35,462 --> 00:34:40,247
, even if in the long term TinyBase
becomes not needed because, you

621
00:34:40,247 --> 00:34:43,517
know, all of these other platforms
have, have matured to the point where

622
00:34:43,517 --> 00:34:44,897
they're offering what I already do.

623
00:34:44,897 --> 00:34:49,497
But I think in the meantime, I'm hopefully
providing a nice,  disambiguation

624
00:34:49,497 --> 00:34:53,797
layer or  you know, something like
that to help people decide what their

625
00:34:53,797 --> 00:34:57,052
approach is going to be without having
to rewrite their app dramatically.

626
00:34:57,072 --> 00:35:00,102
So yeah, today you could store
your TinyBase data to local

627
00:35:00,102 --> 00:35:03,312
storage and tomorrow you could
then sync it to ElectricSQL.

628
00:35:03,912 --> 00:35:04,602
Why not, right?

629
00:35:04,985 --> 00:35:11,885
So in terms of the data that is persisted,
let's say to IndexedDB or OPFS, SQLite,

630
00:35:11,885 --> 00:35:18,075
or synced to one of the syncing providers,
how do you bring the data into memory?

631
00:35:18,135 --> 00:35:22,085
And do you typically, let's say
I have a, let's say I'm using

632
00:35:22,085 --> 00:35:26,945
Turso and have my SQLite database
somewhere, Is TinyBase automatically,

633
00:35:27,175 --> 00:35:32,195
hydrating all of that data from the
database into the in memory version?

634
00:35:32,245 --> 00:35:36,835
Or is there some sort of scoped
version where maybe the database is two

635
00:35:36,835 --> 00:35:41,945
gigabytes and you only can constrain
yourself to 200 megabytes in memory?

636
00:35:42,222 --> 00:35:43,282
how are you handling that?

637
00:35:43,702 --> 00:35:44,192
Right.

638
00:35:44,292 --> 00:35:48,673
So for all of the database based
persisters, I call them, there's a

639
00:35:48,733 --> 00:35:52,293
configuration where you say which
tables you want and, you know,

640
00:35:52,293 --> 00:35:55,283
whether you want to just load from
those tables or whether you also

641
00:35:55,283 --> 00:35:56,723
want to be able to save back to them.

642
00:35:57,023 --> 00:36:00,673
the worst thing I could think of would
be somebody with some large production

643
00:36:00,683 --> 00:36:03,783
database and they connect TinyBase to
it and the next thing you know, it's

644
00:36:03,783 --> 00:36:08,073
tried to load the entire database into
memory or it's tried to write No, back

645
00:36:08,088 --> 00:36:10,488
to the whole database, and then, you
know, that's the end of the world.

646
00:36:10,488 --> 00:36:14,738
So no, it's all very configurable
on a table by table basis.

647
00:36:15,048 --> 00:36:18,378
And the one thing I have not done,
but I'm pretty sure I need to

648
00:36:18,378 --> 00:36:22,698
do, is also provide some kind of
pagination or filtering on that view.

649
00:36:23,008 --> 00:36:27,693
because if you've got a database that
has, let's say you, you, you shard

650
00:36:27,693 --> 00:36:31,663
it on user or something, and you only
want to be able to see just the data

651
00:36:31,663 --> 00:36:34,723
from that user, which, you know, it's
gonna be a pretty common use case,

652
00:36:34,933 --> 00:36:38,543
then make sure that persistence is
not for the whole table, but just

653
00:36:38,543 --> 00:36:41,553
for the relevant rows, of that table.

654
00:36:41,783 --> 00:36:43,223
I think it's going to be
harder than I think it is.

655
00:36:43,947 --> 00:36:46,177
I suspect there are lots
of gotchas to doing that.

656
00:36:46,497 --> 00:36:51,337
, and so for now, there's my, my solution
or my suggestion will be that people

657
00:36:51,337 --> 00:36:56,077
doing this should probably have a per
user database, which is kind of an

658
00:36:56,077 --> 00:36:58,977
interesting approach that I know some
people have started taking anyway,

659
00:36:59,337 --> 00:37:01,707
for, for edge based, databases.

660
00:37:02,097 --> 00:37:06,167
Um, so that, you know, you're,
you're in no danger of, accidentally

661
00:37:06,167 --> 00:37:09,377
loading data from a different
user into someone's browser.

662
00:37:09,937 --> 00:37:12,197
But no, that's definitely
something I need to tackle.

663
00:37:12,227 --> 00:37:16,117
So it's scoped, to answer your question,
it's scoped to individual tables as

664
00:37:16,117 --> 00:37:17,987
to whether it's load or save or both.

665
00:37:18,717 --> 00:37:21,107
But I think over time we
need to add more pagination.

666
00:37:21,387 --> 00:37:23,837
So that you are just looking at,
you know, the top 10 records,

667
00:37:23,837 --> 00:37:25,067
100 records, or what have you.

668
00:37:25,327 --> 00:37:29,237
The reactivity gets really tricky
at that point because I'm sure you

669
00:37:29,287 --> 00:37:32,647
know, you know, SQLite's reactivity
out of the box is pretty weak.

670
00:37:32,907 --> 00:37:34,787
At best, you're going to
know that a table changed.

671
00:37:35,077 --> 00:37:36,707
And what are you going to do?

672
00:37:36,907 --> 00:37:39,307
Query the whole table to find out
which row it was that changed.

673
00:37:40,250 --> 00:37:45,580
And so knowing that it was row 47 out of
2 billion that was the one that changed.

674
00:37:45,765 --> 00:37:49,595
is not currently something that the
database platforms provide by default.

675
00:37:49,735 --> 00:37:54,125
Um, So, that's one thing where I
am really having to work around

676
00:37:54,125 --> 00:37:55,665
those limitations right now.

677
00:37:56,045 --> 00:37:59,448
, and I'm hoping, if I can't make it
clearer to you, I'm hoping that people

678
00:37:59,448 --> 00:38:03,908
working on SQLite are going to crack
this and provide, you know technologies

679
00:38:03,918 --> 00:38:06,658
that make it easier to synchronize
at a much more granular level, or get

680
00:38:06,658 --> 00:38:10,108
reactivity at a much more granular level,
so that TinyBase isn't having to poll

681
00:38:10,118 --> 00:38:12,652
everything in a way that doesn't scale.

682
00:38:13,248 --> 00:38:21,758
Yeah, I mean, I, I think, Ideally
for SQLite, the most principled and

683
00:38:21,758 --> 00:38:27,178
foundational approach would be to
rebuild SQLite from the ground up to

684
00:38:27,178 --> 00:38:29,418
be incremental and to be reactive.

685
00:38:29,798 --> 00:38:35,138
And I think actually a former coworker
of yours, who is um, Julian, who

686
00:38:35,168 --> 00:38:40,448
has also created, like HipHopVM
at, at Facebook and, and HackLang.

687
00:38:40,943 --> 00:38:45,463
he's actually trying to, to do that with
a new startup called, Skip  that is a

688
00:38:45,463 --> 00:38:50,923
very ambitious, or even audacious goal to
build the whole new database from scratch

689
00:38:50,923 --> 00:38:52,338
to be reactive, from the ground up.

690
00:38:53,003 --> 00:38:57,620
Which I think is very, very interesting,
but short of that, I think you, you're

691
00:38:57,620 --> 00:39:04,080
left by imposing, reactivity, primitives
on top of SQLite and the best you can

692
00:39:04,090 --> 00:39:09,353
do there is to do the minimal amount
of work, you need at a given situation.

693
00:39:09,538 --> 00:39:16,278
So instead of pulling the entire table
that, you know, okay, row 47 has changed.

694
00:39:16,458 --> 00:39:20,248
And that requires quite a bit of like
a reactivity system on top of it.

695
00:39:20,628 --> 00:39:25,642
And so luckily with, a signal like
system, that is a, it's a pretty

696
00:39:25,642 --> 00:39:29,622
good, primitive to put on top of
it, to implement that reactivity.

697
00:39:30,072 --> 00:39:33,905
But, yeah, it's not as efficient
as you, if you'd build it

698
00:39:33,905 --> 00:39:34,985
from the, from the ground up.

699
00:39:35,325 --> 00:39:40,175
That being said, SQLite is so fast that
you get a lot of performance benefits out

700
00:39:40,175 --> 00:39:42,155
of the box and you can get away with it.

701
00:39:42,588 --> 00:39:43,618
Yeah, that's true.

702
00:39:43,668 --> 00:39:44,918
you know, certainly on the client.

703
00:39:44,968 --> 00:39:48,898
Um, yeah, I, I, without, you know,
sharing too much, internal stuff,

704
00:39:49,258 --> 00:39:51,278
there was a big push, at Facebook.

705
00:39:51,718 --> 00:39:56,238
I'm thinking six, seven years ago, you
know, to think about reactivity for

706
00:39:56,238 --> 00:40:00,678
the entire Facebook stack, because this
concept of, you know, taking the ideas

707
00:40:00,678 --> 00:40:02,188
of React that were out on facebook.

708
00:40:02,218 --> 00:40:06,438
com and bringing them all the way back
through the web servers, which are

709
00:40:06,468 --> 00:40:10,128
HHVM, all the way through to the data
stores that were being used at the

710
00:40:10,128 --> 00:40:14,048
company, you know, like it's a utopian
vision, but like, if you can make

711
00:40:14,048 --> 00:40:15,788
that push based all the way through.

712
00:40:16,078 --> 00:40:17,008
That's spectacular.

713
00:40:17,488 --> 00:40:22,068
and you know, Julian and I were
probably in many of the same, uh

714
00:40:22,098 --> 00:40:25,098
discussion groups and, you know,
internal Facebook groups where a lot of

715
00:40:25,128 --> 00:40:26,948
these ideas were being bounced around.

716
00:40:27,378 --> 00:40:31,928
And, and so yeah, when he left and
went off and did, Skip  and you know,

717
00:40:31,958 --> 00:40:36,788
I guess maybe some of this informed my
thinking about TinyBase too,  you know,

718
00:40:36,978 --> 00:40:40,248
that dream is still very much alive.

719
00:40:40,298 --> 00:40:44,078
and yeah, it's coming from, ironically,
it's like it's coming from React.

720
00:40:44,128 --> 00:40:45,598
That idea is coming from React.

721
00:40:45,638 --> 00:40:48,968
It's just like, well, okay, can we bring
that idea a little bit further back,

722
00:40:48,968 --> 00:40:51,148
and then a little bit further back,
and then a little bit further back?

723
00:40:51,148 --> 00:40:53,048
Oh, like, and then we
end up on the database.

724
00:40:53,298 --> 00:40:57,678
Like, why can't we get the database to be,
you know, telling us about these changes?

725
00:40:57,738 --> 00:41:00,608
And, yeah, I guess that
would be the vision.

726
00:41:00,648 --> 00:41:04,238
Unfortunately, I haven't checked in
recently, but I think SkipDB wasn't

727
00:41:04,783 --> 00:41:08,663
Wasn't at a level where I could start
working with it, when I last looked.

728
00:41:08,763 --> 00:41:09,593
Um, so yeah.

729
00:41:10,137 --> 00:41:13,867
I think it's not yet fully production
ready, but as far as I know,

730
00:41:13,867 --> 00:41:15,207
they're just still working on it.

731
00:41:15,677 --> 00:41:20,993
So in terms of the query layer
for TinyBase, you have, not

732
00:41:21,213 --> 00:41:25,587
implemented SQL as a query language
on top of your own data store.

733
00:41:25,587 --> 00:41:25,786
Um, so yeah.

734
00:41:25,937 --> 00:41:29,667
But you've provided, given that
JavaScript or TypeScript is the

735
00:41:29,667 --> 00:41:34,217
primary way how you interact with
it, you've just embedded a DSL, as a

736
00:41:34,217 --> 00:41:36,537
query language directly into TinyBase.

737
00:41:36,887 --> 00:41:40,683
So would you mind briefly describing
that and, how that describes a user

738
00:41:40,683 --> 00:41:42,173
experience or the developer experience?

739
00:41:42,600 --> 00:41:43,770
Right, right.

740
00:41:43,890 --> 00:41:47,320
So the, the journey here for me was
that first I knew there were going

741
00:41:47,320 --> 00:41:51,800
to be some very simple query like
primitives that I wanted to have.

742
00:41:51,810 --> 00:41:57,220
So one is, like a metric, which
is some kind of, you know, number

743
00:41:57,220 --> 00:41:59,060
derived from the content in a table.

744
00:41:59,260 --> 00:42:02,500
And I knew that that was going to be the
first thing I wanted to have if I was

745
00:42:02,500 --> 00:42:04,840
building this hypothetical GitHub app.

746
00:42:04,840 --> 00:42:07,820
I was going to want to have a number
in the top that said number of repos,

747
00:42:07,820 --> 00:42:10,180
and I was going to want to have a
number that said number of commits.

748
00:42:10,510 --> 00:42:12,570
And so I actually baked in.

749
00:42:12,875 --> 00:42:19,145
a kind of a metrics oriented DSL where you
can define a metric which is, you know,

750
00:42:19,155 --> 00:42:24,915
basic aggregates, counts, averages, sums,
those sorts of things, which by default

751
00:42:24,915 --> 00:42:29,715
is normally just counting the rows in a
table, but that is then a reactive entity.

752
00:42:29,715 --> 00:42:33,388
So again, you can say, I just want
this span in the top right hand

753
00:42:33,388 --> 00:42:36,675
corner of the window to just always
show whatever that metric was,

754
00:42:36,985 --> 00:42:38,085
and then you can forget about it.

755
00:42:38,215 --> 00:42:40,665
And if that table is updated, You
know that number's going to change,

756
00:42:40,695 --> 00:42:41,595
TinyBase will take care of it.

757
00:42:42,015 --> 00:42:44,285
another thing that I knew I
was going to need to do was

758
00:42:44,285 --> 00:42:45,495
relationships between tables.

759
00:42:45,505 --> 00:42:51,265
So I built a very specific thing for
just one local table, one remote foreign

760
00:42:51,305 --> 00:42:53,325
table, and then like keys between them.

761
00:42:53,535 --> 00:42:57,475
So the value of one column in one table
is used as the identifier for another.

762
00:42:57,795 --> 00:43:01,475
And so, yeah, you want to see the issues
just for this repo, or you want to see

763
00:43:01,772 --> 00:43:04,162
the repos just for this user, then you'll
be able to do those kinds of things.

764
00:43:04,332 --> 00:43:07,582
So those are, were actually baked in
pretty early to TinyBase, just because

765
00:43:07,582 --> 00:43:13,102
they seemed Very important, but I, I
guess I knew eventually people were

766
00:43:13,132 --> 00:43:19,702
going to want to push that on and start
doing things like arbitrary queries.

767
00:43:20,162 --> 00:43:26,112
And I toyed with the idea of, you
know, supporting SQL in some form.

768
00:43:26,777 --> 00:43:28,297
And I should say, I love SQL.

769
00:43:28,297 --> 00:43:30,947
I have been writing SQL most of
my professional career, which

770
00:43:30,947 --> 00:43:32,927
you know, goes back a fair way.

771
00:43:33,317 --> 00:43:37,397
And my most recent role at Facebook
was, you know, the data analytics

772
00:43:37,577 --> 00:43:40,347
team in the data infrastructure org.

773
00:43:40,347 --> 00:43:43,217
So you know, we were working
with SQL all the time.

774
00:43:43,437 --> 00:43:47,867
Perhaps despite that, or because of
that, I kind of got nervous about doing

775
00:43:47,867 --> 00:43:53,367
an arbitrary SQL parser, evaluator,
executor, and then being able to make

776
00:43:53,367 --> 00:43:58,398
the results reactive, which was like,
that's the, that's That's the non deniable

777
00:43:58,418 --> 00:44:00,608
requirement, like, it has to be, reactive.

778
00:44:01,268 --> 00:44:06,458
So, I didn't really have a lot of
choice, but, oh, and by the way, you

779
00:44:06,458 --> 00:44:09,858
know, a full SQL parser with all the
dialects you'd want is, like, it's

780
00:44:09,858 --> 00:44:12,338
gonna quadruple the size of TinyBase.

781
00:44:12,338 --> 00:44:13,288
It's just, it's code based.

782
00:44:13,288 --> 00:44:15,298
So, no longer tiny.

783
00:44:15,348 --> 00:44:15,858
Yes.

784
00:44:15,888 --> 00:44:19,298
So, I wanted to come at it from
a slightly different direction.

785
00:44:19,298 --> 00:44:22,868
I know I'm not the only person to have
thought of doing more like a DSL approach

786
00:44:22,868 --> 00:44:26,778
to this, but I, I wanted to see whether
I could capture as much of the, the

787
00:44:26,778 --> 00:44:31,348
valuable parts of SQL without turning
it into a place where people could build

788
00:44:31,808 --> 00:44:33,828
stupid cartesian joins and kill their app.

789
00:44:34,158 --> 00:44:36,978
so I wanted to make it kind
of a little bit on rails.

790
00:44:37,118 --> 00:44:41,528
And yeah, it was the idea of TinyQL was
born, which is kind of a stupid name.

791
00:44:41,528 --> 00:44:45,305
But it's, as you said, a DSL
that allows you to, you know,

792
00:44:45,315 --> 00:44:48,358
select, where, group, limit.

793
00:44:48,658 --> 00:44:50,098
, actually, no, I don't
have a limit in there.

794
00:44:50,098 --> 00:44:53,028
I limit a later part in the pipeline.

795
00:44:53,028 --> 00:44:55,778
But, yeah, basically allows
you to join tables together.

796
00:44:56,103 --> 00:45:01,623
and then where them, there's havings and
groups and those kinds of things too,

797
00:45:02,193 --> 00:45:07,113
which like really is what 98 percent
of people want to do with SQL anyway.

798
00:45:07,223 --> 00:45:11,393
And haven't really come across too
many queries that I can't express

799
00:45:11,483 --> 00:45:14,263
with these five or six quote keywords.

800
00:45:14,623 --> 00:45:17,453
Yeah, the cool thing about
SQL is you can do anything.

801
00:45:17,463 --> 00:45:19,293
The awful thing about SQL
is you can do anything.

802
00:45:19,673 --> 00:45:24,103
And, I have worked with enough people
who thought they knew what SQL did and

803
00:45:24,113 --> 00:45:27,143
didn't quite know what it did to, you
know, see the trouble you can get into.

804
00:45:27,143 --> 00:45:30,793
So I really, yeah, wanted to make it a
little bit more constrained than that.

805
00:45:31,483 --> 00:45:33,273
And it's, it's been,
it was a real journey.

806
00:45:33,293 --> 00:45:35,743
That was a very tricky, for me, anyway.

807
00:45:35,743 --> 00:45:38,663
, that was a very tricky thing to
build, especially making sure

808
00:45:38,663 --> 00:45:39,853
that all the results are reactive.

809
00:45:39,883 --> 00:45:42,603
Because, by the way, you know,
any of those tables could change.

810
00:45:43,198 --> 00:45:44,808
Any of the rows in those
tables could change.

811
00:45:44,978 --> 00:45:47,928
In fact, you don't want to react
to the changes of the results if

812
00:45:47,928 --> 00:45:49,398
some of the irrelevant rows change.

813
00:45:49,398 --> 00:45:51,861
You only want to know if it was
the relevant rows that changed.

814
00:45:51,861 --> 00:45:54,828
So you have to set up listeners on
all the things that were relevant and

815
00:45:54,948 --> 00:45:56,508
not the things that were irrelevant.

816
00:45:56,918 --> 00:45:59,468
so that ended up being a little
harder than I thought, but yeah,

817
00:45:59,468 --> 00:46:00,628
pretty proud with how it turned out.

818
00:46:00,978 --> 00:46:04,633
And as a result, and I would urge
people to go check this out, You can

819
00:46:04,633 --> 00:46:09,623
build kind of interesting analytics
apps, right, with this, in the browser.

820
00:46:09,753 --> 00:46:11,773
So if you go to the TinyBase.

821
00:46:11,863 --> 00:46:14,733
org demos, you'll see there's a demo.

822
00:46:14,773 --> 00:46:17,453
I think it's called car
analytics or something like that.

823
00:46:17,453 --> 00:46:20,453
And it takes a data set of car
data, different models, different

824
00:46:20,463 --> 00:46:23,513
makes, miles per gallon, years.

825
00:46:23,563 --> 00:46:27,503
So there's a bunch of numerical measures
and there's a bunch of dimensions.

826
00:46:27,752 --> 00:46:29,902
And in the browser, it loads
all the data in pretty quick.

827
00:46:30,202 --> 00:46:32,392
It's not that much data, but you
know, loads it in pretty quickly.

828
00:46:32,392 --> 00:46:35,545
And then you can do groups,
sorts, filters, across all

829
00:46:35,545 --> 00:46:37,045
of this data in the browser.

830
00:46:37,045 --> 00:46:38,915
And it's like, it's completely instant.

831
00:46:39,015 --> 00:46:40,825
It's like, great, love it.

832
00:46:41,145 --> 00:46:44,815
and look, this is not going to be
great for querying the Facebook data

833
00:46:44,815 --> 00:46:49,005
warehouse, however many hundreds of
petabytes that is these days, but

834
00:46:49,005 --> 00:46:53,525
it is going to be fine if you've got
10 or 100, 000 rows in your browser.

835
00:46:53,545 --> 00:46:55,135
And Don't be scared, people.

836
00:46:55,305 --> 00:46:58,115
Like, getting a hundred thousand rows
of data into a browser is not hard.

837
00:46:58,575 --> 00:47:00,225
The browser is perfectly
capable of doing that.

838
00:47:00,405 --> 00:47:04,435
You know, most  even phones
are very happy to run that kind

839
00:47:04,435 --> 00:47:05,945
of sized data in, in memory.

840
00:47:06,285 --> 00:47:09,815
so yeah, for a lot of even analytics
use cases, you can do, you could, you

841
00:47:09,815 --> 00:47:13,345
could build interactive dashboards
with this kind of technology and

842
00:47:13,345 --> 00:47:17,245
have a sort of constrained set of
queries all running off TinyBase.

843
00:47:17,245 --> 00:47:19,655
And it's super feasible, and it's been.

844
00:47:20,310 --> 00:47:21,810
It's been fun to build that.

845
00:47:22,070 --> 00:47:24,160
Whether or not people are using
it in the wild, I don't know.

846
00:47:24,275 --> 00:47:27,775
I should say, I don't put any
instrumentation into this product.

847
00:47:27,775 --> 00:47:31,115
So who knows what people are using
it for, or how they're using it.

848
00:47:31,405 --> 00:47:34,035
But I hope that those people who use
it do, do find the value of being

849
00:47:34,035 --> 00:47:37,075
able to run queries, without, shooting
themselves in the foot with SQL.

850
00:47:37,615 --> 00:47:41,505
Did you follow any sort of prior
art in regards to how you built

851
00:47:41,505 --> 00:47:43,395
that reactive query system?

852
00:47:43,395 --> 00:47:48,865
So, as I was working on a similar
part as, the work on Rffle, there,

853
00:47:48,915 --> 00:47:53,415
there was, some prior art in
regards to Adapton and mini Adapton.

854
00:47:53,825 --> 00:47:57,915
And so this was, some inspiration,
that we followed for the reactivity

855
00:47:57,935 --> 00:48:04,155
system and we've like over time learned
that, it's very similar to how now like

856
00:48:04,155 --> 00:48:06,365
signals is all the rage these days.

857
00:48:06,455 --> 00:48:09,025
It's like very similar
in terms of the ideas.

858
00:48:09,055 --> 00:48:11,215
So did you follow some,
some similar paths?

859
00:48:12,236 --> 00:48:12,716
No.

860
00:48:13,276 --> 00:48:14,016
And I wish I had.

861
00:48:14,416 --> 00:48:16,016
I think it's one of my weaknesses.

862
00:48:16,066 --> 00:48:18,096
One of my weaknesses is
that I look at a problem.

863
00:48:18,186 --> 00:48:19,756
You know, it's like the
famous Hacker News thing.

864
00:48:19,766 --> 00:48:21,726
It's like, I could have
built that in a weekend.

865
00:48:22,056 --> 00:48:23,876
I, I look at a reactive query system.

866
00:48:23,876 --> 00:48:25,296
I think, yeah, I'm sure
I could build that.

867
00:48:25,636 --> 00:48:30,146
And then like two months later, I
was like, I wish I'd read a bit more.

868
00:48:30,236 --> 00:48:35,343
I am not good at prior art and
reading scientific papers or even

869
00:48:35,343 --> 00:48:37,263
just, you know, looking at other
projects to see how they're done.

870
00:48:37,263 --> 00:48:39,763
I think, you know, I know what
the result should be and I'm

871
00:48:39,763 --> 00:48:40,783
going to try to build it myself.

872
00:48:40,783 --> 00:48:41,703
And then I get into trouble.

873
00:48:42,056 --> 00:48:43,466
Fortunately, I worked
my way out of trouble.

874
00:48:44,236 --> 00:48:48,116
If it makes you feel any better,
even with knowledge of the prior art,

875
00:48:48,346 --> 00:48:52,936
it still took easily more than two
months just to get anything working.

876
00:48:53,336 --> 00:48:53,846
So,

877
00:48:55,111 --> 00:48:59,021
Okay, that's just, that's just my,
my weakness that  fortunately I

878
00:48:59,026 --> 00:49:00,651
was able to work around this time.

879
00:49:00,651 --> 00:49:06,041
But  yeah, I think the other thing is
that I obviously knew in intense detail

880
00:49:06,401 --> 00:49:11,141
how the reactivity of the underlying
tables, rows, and cells were right.

881
00:49:11,411 --> 00:49:16,591
And so I knew how I was gonna have to
cascade the listener trees into all

882
00:49:16,591 --> 00:49:18,391
the relevant parts of the database.

883
00:49:18,801 --> 00:49:23,251
And, That was, yeah, that was just
something I had to figure out for myself.

884
00:49:23,981 --> 00:49:27,511
The other thing I alluded to
earlier is that TinyBase is

885
00:49:27,511 --> 00:49:29,221
just draped with test cases.

886
00:49:29,231 --> 00:49:32,371
Like, I am exhaustive, overly exhaustive.

887
00:49:32,371 --> 00:49:35,621
I'm completely OCD when
it comes to test cases.

888
00:49:35,901 --> 00:49:37,421
It's not quite TDD.

889
00:49:37,721 --> 00:49:41,071
I don't always do the tests first,
but, you know, I do eventually try

890
00:49:41,071 --> 00:49:42,481
to make it look like I did TDD.

891
00:49:42,521 --> 00:49:46,981
So I built every possible query I can
think of, and I build all these demo

892
00:49:46,981 --> 00:49:50,901
apps, and I build all these sample,
you know, fragments of code, and

893
00:49:50,911 --> 00:49:54,801
they all get tested exhaustively, and
so I figure out, well, once, once,

894
00:49:55,261 --> 00:49:56,871
once those work, I'm probably there.

895
00:49:57,238 --> 00:49:59,258
So that, that was my
benchmark, and I got there.

896
00:49:59,558 --> 00:50:02,108
It's probably, I'm sure it's
still possible to break it,

897
00:50:02,158 --> 00:50:05,568
but, you know, I think, I think
I'm about where it needs to be.

898
00:50:06,356 --> 00:50:10,586
So one of my favorite problems
to, to think about, and it's a

899
00:50:10,586 --> 00:50:14,836
love hate relationship in terms of
technical problems, which are schema

900
00:50:14,886 --> 00:50:18,736
migrations and schema evolution,
which is something I thought a lot

901
00:50:18,736 --> 00:50:20,566
about, through the work on Prisma.

902
00:50:20,616 --> 00:50:26,816
And I tried for the work on Overtone,
ideally having to deal with as little

903
00:50:27,016 --> 00:50:30,481
as possible, or at least have a
very principled foundation for that.

904
00:50:30,781 --> 00:50:34,371
And I feel this is a bit of
a underdeveloped area in some

905
00:50:34,371 --> 00:50:36,911
of the available open source
technologies right now, or

906
00:50:36,911 --> 00:50:38,511
local-first technologies right now.

907
00:50:38,921 --> 00:50:44,661
So I'm curious how you have been thinking
about schema migrations for TinyBase.

908
00:50:45,051 --> 00:50:47,271
and if you've already built
some foundation there.

909
00:50:47,755 --> 00:50:48,025
Okay.

910
00:50:48,025 --> 00:50:50,825
Well, before we talk about schema
migrations, we should talk about schemas.

911
00:50:51,395 --> 00:50:51,875
So.

912
00:50:52,390 --> 00:50:57,570
even having a schema was kind of a
late thought for me, TinyBase outta the

913
00:50:57,570 --> 00:51:00,600
box by default, when, and especially
when I first built, it, didn't have

914
00:51:00,600 --> 00:51:02,310
the concept of a schema at all.

915
00:51:03,120 --> 00:51:07,430
And, you know, any row
could have any set of cells.

916
00:51:07,430 --> 00:51:10,095
I mean, a, a a row of cells
was basically just a map.

917
00:51:10,655 --> 00:51:14,675
So it was possible for every row of
a table to have completely different

918
00:51:14,675 --> 00:51:16,396
cells in it, which is a bit.

919
00:51:16,880 --> 00:51:21,290
Scary, and contrarian especially
for someone like me who'd

920
00:51:21,290 --> 00:51:23,670
just come from working on the
world's largest data warehouse.

921
00:51:24,030 --> 00:51:25,940
the idea of doing this
was, was a little daunting.

922
00:51:26,380 --> 00:51:31,886
But,, I felt like, you know, the word tiny
meant I was allowed to do things like that

923
00:51:32,096 --> 00:51:37,576
and take away some constraints and just
let people put arbitrary data into this

924
00:51:38,236 --> 00:51:39,906
basically a map of map of maps, right?

925
00:51:39,906 --> 00:51:41,396
Tables of rows of cells.

926
00:51:41,446 --> 00:51:46,366
Now that obviously is fun for little
demo apps, but at some point you

927
00:51:46,366 --> 00:51:47,986
need to start tidying things up.

928
00:51:48,026 --> 00:51:50,296
It's all very good when it's just
one person building it too, right?

929
00:51:50,296 --> 00:51:53,096
Because I can remember all the fields
that are supposed to be in this table.

930
00:51:53,476 --> 00:51:55,926
but when I've got colleagues who
maybe want to know what the schema is,

931
00:51:55,946 --> 00:51:56,866
then should do something different.

932
00:51:57,616 --> 00:51:59,406
So I did, yeah, we do have schema support.

933
00:51:59,696 --> 00:52:02,146
I did add schema support,
but it's optional, right?

934
00:52:02,146 --> 00:52:06,006
You, you, you have to explicitly
add the schema onto your store.

935
00:52:06,386 --> 00:52:09,846
but even then the schema is,
I'm afraid, sorry, very basic.

936
00:52:10,196 --> 00:52:13,526
So you can say whether a cell is a, you
know, string, a boolean or a number.

937
00:52:13,861 --> 00:52:16,551
And you can say whether it was required
or not, and what the default is.

938
00:52:17,231 --> 00:52:17,621
That's it.

939
00:52:18,141 --> 00:52:20,531
So that seems a little daunting.

940
00:52:20,931 --> 00:52:24,761
I should say, by the way, that TinyBase
only supports those data types anyway.

941
00:52:24,791 --> 00:52:27,111
So you can't put anything other
than a string, a number, and

942
00:52:27,121 --> 00:52:29,471
a Boolean into a field anyway.

943
00:52:29,471 --> 00:52:35,041
So I don't have support for
arrays, or objects, or even null.

944
00:52:35,541 --> 00:52:41,131
so that kind of makes you realize this is
a relatively simple thing to model anyway.

945
00:52:41,911 --> 00:52:46,396
But yeah, that, that, that's, that's
where we are right now with schemas.

946
00:52:46,446 --> 00:52:51,296
And once you've added a schema,
it will try to massage the data

947
00:52:51,376 --> 00:52:53,886
into that schema, and it'll drop
anything that doesn't match.

948
00:52:54,236 --> 00:52:55,976
that's pretty basic, I will admit.

949
00:52:55,976 --> 00:53:00,316
But there are two, I think, two main
things I need to do from here with this,

950
00:53:00,346 --> 00:53:01,516
because clearly that's not sufficient.

951
00:53:01,826 --> 00:53:03,656
It's great for fun, simple apps.

952
00:53:03,956 --> 00:53:07,516
It's actually, I will say, it does allow
you to do more than you might think.

953
00:53:07,776 --> 00:53:12,456
But anyway, people do want to do arrays,
and That lets you do many to many joins,

954
00:53:12,456 --> 00:53:14,786
and they do want to do objects, so fine.

955
00:53:14,796 --> 00:53:15,876
We should probably get
to that at some point.

956
00:53:16,396 --> 00:53:20,843
So, that's, yeah, that's my big push,
I think, is making time based support

957
00:53:20,883 --> 00:53:22,613
richer data types inside a cell.

958
00:53:22,926 --> 00:53:24,246
I think arrays will be the first.

959
00:53:24,606 --> 00:53:27,896
I'll probably stick to having arrays
of one, type, like it's going to

960
00:53:27,896 --> 00:53:29,916
be all numbers or all strings.

961
00:53:29,926 --> 00:53:31,176
I don't think I'm going
to have mixed arrays.

962
00:53:31,176 --> 00:53:32,276
That could get too tricky.

963
00:53:32,276 --> 00:53:33,786
I still want to have
some kind of validation.

964
00:53:34,263 --> 00:53:35,143
so we'll do that.

965
00:53:35,393 --> 00:53:39,113
, that knocks off a many to many requirement
that a bunch of people have had on GitHub

966
00:53:39,113 --> 00:53:41,303
that I can't currently do very easily.

967
00:53:41,890 --> 00:53:43,590
And so we'll, we'll do that.

968
00:53:43,620 --> 00:53:47,630
Secondly, I would love to do
more with the schemas themselves.

969
00:53:48,000 --> 00:53:52,830
So the, schema dialect that I put
in right now is just, like I said,

970
00:53:53,190 --> 00:53:57,675
a fairly simple description of what
the rows are, but There's Zod in the

971
00:53:57,675 --> 00:54:01,225
world, and there's Effect, and a bunch
of other ways that people like to

972
00:54:01,225 --> 00:54:05,401
express schemas, and if they've already
built their schema for some other part

973
00:54:05,401 --> 00:54:08,371
of the app, or they've built it for
some, you know, some other part of the

974
00:54:08,371 --> 00:54:12,921
system, maybe up on the server, like,
how can they then turn that into the

975
00:54:13,631 --> 00:54:15,991
schema that resides in the app itself?

976
00:54:16,251 --> 00:54:22,821
So I have no doubt that I will be building
Zod to TinyBase Converter, and Effect

977
00:54:22,821 --> 00:54:27,341
to TinyBase Converter or some, some,
something to map, map those schemas in.

978
00:54:27,711 --> 00:54:30,931
Still doesn't solve your problem
of migration, and I will admit

979
00:54:30,961 --> 00:54:34,031
that I am a bit daunted by that.

980
00:54:34,251 --> 00:54:36,991
In general, I am daunted by the
whole space of anything that

981
00:54:36,991 --> 00:54:41,255
requires build time code mods and,
you know, running generated code.

982
00:54:42,655 --> 00:54:46,375
Like, I just hate that because immediately
you've got a team of 10 people and all

983
00:54:46,380 --> 00:54:47,665
of their artifacts get out of sync.

984
00:54:47,670 --> 00:54:48,925
I've seen that at Facebook, right?

985
00:54:49,315 --> 00:54:51,325
Whether it's GraphQL or what have you.

986
00:54:51,595 --> 00:54:55,285
So I, always gonna be trying to look
for solutions that don't require you

987
00:54:55,285 --> 00:55:00,255
to run a build step, to generate some
magic code that you then have to remember

988
00:55:00,255 --> 00:55:04,605
to link in, how to actually avoid that
step and still do schema migration.

989
00:55:05,435 --> 00:55:06,795
is not quite in my head yet.

990
00:55:07,065 --> 00:55:09,535
So I share your sentiment.

991
00:55:09,535 --> 00:55:11,905
These things are underdeveloped,
but I don't have an answer for you.

992
00:55:12,573 --> 00:55:12,933
Right.

993
00:55:12,983 --> 00:55:18,233
I can share my thoughts on it, which is,
kind of like an architectural one, that

994
00:55:18,233 --> 00:55:23,223
has quite a lot of implications, but those
implications are appealing to me, I would

995
00:55:23,223 --> 00:55:28,793
separate the read path from the write path
and have the write path be event driven.

996
00:55:29,403 --> 00:55:32,983
And that allows me to do
sort of event sourcing.

997
00:55:33,023 --> 00:55:37,373
So similar to how Redux works,
but, persisted and distributed

998
00:55:37,653 --> 00:55:39,143
Redux, if you, if you want.

999
00:55:39,543 --> 00:55:43,943
And, then like the way, how you
interpret your Redux events.

1000
00:55:44,388 --> 00:55:47,168
you can interpret them however
you want, and you can very

1001
00:55:47,168 --> 00:55:48,768
easily change that over time.

1002
00:55:49,168 --> 00:55:53,178
So you basically just go through the
entire event source, the entire event

1003
00:55:53,188 --> 00:55:58,518
log of events, the entire history,
and your app database that you

1004
00:55:58,518 --> 00:56:01,718
read from, that is just, a result.

1005
00:56:01,988 --> 00:56:06,418
By going through all the events
and every event, you might come

1006
00:56:06,418 --> 00:56:08,468
across like a user signed up event.

1007
00:56:08,798 --> 00:56:14,688
, you then translate into a insert
into users with all the values.

1008
00:56:15,078 --> 00:56:19,458
And you can change the  user table
at any moment, you can, instead of

1009
00:56:19,468 --> 00:56:23,608
having one user table, you can have
a customer's table and an employee's

1010
00:56:23,628 --> 00:56:26,398
table and just reinterpret the events.

1011
00:56:26,428 --> 00:56:29,668
And so this way, you don't
have schema migrations at all.

1012
00:56:29,878 --> 00:56:33,338
You just change sort of the
. Interpretation of your event.

1013
00:56:33,748 --> 00:56:36,528
it requires a bit of a different
architectural approach and I'm

1014
00:56:36,748 --> 00:56:40,568
building LiveStore all around
this idea, which is very different

1015
00:56:40,858 --> 00:56:42,518
from, from other approaches.

1016
00:56:42,878 --> 00:56:47,148
But it's the most principled approach
that I can currently think of in

1017
00:56:47,148 --> 00:56:51,228
terms of schema migrations, where you
don't do like my schema migrations,

1018
00:56:51,228 --> 00:56:53,438
basically just I design a new schema.

1019
00:56:53,893 --> 00:56:58,423
And I target that and there's
no, like, up or down scripts.

1020
00:56:58,733 --> 00:57:02,463
and so that is very appealing, but
it has other downsides as well.

1021
00:57:02,713 --> 00:57:07,053
But this is certainly an idea that I,
that I think is worth exploring more.

1022
00:57:07,456 --> 00:57:08,186
No, I like that.

1023
00:57:08,186 --> 00:57:12,044
And it also shares, , Similarities
with what I'm separately having to do

1024
00:57:12,054 --> 00:57:18,454
for the, native CRDT synchronization,
as of TinyBase version 5, which at

1025
00:57:18,454 --> 00:57:21,704
the time we're speaking isn't quite
released, but by the time this podcast

1026
00:57:21,714 --> 00:57:22,834
is out might have been released.

1027
00:57:22,834 --> 00:57:24,884
So, hey everybody, go download version 5.

1028
00:57:25,094 --> 00:57:29,334
but no, it's, it's got a native CRDT
support and I do that by sending,

1029
00:57:29,604 --> 00:57:32,944
you know, basically little, little
messages, but those are the data.

1030
00:57:33,304 --> 00:57:33,914
level, right?

1031
00:57:33,984 --> 00:57:37,814
It's, you know, here's, here's how
this cell changed, and I wonder whether

1032
00:57:37,834 --> 00:57:41,754
like there's some higher abstraction
for those messages that is then sort

1033
00:57:41,754 --> 00:57:45,824
of schema agnostic or that can be
mapped into whatever the schema is.

1034
00:57:45,844 --> 00:57:49,404
Because by the way, the minute you
start synchronizing things, the schemas

1035
00:57:49,424 --> 00:57:53,204
getting out of date is going to become
an issue very quickly, because maybe

1036
00:57:53,204 --> 00:57:55,684
you've updated the app on your phone,
but you haven't updated the app on

1037
00:57:55,684 --> 00:57:57,734
your desktop, but now they're jogging.

1038
00:57:58,004 --> 00:58:01,144
You know, WebSockets to each other
and all hell breaks loose because

1039
00:58:01,144 --> 00:58:02,244
the schemas weren't quite the same.

1040
00:58:02,624 --> 00:58:03,864
It's all questions at the moment.

1041
00:58:04,288 --> 00:58:04,548
Yeah.

1042
00:58:04,558 --> 00:58:07,558
I think there's a whole episode
just to be done around that.

1043
00:58:07,758 --> 00:58:11,768
Happy to form a little working group
around this, but I think that goes

1044
00:58:11,778 --> 00:58:13,798
beyond the scope of, of this podcast.

1045
00:58:14,438 --> 00:58:18,228
but yeah, I think you've come really,
really far with TinyBase and this

1046
00:58:18,238 --> 00:58:24,389
is, I think, a very common area of
the local-first technologies part

1047
00:58:24,739 --> 00:58:27,979
that is not yet as fully explored.

1048
00:58:28,069 --> 00:58:32,979
and I've just changed my priorities
to go double down on that from

1049
00:58:32,979 --> 00:58:36,709
the beginning, since I know like
how gnarly this is to deal with.

1050
00:58:37,161 --> 00:58:40,821
Well, can I just say that, you know,
from the point of view of exhaustiveness,

1051
00:58:41,241 --> 00:58:45,831
there are many, many unsolved
problems in the local-first space.

1052
00:58:46,271 --> 00:58:50,451
And I have a horrible feeling
that it's easy to think that

1053
00:58:50,471 --> 00:58:51,961
synchronization is the problem.

1054
00:58:52,021 --> 00:58:54,471
And then once you've solved
synchronization, you're good.

1055
00:58:55,066 --> 00:58:56,756
Well, I don't think that's true.

1056
00:58:57,226 --> 00:59:03,086
And the reason I think that is that
I've tried building some local-first

1057
00:59:03,106 --> 00:59:07,806
apps that, you know, have things like
anonymous versus authenticated access,

1058
00:59:08,056 --> 00:59:14,386
or that have private data versus shared
data, or that have online, offline, and,

1059
00:59:14,446 --> 00:59:18,576
you basically multiply this state machine
together and you've got like, you know,

1060
00:59:18,852 --> 00:59:22,702
two to the power of four combinations
of state that your clients can be in.

1061
00:59:23,092 --> 00:59:23,532
And.

1062
00:59:23,802 --> 00:59:26,292
It's all very well being able to
synchronize data back and forwards, but,

1063
00:59:26,362 --> 00:59:29,882
like, you don't want to synchronize a
non shared store with another user, or

1064
00:59:29,882 --> 00:59:34,102
you don't want to share an authenticated,
you know, you brought a copy of an

1065
00:59:34,102 --> 00:59:38,162
authenticated database to be local,
but now you log out and now that's

1066
00:59:38,162 --> 00:59:40,872
got to go, like, the state machine
of what it actually takes to build a

1067
00:59:40,872 --> 00:59:44,022
real app like Figma or  I don't know.

1068
00:59:45,002 --> 00:59:48,942
It's like, wow, there are lots of crazy,
crazy transitions that can change here.

1069
00:59:49,292 --> 00:59:52,472
And I don't think anyone's really
thinking about all of those.

1070
00:59:52,472 --> 00:59:55,612
I think we all got hung up on, oh,
once we crack CRDTs, we'll be good.

1071
00:59:56,042 --> 00:59:57,402
No, no, no, no, that's the easy part.

1072
00:59:57,632 --> 01:00:00,762
It's not state management, it's the
state of the state management in a way.

1073
01:00:00,762 --> 01:00:03,242
It's like, should I be
synchronizing this data?

1074
01:00:03,502 --> 01:00:07,552
Because this person isn't logged in,
or is logged in, or is online, or is

1075
01:00:07,552 --> 01:00:11,492
offline, or has shared this document,
or hasn't shared this document, and

1076
01:00:11,632 --> 01:00:14,192
that is actually unsolved, I think.

1077
01:00:14,702 --> 01:00:19,382
So I built a little sample app called
Tiny Rooms a way back, and like,

1078
01:00:19,382 --> 01:00:21,742
the app itself is stupid, it's just
dragging rectangles around, but like,

1079
01:00:21,742 --> 01:00:25,182
I tried to model all of these different
states, and it was really hard.

1080
01:00:25,182 --> 01:00:26,262
Like, I was, oh god.

1081
01:00:27,367 --> 01:00:30,737
I would hate to be actually
trying to build a production grade

1082
01:00:30,837 --> 01:00:33,417
local-first app at the moment because
those problems are really hard.

1083
01:00:33,843 --> 01:00:39,213
Yeah, I think the, the benefits
are that if you're building linear

1084
01:00:39,253 --> 01:00:43,493
or if you're building Figma or
if you're building, Tiny rooms.

1085
01:00:43,783 --> 01:00:49,043
the advantage for you is that you have
very specific trade offs, very specific

1086
01:00:49,073 --> 01:00:51,913
constraints that work for your app.

1087
01:00:52,203 --> 01:00:55,783
And so you can take tons of
shortcuts that for a more

1088
01:00:55,793 --> 01:00:57,653
general solution are not viable.

1089
01:00:57,933 --> 01:00:59,673
But for your app works.

1090
01:01:00,233 --> 01:01:04,283
And so, given that, well, there,
there's many trade offs that

1091
01:01:04,303 --> 01:01:07,943
Figma can make that would not work
for Linear and, and vice versa.

1092
01:01:08,233 --> 01:01:12,343
But I think that is  where you can
still build things in a local-first way,

1093
01:01:12,623 --> 01:01:15,233
that is like competitively, beneficial.

1094
01:01:15,843 --> 01:01:20,003
but I agree having the best of
all worlds, is where we're a few

1095
01:01:20,383 --> 01:01:22,423
days away from that, at least.

1096
01:01:22,817 --> 01:01:23,267
Yeah.

1097
01:01:23,307 --> 01:01:25,747
So I think that's one of the
curses of being a, a tools

1098
01:01:25,747 --> 01:01:27,307
builder like, like you, right.

1099
01:01:27,447 --> 01:01:30,227
you know, I feel that I'm building
shovels for people who are going

1100
01:01:30,227 --> 01:01:31,367
to go off digging for gold.

1101
01:01:31,837 --> 01:01:34,207
but I have to build a shovel
that'll work in all different

1102
01:01:34,217 --> 01:01:36,537
types of terrain to be successful.

1103
01:01:36,562 --> 01:01:39,662
Um, and so like I said, you know,
is it going to be online, offline,

1104
01:01:39,692 --> 01:01:43,412
auth, not auth, stored locally,
stored remotely  shared or not shared?

1105
01:01:43,412 --> 01:01:45,832
Like, okay, now 16 combinations,
got to support all 16.

1106
01:01:46,172 --> 01:01:48,202
Whereas yes, if you're Figma,
you can say, well, no, you

1107
01:01:48,202 --> 01:01:49,412
can't ever use it anonymously.

1108
01:01:49,422 --> 01:01:50,202
You've always got to be logged in.

1109
01:01:50,352 --> 01:01:50,522
It's like, oh, great.

1110
01:01:50,522 --> 01:01:51,432
Okay, fine.

1111
01:01:51,542 --> 01:01:53,442
Like, I've just reduced
that problem to eight.

1112
01:01:53,755 --> 01:01:54,145
Yeah.

1113
01:01:54,478 --> 01:01:56,268
Pick your trade offs very carefully.

1114
01:01:56,473 --> 01:01:59,633
And so this is why I'm also,
why I'm working on Overtone

1115
01:01:59,633 --> 01:02:01,883
and LiveStore at the same time.

1116
01:02:02,143 --> 01:02:08,133
So if your app is sort of like
Overtone esque shaped, then LiveStore

1117
01:02:08,173 --> 01:02:09,423
will work really well for you.

1118
01:02:09,853 --> 01:02:13,943
If it looks rather like Facebook,
like a social network, or has like

1119
01:02:13,943 --> 01:02:18,233
some very different shapes and trade
offs, then it's not as good of a fit.

1120
01:02:18,233 --> 01:02:22,390
But I think this is also what's so
nice about having all those different

1121
01:02:22,390 --> 01:02:26,900
local-first tool vendors is they have all
their different starting points and all

1122
01:02:26,900 --> 01:02:28,980
their different thoughts on trade offs.

1123
01:02:29,380 --> 01:02:32,607
And, I think this is where we're
going to have a great shovel

1124
01:02:32,627 --> 01:02:34,477
for many different terrains.

1125
01:02:34,853 --> 01:02:35,023
Yeah.

1126
01:02:35,023 --> 01:02:36,083
I think that's exactly right.

1127
01:02:36,143 --> 01:02:37,493
You know, it's a dilemma.

1128
01:02:37,863 --> 01:02:41,773
Do you build a tool that
fits one niche perfectly?

1129
01:02:41,813 --> 01:02:45,213
And, yeah, of course, that really informs,
and you'll build a, you know, brilliant

1130
01:02:45,753 --> 01:02:47,653
tool for the one job you have in mind.

1131
01:02:48,153 --> 01:02:51,493
but at the same time, you
may have limited your market.

1132
01:02:51,533 --> 01:02:54,453
Now, fortunately, I don't have to think
about those things because, you know, it's

1133
01:02:54,453 --> 01:02:56,213
not a commercial, commercial business.

1134
01:02:56,473 --> 01:02:58,843
and I'm, but I'm trying to keep as
many People are happy as possible.

1135
01:02:58,843 --> 01:03:01,553
And if I'm just listening to the
feedback that's coming in on, on

1136
01:03:01,573 --> 01:03:04,203
GitHub and people are saying, Oh, I
want it to go off in this direction.

1137
01:03:04,203 --> 01:03:05,743
And, Oh, someone else wants
to go off in that direction.

1138
01:03:05,743 --> 01:03:10,103
It's like, okay  I'm going
to try to, maybe I'm going to

1139
01:03:10,103 --> 01:03:11,373
try to keep everybody happy.

1140
01:03:11,703 --> 01:03:13,153
but then the complexity falls onto me.

1141
01:03:13,303 --> 01:03:16,773
And that's where being a tools
builder starts getting hard work.

1142
01:03:16,773 --> 01:03:17,483
You know, this.

1143
01:03:18,540 --> 01:03:18,880
Right.

1144
01:03:18,960 --> 01:03:23,250
I mean, for, for what it's worth, I
think I'm trying to actually, write

1145
01:03:23,260 --> 01:03:27,680
down the cases where LiveStore is
not a great fit for, and I'm trying

1146
01:03:27,700 --> 01:03:31,320
to be like, very explicit about
the trade offs that I'm making.

1147
01:03:31,320 --> 01:03:35,550
So for example, LiveStore right now
expects you to load all of your data

1148
01:03:35,855 --> 01:03:38,895
into a single SQLite in memory database.

1149
01:03:39,115 --> 01:03:44,735
Luckily, SQLite is very efficient, like
based on my benchmarks and testing, much

1150
01:03:44,735 --> 01:03:47,115
more efficient than like JSON in memory.

1151
01:03:47,115 --> 01:03:51,165
It's much more efficient to keep like
hundreds of thousands of rows in,

1152
01:03:51,175 --> 01:03:57,075
in memory SQLite as you keep them in
just JavaScript objects in, in memory.

1153
01:03:57,458 --> 01:04:01,168
you need to just, deserialize
the, just a few ones that you

1154
01:04:01,168 --> 01:04:04,578
actually want to like currently
keep in memory for, for your query.

1155
01:04:05,128 --> 01:04:06,998
And so, but that's a major trade off.

1156
01:04:07,028 --> 01:04:11,228
If you have your database, if
that's necessarily five gigabytes.

1157
01:04:11,503 --> 01:04:14,193
Then LiveStore is probably
not a great fit for you.

1158
01:04:14,493 --> 01:04:20,073
Or if you don't want to follow the more
like event sourced, nature of it, then

1159
01:04:20,073 --> 01:04:21,563
it's probably also not a good fit for it.

1160
01:04:21,573 --> 01:04:26,183
But I think this is what makes it
more specific for when it's a good

1161
01:04:26,183 --> 01:04:28,403
fit for someone, whereas if it's not.

1162
01:04:28,813 --> 01:04:31,493
So actually this brings us onto
an interesting thing that I think

1163
01:04:31,503 --> 01:04:34,023
this community needs, which is.

1164
01:04:34,598 --> 01:04:38,788
kind of a, a community view of what
all these pros and cons are of the

1165
01:04:38,788 --> 01:04:43,548
different solutions and what the
decision tree should be if you want

1166
01:04:43,548 --> 01:04:45,048
to build an app of a certain type.

1167
01:04:45,088 --> 01:04:47,238
You know, am I going to be online
or am I going to be offline?

1168
01:04:47,248 --> 01:04:48,548
Am I going to be authed or not authed?

1169
01:04:48,918 --> 01:04:52,448
You know, how do I work my way down to
what is going to be the best solution?

1170
01:04:52,968 --> 01:04:54,678
Because of course, you talk to
a vendor, they're going to say,

1171
01:04:54,678 --> 01:04:55,458
oh, well, we can do everything.

1172
01:04:55,868 --> 01:05:00,788
but something that allows people to
know when, you know, when should I use.

1173
01:05:00,808 --> 01:05:04,336
In something like the more mature
front end world, people know when

1174
01:05:04,336 --> 01:05:07,570
they should be using React versus
Svelte or whatever, I guess.

1175
01:05:07,570 --> 01:05:12,568
There are plenty of places you can go
and read up about what the pros and the

1176
01:05:12,568 --> 01:05:14,332
cons are of these different solutions.

1177
01:05:14,332 --> 01:05:18,378
But right now, if you're looking
at Database Sync Technology A and

1178
01:05:18,378 --> 01:05:22,578
Database Sync Technology B, they're
both local-first, apparently, right?

1179
01:05:22,578 --> 01:05:24,418
But one's going to be better
for one thing versus another.

1180
01:05:24,418 --> 01:05:26,188
Who's going providing that commentary.

1181
01:05:26,188 --> 01:05:30,008
And I think we haven't got that critical
mass of users yet to be able to say, well,

1182
01:05:30,008 --> 01:05:32,988
I tried it and this didn't scale, but
I went to this one and this one worked.

1183
01:05:33,168 --> 01:05:34,068
Someone else saying the opposite.

1184
01:05:34,078 --> 01:05:36,068
And then you can like have that debate.

1185
01:05:36,568 --> 01:05:37,118
and so.

1186
01:05:38,158 --> 01:05:40,458
Actually, this is something I didn't
mention, but, you know, one of, one

1187
01:05:40,458 --> 01:05:44,068
of the parts of my local-first journey
was, was putting together a directory

1188
01:05:44,068 --> 01:05:45,668
of these solutions that I was finding.

1189
01:05:46,438 --> 01:05:50,558
And so I launched that as
the localfirstweb.dev site.

1190
01:05:50,598 --> 01:05:53,498
And that was partly me just
trying to enumerate what these

1191
01:05:53,498 --> 01:05:54,718
different solutions were.

1192
01:05:55,128 --> 01:05:57,188
And obviously a community
is built up around that.

1193
01:05:57,188 --> 01:05:58,758
And now we obviously have
the conference as well.

1194
01:05:58,758 --> 01:06:01,958
And what I'm really hoping is that we
see more and more people building real

1195
01:06:01,958 --> 01:06:05,675
apps, learning What trade offs they're
having to make, and which of these

1196
01:06:05,675 --> 01:06:07,625
solutions they're then converging on.

1197
01:06:08,120 --> 01:06:11,030
given those and, and I think it's fine
to have lots of different types of tools.

1198
01:06:11,040 --> 01:06:13,310
Sometimes you need a pickaxe,
sometimes you need a shovel,

1199
01:06:13,460 --> 01:06:16,370
sometimes you need a pan to get
the gold out of the river, right?

1200
01:06:16,720 --> 01:06:19,570
But it's not always obvious which
tool you should take until you've

1201
01:06:19,570 --> 01:06:21,860
actually gone out into the hills
and started looking for gold.

1202
01:06:22,230 --> 01:06:24,600
Sorry to stretch the analogy, maybe
it's because I lived in California

1203
01:06:24,620 --> 01:06:27,510
for a while, but you know, I think
we're not at that point yet, right?

1204
01:06:27,510 --> 01:06:30,820
We haven't had enough, we've not had
enough miners going up into them,

1205
01:06:30,820 --> 01:06:32,210
there hills to go look for the gold.

1206
01:06:32,463 --> 01:06:34,983
so we haven't formed opinions about
what the right trade offs are and

1207
01:06:35,003 --> 01:06:36,393
which are the right tool chains to use.

1208
01:06:36,828 --> 01:06:37,658
We will get there.

1209
01:06:37,748 --> 01:06:42,738
So speaking of real apps, it seems like
I've recently nerd sniped on Twitter.

1210
01:06:42,738 --> 01:06:48,268
I've recently nerd sniped you into
building another app on top of TinyBase,

1211
01:06:48,548 --> 01:06:51,158
which is a local-first GitHub client.

1212
01:06:51,448 --> 01:06:53,708
And you've made quite a
lot of progress on that.

1213
01:06:53,778 --> 01:06:54,958
Do you, do you mind sharing more?

1214
01:06:55,233 --> 01:06:55,703
Sure.

1215
01:06:55,813 --> 01:06:58,013
So that was a, that was
a clinical nerd snipe.

1216
01:06:58,053 --> 01:07:01,483
That was, that was one of the
finest even though I was the victim.

1217
01:07:01,853 --> 01:07:04,813
So as I mentioned, you know, one of my
original ideas for an app that would

1218
01:07:04,813 --> 01:07:08,543
use something like TinyBase was an open
source dashboard that would let you see

1219
01:07:08,573 --> 01:07:12,313
large numbers of repos and, and, and, and
study them and understand them at scale.

1220
01:07:12,580 --> 01:07:14,240
And I just never got
around to building it.

1221
01:07:14,240 --> 01:07:17,570
And then of course you said something on
Twitter like, Oh, wouldn't it be awesome

1222
01:07:17,570 --> 01:07:19,300
if there was a local-first GitHub client?

1223
01:07:19,320 --> 01:07:19,910
I'm like, No!

1224
01:07:20,680 --> 01:07:21,030
Damn it!

1225
01:07:21,100 --> 01:07:22,300
That's what I was supposed to build!

1226
01:07:22,310 --> 01:07:23,060
Now I remember!

1227
01:07:23,470 --> 01:07:28,340
So I  took that and I figured
that I would maybe go and put

1228
01:07:28,340 --> 01:07:30,840
my, my code where my mouth was.

1229
01:07:31,030 --> 01:07:36,380
So I started a little repo
called TinyHub, which is in the

1230
01:07:36,380 --> 01:07:39,130
same  , parent org as TinyBase.

1231
01:07:39,540 --> 01:07:41,200
So I guess you have show notes.

1232
01:07:41,200 --> 01:07:43,700
There'll be a link in the show notes
and, people can go check that out.

1233
01:07:44,020 --> 01:07:48,165
And yes, it's a GitHub client for
running locally in your browser.

1234
01:07:48,438 --> 01:07:52,148
And I wanted to try and build it as
quickly as I could, just to hopefully

1235
01:07:52,398 --> 01:07:55,718
prove to myself that building
apps with TinyBase would be fun.

1236
01:07:56,018 --> 01:08:01,428
And what it does is it, there's
a quick bit of GitHub OAuth right

1237
01:08:01,428 --> 01:08:05,658
at the beginning, and it then will
pull repos that are either starred

1238
01:08:05,918 --> 01:08:09,973
or that you, have personally, or
any orgs that you're a member of if

1239
01:08:09,973 --> 01:08:11,933
you accept those OAuth permissions.

1240
01:08:12,113 --> 01:08:16,673
Anyway, long story short, it pulls
the GitHub data via the API down

1241
01:08:16,703 --> 01:08:18,983
into a local TinyBase instance.

1242
01:08:19,303 --> 01:08:20,443
In fact, a number of instances.

1243
01:08:20,483 --> 01:08:24,863
It actually has, there's a TinyBase
instance per repo, because if you

1244
01:08:24,863 --> 01:08:29,333
pull React, like, okay, now we've got
20, 000 pull requests or something.

1245
01:08:29,763 --> 01:08:35,257
So it will pull data locally,
stores it in local storage.

1246
01:08:35,547 --> 01:08:38,277
Yes which seems to be fine, actually.

1247
01:08:38,637 --> 01:08:42,917
, just, it's a, the first hundred
records which is the basic

1248
01:08:42,997 --> 01:08:44,217
pagination for, for GitHub.

1249
01:08:44,247 --> 01:08:48,777
So it's, it's not, you know, a
comprehensive open source dashboard, but

1250
01:08:48,777 --> 01:08:53,047
it at least gives you A sample of, you
know, 100 repos from 100 orgs and up to

1251
01:08:53,047 --> 01:08:54,667
100 pull requests and issues from each.

1252
01:08:55,000 --> 01:08:58,800
And yeah, then just paint a
React UI out of that data.

1253
01:08:58,830 --> 01:09:02,110
And if you go check the repo,
you'll see I put a little video

1254
01:09:02,110 --> 01:09:03,770
on the front page of the readme.

1255
01:09:04,027 --> 01:09:06,737
And of course, the beauty of this
is that now all of this GitHub

1256
01:09:06,937 --> 01:09:08,437
data is sitting in your browser.

1257
01:09:09,052 --> 01:09:14,422
And, it's in memory, but you can
flip through it at 16 milliseconds

1258
01:09:14,432 --> 01:09:15,862
a frame, to your heart's content.

1259
01:09:15,872 --> 01:09:19,932
So, you know, you press the, you press
the down cursor and it whizzes down

1260
01:09:19,932 --> 01:09:20,882
through the pull requests and it's pffft.

1261
01:09:21,895 --> 01:09:22,905
Views them all instantly.

1262
01:09:22,945 --> 01:09:23,995
Not a spinner in sight.

1263
01:09:24,035 --> 01:09:24,745
It's pretty awesome.

1264
01:09:25,115 --> 01:09:28,565
I'm not sure it's a particularly useful
tool at this point because it's read only.

1265
01:09:28,755 --> 01:09:33,445
Um, and it obviously has to do some work
to pull the data down at the beginning.

1266
01:09:33,795 --> 01:09:38,125
But it certainly, I hope, emphasizes
the fact that if you co locate your

1267
01:09:38,135 --> 01:09:41,915
data with the app, which I think is
kind of like what this, this, this

1268
01:09:41,915 --> 01:09:44,772
local-first thing should be all
about at some point, it's amazing.

1269
01:09:44,832 --> 01:09:46,202
Like, the UX is spectacular.

1270
01:09:46,442 --> 01:09:49,682
Um, and you can just paginate through
this stuff at the speed of thought.

1271
01:09:50,012 --> 01:09:51,752
Which is really amazing.

1272
01:09:52,162 --> 01:09:56,102
I will just add a little side note here,
is my philosophy around local-first, or

1273
01:09:56,102 --> 01:10:00,552
my motivation for local-first, apart from
being on a boat, is the user experience.

1274
01:10:01,212 --> 01:10:03,392
I'm just tired of looking at
spinners, because I'm waiting for

1275
01:10:03,392 --> 01:10:06,002
something to pull down and cache
locally and then get thrown away.

1276
01:10:06,012 --> 01:10:08,382
Like, if I can get everything into
the browser as soon as possible,

1277
01:10:09,052 --> 01:10:13,182
and then just go through it at 16
milliseconds That's, that's amazing.

1278
01:10:13,972 --> 01:10:18,455
So hopefully that has emphasized
that point of local-first.

1279
01:10:18,475 --> 01:10:20,035
Yes, it's about data governance.

1280
01:10:20,035 --> 01:10:20,365
Yes.

1281
01:10:20,365 --> 01:10:21,935
It's about, you know,
owning your own data.

1282
01:10:22,295 --> 01:10:22,595
Yes.

1283
01:10:22,595 --> 01:10:26,395
It's about you know, all the other
things that are laid out in many, many

1284
01:10:26,395 --> 01:10:31,555
other essays other than mine, but like
having a UX like that is really, for me,

1285
01:10:31,555 --> 01:10:33,725
what it's all about, that's the focus.

1286
01:10:33,725 --> 01:10:37,095
, and yeah, so I'd encourage people
to go check out TinyHub and that's

1287
01:10:37,095 --> 01:10:41,165
me building what I think is a
state of the art TinyBase app.

1288
01:10:42,195 --> 01:10:47,235
I would still say that to make it fully
functional, making it read write is

1289
01:10:47,245 --> 01:10:50,852
a little more tricky because whilst
GitHub has some pretty awesome bulk

1290
01:10:51,072 --> 01:10:58,002
read APIs the write APIs are a little
different and making changes to a

1291
01:10:58,002 --> 01:11:01,232
local datastore and then going back
online and reconciling that back up

1292
01:11:01,232 --> 01:11:03,882
to GitHub is not as easy as it sounds.

1293
01:11:04,172 --> 01:11:07,357
I'm sure it's Events are probably the
answer to that, is what you'll say.

1294
01:11:07,717 --> 01:11:09,667
Um, but but I'm not there yet.

1295
01:11:09,973 --> 01:11:14,303
Yeah, again, to my earlier joke that
we have more tools than, apps at this

1296
01:11:14,303 --> 01:11:18,983
point, I really want to just add to the
pool of local-first demos, right, but

1297
01:11:19,143 --> 01:11:23,063
add to the number of apps that show what
could be done, and really emphasize what

1298
01:11:23,093 --> 01:11:27,643
the benefits are of this whole movement
rather than just building shovels.

1299
01:11:27,643 --> 01:11:30,143
I'm actually going to go out and
look for some gold myself as well,

1300
01:11:30,193 --> 01:11:31,383
just to make sure the shovel's okay.

1301
01:11:31,743 --> 01:11:35,523
I think that's a wonderful
place to, to wrap it here.

1302
01:11:35,783 --> 01:11:40,643
James, thank you so much for coming on
the show today, sharing all of your wisdom

1303
01:11:40,663 --> 01:11:43,043
on TinyBase, the path that led you here.

1304
01:11:43,303 --> 01:11:43,973
Thank you so much.

1305
01:11:44,327 --> 01:11:48,367
It's been a huge pleasure and  I wish
the podcast the greatest success.

1306
01:11:48,367 --> 01:11:52,647
I'm so excited that you've set it up
and honored to be a small part of it.

1307
01:11:52,647 --> 01:11:56,007
And thank you to everybody
that has made it this far and,

1308
01:11:56,257 --> 01:11:57,507
followed the TinyBase journey.

1309
01:11:57,917 --> 01:12:00,307
It's been a privilege to work on
this and share it with you all.

1310
01:12:00,831 --> 01:12:03,241
Thank you for listening to
the local-first FM podcast.

1311
01:12:03,471 --> 01:12:06,981
If you've enjoyed this episode and haven't
done so already, please subscribe and

1312
01:12:06,981 --> 01:12:08,541
leave a review wherever you're listening.

1313
01:12:08,911 --> 01:12:10,911
Please also share this
episode with others.

1314
01:12:11,211 --> 01:12:14,011
Spreading the word about the
podcast is a great way to

1315
01:12:14,011 --> 01:12:15,611
support it and to keep it going.

1316
01:12:16,081 --> 01:12:20,091
A special thanks again to Rocicorp
and Expo for supporting this podcast.

1317
01:12:20,261 --> 01:12:21,051
See you next time.