Revolutionizing API Syntax and Schema Management with Jazz Framework - JSJ 663

In today's episode, Charles and AJ are joined by Anselm Eickhoff, a trailblazing full-stack software engineer. Anselm delves into the world of "Local First" software development and the innovative tool he’s developed, "Jazz." They explore how Jazz leverages schema information for type inference and runtime validation, enabling real-time collaboration and seamless offline functionality. They dive into the simplifications brought by Jazz's API changes, the flexibility offered through open protocols, and the local-first approach using CRDTs.

Special Guests: Anselm Eickhoff

Show Notes

In today's episode, Charles and AJ are joined by Anselm Eickhoff, a trailblazing full-stack software engineer. Anselm delves into the world of "Local First" software development and the innovative tool he’s developed, "Jazz." They explore how Jazz leverages schema information for type inference and runtime validation, enabling real-time collaboration and seamless offline functionality. They dive into the simplifications brought by Jazz's API changes, the flexibility offered through open protocols, and the local-first approach using CRDTs.
They also tackle Jazz’s impressive backend infrastructure and its shift to direct disk storage, along with insights into the challenges and emerging support structures faced by early adopters. Anselm shares real-world applications, advanced analytics capabilities, and the future outlook for Jazz, emphasizing performance, resilience, and data privacy.
Plus, stay tuned for a lighthearted detour into board games and TV recommendations, as well as updates on Charles’ AI Dev Boot Camp and exciting developments on the Top End Devs platform. This episode is packed with cutting-edge insights and practical advice for developers looking to integrate advanced real-time features and streamline their app development processes. 

Socials


Picks

Transcript

Charles Max Wood [00:00:05]:
Hey, folks. Welcome back to another episode of JavaScript Jabber. This week on our panel, we have AJ O'Neil.

AJ O'Neil [00:00:12]:
Yo. Yo. Yo. Coming at you live from the sickness. No. I'm feeling better today. Yesterday, I was a little under the weather. I just slept all day, and now I feel good.

AJ O'Neil [00:00:23]:
I'm just a little groggy.

Charles Max Wood [00:00:24]:
I still have some turkey soup from Thanksgiving. Maybe I'll drop by. I'm Charles Max with from Top End Devs. And, this week, we're we have a special guest. It's Anselm. Sorry. I don't have your last name in front of me. I usually

Anselm Eickhoff [00:00:39]:
My last name is Aykoff, but it that's, like, even more difficult. Don't don't worry about it. Nice to meet you guys. Very happy to be here.

Charles Max Wood [00:00:47]:
Yeah. The foreign names kinda throw us off sometimes. You wanna introduce yourself real quick? I mean, I have jazz.tools. It's something you work on. But,

Anselm Eickhoff [00:00:57]:
yeah. Sure. So I'm, like, broadly speaking, a full stack software engineer. I've worked kind of as a freelancer most of my life. I'm originally from Germany. I live in the UK now, and I kind of just kept building apps for different companies, always kind of taking them from 0 to 1, and just felt like I'm always doing the same stuff. And I never really had a good answer to how to solve that problem until I ran into what is now known as Local First, and that kind of became jazz. That's, like, my mini origin story on that.

Anselm Eickhoff [00:01:30]:
Awesome.

AJ O'Neil [00:01:30]:
So So are you the main person behind Jazz?

Anselm Eickhoff [00:01:34]:
Yeah. So I've I've been working on it for a bit over four and a half years now. And, since this summer, it's a company, and I raised some funding and so on. But before that, it was just, like, my side main project.

AJ O'Neil [00:01:48]:
Nice.

Charles Max Wood [00:01:48]:
Nice. So I just have to ask just right off the bat because you said local first.

Anselm Eickhoff [00:01:55]:
If you go to

Charles Max Wood [00:01:55]:
jazz.tools.a, you know, or jazz.tools, I almost added a dotcom to that. But, guys, there's no dotcom. It's jazz.tools on the Internet, and, it says local first. And, of course, my brain goes through, is it one of these 80 different things? So do you wanna just kind of explain, give us some context of what kind of apps we're looking at and what you mean by local first so that we're not talking about things different things that people are thinking, oh, it's this, and then we're talking about this other thing.

Anselm Eickhoff [00:02:26]:
Yeah. Sure. So, like, local first is kind of a new term and a new sphere. Like, everyone who is into it seems to have bumped into it their own way. And it means, because it's so early in the movement, it means a lot of different things to different people.

Charles Max Wood [00:02:42]:
Right.

Anselm Eickhoff [00:02:42]:
And, I think what everyone has in common in terms of how they would define it is, like, you move away from the traditional stack model where you have a back end and a front end. And most of the authoritative state lives in your database and the back end interacts with that and the front end kind of sends requests to the back end. You move away from that to a new model where you try to keep as much state as possible or maybe even all state in the client, and you just write your UI around that as if you were building basically an old school offline app that just writes to memory into disk. But then that state gets synced to other participants because, of course, you still want to, like, interact with other users, maybe even have real time multiplayer, that sort of stuff. So you kind of the the way I like to look at is it is that we're we're so used to the traditional stack as, like, obviously, that's how you build web apps. But if you think about it, what what the stacks do is they just facilitate sharing state between users. And the way they do that traditionally is by having, like, centralized authoritative state. And and with local first, you just turn that problem around and you're like, what if everyone kept state locally, and then how do we sync between participants?

Charles Max Wood [00:03:58]:
So this reminds me a little bit of how things like WebRTC works, right, where you can have, a lot of times, there's a server that kinda coordinates. So people will hit the server first and say

Anselm Eickhoff [00:04:12]:
Yeah.

Charles Max Wood [00:04:13]:
You know, who else can I connect to? But then you can do peer to peer video. Right? Or you've got other peer to peer apps where, kinda like BitTorrent, I guess. Right? Where if you Yeah. If you know where the other participants are, you can go ahead and share, in this case, as parts of a file, but it's the same idea. Right?

Anselm Eickhoff [00:04:33]:
Yeah. And and, like, I really like this comparison because that lets us get into more precisely what what what it is because something like WebRTC or BitTorrent, that's mostly about the the transport mechanism, like, how do you find the other peers. Local first is kind of, like, almost orthogonal to that. You can do local first in a peer to peer way, but you can also do it with some centralized syncing infrastructure, implements, for example. What local first is about is, mostly solving the problem of, well, if if you write against the state as if it was local state, what should happen if multiple people edit the same piece of content? Again, in the traditional stack model, this problem doesn't really exist because it just depends whoever's request comes first and then there's one central state. In this case, you have distributed state. And how do you solve for conflicts in distributed state? And what you get then is something, that works very similarly to Git. And, again, different local first frameworks or or services do different things, but what seems to be the most common is to rely on a technology called conflict free replicated data types or CRDTs for short.

Anselm Eickhoff [00:05:46]:
That's the term that's starting to be thrown around more. That's an idea that Jazz is based on, that many others are based on. And the way I like to, like, illustrate that is that it it's very much like Git in that you have your local state that you work with, and then you share your edits with other people. And there's something akin to merging and conflict resolution. The difference to Git is that it's much more fine grained. Well, I can get you kind of to pretty large commits, right, over, like, maybe an hour's worth of time or something. For CRDTs, imagine if you made these commits smaller and smaller until, like, every single keystroke and every single, like, edit of an object property becomes a commit, And then that's what you sync. You actually objects no longer are, like, their current state, but they're just represented by the entire history of everything that ever happened to them.

Anselm Eickhoff [00:06:39]:
And, again, I have to be careful here not to get too specific to how Jazz works, how Jazz interpret interprets CRDTs, but this is like a common story. And and,

Charles Max Wood [00:06:49]:
Right.

Anselm Eickhoff [00:06:49]:
What Jazz does basically is you, as the application developer, it gives you an API that makes these objects look like simple, mutable objects that you can write to and read from. Under the hood, it it converts these edits into changes in the history and then kind of reconciles that history with everyone else who's interested in the same object based on their edits. Does does that start to give you an idea?

Charles Max Wood [00:07:11]:
Right. It sounds a little bit more like Google Docs where you might have multiple people editing the same file or the same doc at the same time. And Yeah. As they type, it shows up on my page. And as I type, it shows up on their page. And if we're typing over the same space, then, yeah, it's gotta figure out, okay, how do we how do we figure out whose edits are what? Exactly.

Anselm Eickhoff [00:07:37]:
And and it's kind of clear how that's useful in something like Google Docs where you have real time communication. Mhmm. But the way I like to think about it and and to get back to your original question of, like, what kinds of app is that for. There are a lot of people who are saying, like, look. There's this new niche of local first apps where this kind of way of building apps is particularly suited, and you can see that with your Google Docs example. Mhmm. But my approach there is to be like, no. This is actually a better way to build any kind of app.

Anselm Eickhoff [00:08:06]:
And the real time multiplayer is kind of just the extreme case, and anything less interactive than that can still be solved with the same pattern. And one of the major other features that you get from local first is that it is offline first because you can write against your state locally. Even if you don't have a connection, your app keeps working, and you just sync when you come back online. And you can kind of imagine the spectrum of, like, really intense, really interactive, real time multiplayer on the one end and, like, being completely offline on the other hand. And then in the middle, you have something more like a traditional app where you have, like, some multi user collaborative app, like a productivity app or maybe a social network where you have some frequency of interaction. And so far, we needed very different ways of building apps and frameworks for each of these cases, But CRDTs and the idea of local first is actually something that lets you solve all of these cases with one abstraction. And and what's nice there is that you don't have to choose what kind of app you're going to build because some parts of your app, some features might be more real time. Some features might be, like, less frequent updates, less collaborative, more personal, and so on.

Anselm Eickhoff [00:09:18]:
And that's kind of what really got me in into the idea and where I'm like, oh, this this can actually solve a lot of things.

AJ O'Neil [00:09:25]:
So one one thing I often ask is, what is this not a good use case for? Like, when would I not want to use this? Because I think hearing we can use this for anything is a little bit. It's not it's not helpful to know, like, we can use it for anything. So I think sometimes knowing what we shouldn't use it for helps us to better understand why it's actually really useful. So when would I not want to be using local first or jazz?

Anselm Eickhoff [00:09:58]:
So I'm I'm going to give you a really annoying first answer, which is nothing and and kind of like the counter question, like, what is React not good for, within web apps, let's say? You can kind of You are asking

Charles Max Wood [00:10:12]:
the wrong man about that.

Anselm Eickhoff [00:10:15]:
What's what's your favorite pick? Yeah. What's your favorite pick other than React?

AJ O'Neil [00:10:22]:
No. I don't I don't like React. Yeah. So what

Anselm Eickhoff [00:10:25]:
what would you rather what what we what would you rather use?

AJ O'Neil [00:10:27]:
I just So so first of all, I mostly do back end or libraries. So I do I do tons of front end code, but my front end code is is in libraries where, you know, people are are use using it as a as a library. So it doesn't matter whether it's back end or front end. But when I do JavaScript on the front end, I just use JavaScript now. Like, the DOM is so good.

Anselm Eickhoff [00:10:51]:
Good. Okay.

AJ O'Neil [00:10:52]:
I'm not I'm not building things that are large enough, or I I don't even know if things exist that are large enough that just JavaScript as it is isn't good enough these days.

Anselm Eickhoff [00:11:02]:
Fair fair enough. Fair enough. Okay. Like, I approach

Charles Max Wood [00:11:04]:
is very similar to AJ's where I use a framework called Stimulus

Anselm Eickhoff [00:11:09]:
Mhmm. And

Charles Max Wood [00:11:09]:
then I use another library called Turbo, which is a lot like HTMX. And Yeah. So Interesting. So, so it just gives me a way to organize my Dom calls.

Anselm Eickhoff [00:11:23]:
Cool. Okay. So, yeah, my my comparison there would have gone nowhere because I'm used to to talking to very different people who are very into React. So I would ask them back, like, well, what is React good for? And they would say, well, any kind of app. That's kind of what I was getting at.

AJ O'Neil [00:11:36]:
To React is really good for things that have infinite scrolls. That's what React was designed for. That's what it's really great at.

Charles Max Wood [00:11:44]:
It it so my my thing, and maybe this will give you a better way to answer this, right, is I feel like there are trade offs. Right?

Anselm Eickhoff [00:11:51]:
Of course. Yeah. Sorry. That was the the first, like, annoying part of my answer. To be more precise, like, I I think a better way to say it is that, eventually, I want it to be good for any kind of app. Right. The reason it might not be right now is because we're early and because, specifically for jazz tools, we decided to prioritize certain features over others. Mhmm.

Anselm Eickhoff [00:12:14]:
So, for example, if you have an app where you definitely need authoritative centralized state, like, you're building a bank or something like that. And there can only be one balance of your account at any time. You you could actually build this on top of Jazz that you can implement authoritative state with local first framework, but it's going to be more awkward than the traditional thing.

Charles Max Wood [00:12:40]:
Right. Because you have you have a tighter constraint, and you have to make sure that everything lines up on the front and back end.

Anselm Eickhoff [00:12:46]:
It's it's basically, like, what you do then is you reimplement something like requests on top of the local first state, which sounds elaborate, but actually has some nice drawbacks because you basically get, optimistic updates on the front end for free. But that's kind of that's a way more advanced topic that I wanna get into at this point. Another thing is, like, if you need, some of the more advanced bread and butter database features like indices over huge amounts of data, full text search. That's something that we haven't implemented as features yet, but they're not, like, impossible to do with local first. So this is an interesting example to kind of start giving you an idea of of what kind of apps it's already really good for and maybe where the boundary is like.

AJ O'Neil [00:13:34]:
And are you using Yeah. IndexedDB?

Anselm Eickhoff [00:13:37]:
Yes. That's what we use for in browser persistence. We're currently moving to OPFS, which lets us write directly to to, like, an isolated file system on the client where we implement all the storage there. Is

AJ O'Neil [00:13:50]:
that implemented in browsers now?

Anselm Eickhoff [00:13:52]:
Yes. That's widely supported. Not a lot of people know about it. The nice thing is if you use something like Jazz, that's like I I guess that's a major important point. If you use something like Jazz, you don't need to worry about the persistence and about the networking. You just manipulate objects, basically. Right? And it can have different storage implementations under the hood. It could communicate over WebSockets, WebRTC in the future, maybe something like QUIC.

Anselm Eickhoff [00:14:17]:
And what what that lets you do is, like, really quickly build apps on the abstraction level of, like, what do users do in my app and what kind of objects do they interact with. That's kind of all you have to think about. And what you like, because of the performance characteristics of local first, what you get away with very often if you have apps with, like, small teams where a couple people interact, you can literally keep all the data belonging to that team locally on each device. The only reason it's hard to scale, for example, productivity apps is because in the traditional model, the central database kind of needs to keep the data for every single team, which might be millions of them. With local first, each of the team's devices just needs to keep the state for the whole team, and Linear is actually a good example of an app. They built their whole own local first, technology and infrastructure. They keep all of your team's issues locally on the client, and that gives you incredibly fast UX interaction on the client. We we we see with a lot of jazz apps where people ask us, like, look.

Anselm Eickhoff [00:15:25]:
I want to implement search in my app. So for that, I need an index. Right? And so far in every case, you can literally just brute force your way over every single object in memory, and it's way faster than any, like, search feature against an API that that you've seen in any other app. That's that's kind of what it's already really good at. Obviously Yeah.

AJ O'Neil [00:15:44]:
I've I've noticed that. Like, so many times people, you know, they're thinking too much about optimization, and they don't realize if you don't optimize this like, optimizing it in many cases makes it slower because then you're adding all the overhead of the algorithm and the sifting. And, like, if it's less than 10,000 items, if maybe a 100,000 items, just, like, brute force it, it's the fastest way.

Anselm Eickhoff [00:16:08]:
Well, that's where Say again.

Charles Max Wood [00:16:10]:
We are talking about trade offs. Right? It's Yeah. Hey. This is really good up to this point and then not so great. Or in, in the other case, it's, you know, now you're over this threshold, so now your optimal case is to use the tool. Right? So

Anselm Eickhoff [00:16:27]:
So so let me draw the picture a bit further then. So what if you start having datasets that don't fit on a single client's device anymore? And that's also where we start seeing differences between Jazz tools and some of the other local first solutions because they are very much what I would call, like, sync the world. Like, you actually have to keep the entire state in the client. Whereas Jazz from the beginning was built to support granular sync, where what it does by default, it it it just syncs whatever objects you're trying to display right now. And then over time, you kind of accumulate everything that's, like, important to that user. And you can, like, evict things again if you don't need them anymore. But that means that you can now have, like, a local first experience for the data that you're actually interested in, but you can still work with potentially infinite datasets. And then, you can build you can build indices against tens of millions of objects, for example, on a server worker, and then the index itself again becomes a syncable object.

Anselm Eickhoff [00:17:26]:
So the client can create the index locally, see which objects it might need to load, and and all of that is it's it's, like, not one extreme or the other. If you make local first granularly syncable, you can actually create, request and networking patterns on the devo that are very similar to traditional stacks with APIs. But, again, you as a developer don't have to think about that. You just think about which objects do you want to have and and kind of request them as needed, and it loads whatever you need.

AJ O'Neil [00:18:00]:
So personally, I just like to work with JSON and functions. Yeah. Like, I Yeah. I don't ever use I literally have never used JavaScript classes except for experimentally to learn about them. I have never Yeah. Shipped code with a JavaScript class. Because I just find that, and I mean, to some degree, it's the concept of functional programming. Like, the less state you have to deal with, the better off you are.

AJ O'Neil [00:18:31]:
The easier it is to test. If I can just take, here's a plain object, here's a plain function. I put the objects and some options into the function. I get the same result out every time. You know, it's very grog brain dev type stuff. And I I like the, REST ish APIs. I like REST ish APIs because they're very, very simple to reason about. Like, if I open up my network console, I can see what's happening.

AJ O'Neil [00:19:03]:
I know what's going on. I like SQL databases because they're very simple and and proven. And I personally am am pretty resistant to things that require a lot of state management or require a lot of, bespoke code structure. So is this something I mean, it sounds like it sounds like the the from what I'm hearing, this is very opinionated. It's like you buy into this way of doing it, and you're going to adopt it, which I think is great. It's probably not something that I personally latch onto, but I do really, really believe that, you know, if you're gonna if you're gonna make something really great, yeah, integrate it and just tell people they have to buy it. But I'm I'm not sure if I'm representing that correctly. Is this like a very streamlined top to bottom solution? Or is this something where I can kinda take the approach of just plain objects and plain functions and and build an application where I'm essentially replacing my calls with jazzish calls.

Anselm Eickhoff [00:20:16]:
Right. So you you're mentioning a bunch of important things there. And, let me maybe start from, what Jazz consists of. It's kind of 2 layers. It's Jazz, which is like the opinionated framework, and then below that, a protocol, which, is called CoJson. I haven't written much about that yet. It's because it's so far it's just like internals of the framework, but it will be an open standard which defines, how what I'm calling co values work, which these are your new primitives. And they are very much like, they're supposed to be just like collaborative JSON.

Anselm Eickhoff [00:20:51]:
You have objects. You have lists and, a bunch of other things for, like, text and rich text. But it's basically what if code what if, yeah, what if JSON was just collaborative, and that's your abstraction? It like, if you read it, it looks just like plain JSON. If you write to it, you kind of have the the choice between 2 different APIs, and that's where we get into the higher level opinionated thing. What Jazz implements something very similar to and, like, React people with no libraries like MobX, where, like, you know, in React even with, like, just used, with used state, you get, like, the current readable version of the state and an updater function. And that's basically what using Jazz is like. Currently, it even exposes a mutable API where you can literally just do, like, object dot property equals something, and it will update it under the hood. But we'll probably move to something more Reactish ish way.

Anselm Eickhoff [00:21:47]:
It's like you get you you subscribe to a collaborative value. You get a readable version of that every time something happens to it. And if you want to mutate it, use this update your function in which you can mutate it. That's what replaces either your rest calls or what replaces your local state updates. That all just becomes 1. And the the nice thing is you just subscribe to updates whether they come from locally because you edited the object or whether they come from other users who are, like, remotely changing that same object. And in your subscription, you can update your UI, obviously, again, with something like React that ties directly into the render loop. Like, it just prerenders your component.

Anselm Eickhoff [00:22:28]:
But there's also Jazz Browser. If you want to use it in plain JavaScript, you just have a subscribe callback in there. You can do to the DOM whatever you want based on the newest duration of that value. That's as as simple as it is. What Jazz as a framework introduces, to kind of structure your applications more, almost in, like, a real sense is that it has this notion of schemas, which are similar to database schemas, where you say, like, look. These are the kinds of objects that I have in my app. They have these properties with these types. Jazz has chosen to represent these schemas using classes because it it's way easier in TypeScript to have classes because you can refer to them as a type and as a value.

Anselm Eickhoff [00:23:13]:
So we can kind of use this schema information both at typing time, so we can give you nice type inference for your apps objects as well as at runtime to do validation and stuff like that. We've noticed that even just seeing the class syntax throws a lot of people off. So in the next version of the API, we'll probably move to something that makes it look even more like the plain data that it is really. But, yeah, under the hood is it is really, like, collaborative JSON like objects that just have this editing and merging implemented. And and my hope is with the protocol becoming open that, not only might there be other frameworks on top of it that might might different API design choices, but are still, like, wire compatible. But it it can also be would also be really easy to port it to other programming languages and environments. Because one very interesting thing you can do is you cannot just write client applications with Jazz, you can write server workers at Weltes. Also, just listen to these co values, can do some external side effects to talk to 3rd party APIs, or they could receive a web hook request and in response, mutate a co value, which then some clients see.

Anselm Eickhoff [00:24:27]:
And right now, you can kind of only write them in Node. Js because right now, Jazz is only implemented in in TypeScript. But if the protocol is open, there could then be, like, cojason for Go or for Rust or for, like, whatever language you want, then you could write these complex systems that all use this really nice model of collaborative values, and no one has to think about transport or persistence.

Charles Max Wood [00:24:51]:
Yeah. I would say go

Anselm Eickhoff [00:24:53]:
go ahead.

AJ O'Neil [00:24:54]:
I've been wondering about the back end part of this. Do I run a Jazz server, or can I can I use my SQL database and and there's a Jazz adapter for the CRDT stuff to to get things in line? Or what what does that look like? What's the what does my server side look like?

Anselm Eickhoff [00:25:15]:
Yeah. So, yeah, it's important to be precise, and this is not going to be very JaaS specific because not a lot of the other local first solutions have a back end story. Obviously, everyone needs to have some kind of back end to to sync the core values and to persist them in the cloud. And in Jazz, this is what I call the sync and storage server. That is a process that you can run yourself. Right now, it's implemented in Node. Js. It's open source.

Anselm Eickhoff [00:25:45]:
It persists the history of the core values into SQLite. In the future, it will persist it directly onto the disk, but that's not really a format that you can interact with it. Like, it it's just, like, primitive internal data, basically. So that's one thing. And and, like, Jazz tools, my company, Garden Computing, is running the sync and storage server as a service, like, as infrastructure that that you can, subscribe to, has a free tier and so on. What's nice about that is if you use that, you can just start building an app and basically only write front end code, and it syncs and persists through that, and you have a whole functioning app with multiplayer and everything. But, again, you're not locked in. It's open source and so on.

Anselm Eickhoff [00:26:27]:
Separately from that yeah?

AJ O'Neil [00:26:29]:
Oh, no. Go ahead. You finish.

Anselm Eickhoff [00:26:31]:
Yeah. So that's just for, like, syncing the core values to everyone who needs them and making sure that they're persisted in the cloud. Right? What you might want to do is to have what I call a back end worker in Jazz, which is actually also a client to the sync and storage infrastructure that just happens to run on a server. So that could be a little Node JS script, for example. And what that lets you do is, like I said earlier, you can do server side things in reaction to core values changing, or you can create core values in reaction to getting something like HTTP requests. And that's kind of one way in which you can connect JASS state to the external world. One thing you might wanna do in a server worker, for example, is to take, JASS state in its, like, high level structured form and replicate it, the current state, into, like, a traditional SQL database either because you want to connect it to an old part of your app that uses test and you want the Jazz state to to, like, be integrated with that, or you might want to run some queries that, like, that particular database is very good at. For example, one app, someone is building with Jazz right now.

Anselm Eickhoff [00:27:44]:
They use Jazz for, like, 99% of it, but then they want to do some really deep analytics on all the user interactions that ever happen. And that's just not something that Jazz is very good or fast at yet. So what they do is they have this, like, background process that syncs Jazz state into DuckDV, which is really good at these kinds of queries. So that's stuff that you can do that. That's kind of your adapter to the external world there.

Charles Max Wood [00:28:09]:
That's that's really interesting. Yeah. I'm just I I was gonna ask about the back end too, so that's interesting. And I like the idea of, possibly having some driver for other systems. Right? I mean, you know, people on the show know that a lot of the back end they do is Ruby on Rails, and so it's interesting just to kinda have that, you know, I you know, eventually being able to feed it into my Rails app or whatever else. Exactly. Just be able to process it there. One of the things that I'm getting more into these days is running things over a WebSocket.

Charles Max Wood [00:28:43]:
And so instead of having the the worker kinda send these updates over a REST API or whatever, also being able to, you know, kinda stream them over the socket and get responses over the socket. And and I'm assuming that that's either something you've got or something you're working on.

Anselm Eickhoff [00:29:00]:
So so that part is, like, for example, let's let's take the example of a rails app. Like, this is something that I want to have really good libraries and patterns for, which we don't have yet, but it is something that you could build by hand right now, and it wouldn't be that part. And, obviously, we would help you. So for your rails app, probably what would be the best example is okay. You're pretty happy with your app. It works great. But you want to add something that's, like, really, really real time where you're like, oh, do I need a WebSocket? Now how does that integrate with Rails? What you could do is basically just build this feature with Jazz, and that will work perfectly internally for the feature, but there might be some parts of the state that the rest of your existing app is interested in. Right? Mhmm.

Charles Max Wood [00:29:43]:
So

Anselm Eickhoff [00:29:43]:
what you can do then is since we don't have code JSON for Ruby yet, you could run a little Node. Js server that subscribes to the JaaS state and at least puts, like, the current version of the state into your SQL database where then, Rails can pick it up and render it in your existing app, and that that should work quite well.

Charles Max Wood [00:30:04]:
So one other thing that I'm looking at here is it sounds like there are advantages that that are sort of obvious, I guess, with this kind of a setup. Right? I mean, if if I'm just mostly managing stuff like it's a local setup, then I essentially eliminate all of the network, stuff. Right? So if if I'm on a slow network or if my connection dies or if even if I'm not on a slow network and I just don't want to wait to get a response from the server, and I don't need 1 per se. Right? Because it's just syncing stuff back and forth. You know, it seems like it it kinda gives me some resiliency and speed and performance on top of everything else that I might be doing.

Anselm Eickhoff [00:30:55]:
That's a that's a great point.

Charles Max Wood [00:30:56]:
Kinda like about that.

Anselm Eickhoff [00:30:58]:
That's like the the funny thing is, like, everyone in the local first sphere kind of came to it from that, like, user experience promises it obviously has. But then starting to build apps with it, you realize that that the big thing about it is really the different developer experience. Because, sure, it's great that the app is snappier, works offline, and so on, or over sketchy connections, which is often even trickier than offline. Right. But the main thing is that by not having to worry about requests or back end or, like, making sure the back end now supports, an endpoint that gives you the data that you need to render this thing, you're just, like, in one context, you build your front end and the data model right next to each other, and you can iterate really, really quickly. And you just think about what objects do I need to create or delete over. I mean, if you're coming from, like, a a Ruby on Rails background, that's actually what I started cutting my teeth at as a developer. You kind of have that experience there, but on the back end, and the back end also does the rendering.

Anselm Eickhoff [00:32:04]:
So local first lets you have that on the client. You meaningfully can create, modify objects. And often what that looks like is, like, it looks almost illegal, like, in a in a in a button on click handler, you create, like, whole team and, like, documents and then whatever you might have in your app. That's that's the developer experience it gives you, and it's hard to understate before you've tried it yourself just how quickly that lets you build apps. However, one component that enables that really that we haven't really talked about yet, that I can go into more detail if you, if you want is, it's really it's a really tricky question. How do you do user identity and permissions in a local first way?

Charles Max Wood [00:32:48]:
Mhmm.

Anselm Eickhoff [00:32:51]:
Because that's not really answered by, like, just the simple way of flight it out so far. Let me know if you want to go into that or if you had some other

Charles Max Wood [00:32:58]:
questions. That is interesting because, you know, as as you're saying, right, if you have that kind of centralized back end system, right, then it can kinda know who's sending it stuff. Right. But on the front end, yeah, that's that's a little bit different. And then, I'd also like to talk a little bit about, you know, maybe doing peer to peer where you don't even need that centralized server beyond, hey. Who else is working with these documents? And so if you're doing that, then it gets even more tricky because Yeah. Then it's, who do I trust it coming from from across the Internet, right, without even having it, you know, a clear identity attached from that centralized server? So, yeah, how how do you think about those issues?

Anselm Eickhoff [00:33:46]:
So Jazz implements something. And, again, that's also part of the underlying protocol code JSON, which I call local first permissions. And this is maybe beyond all the other details of how exactly it's implemented. The biggest difference between Jazz and other local first things because the approach that many others take is either look, the the author and permissions question is out of scope. We just give you the shared state. You figure it out yourself. Or in many of the other cases where they also have hosted services, they kind of they do the local first state, but then identity and office still traditional in a centralized way, which works okay for a lot of things, but it kind of makes you trade off some of the local first properties you could otherwise have. And it's tricky to do, like, well, how do you do offline then? Because then you're not really authenticated against the back end that at least checks the permissions and so on.

Anselm Eickhoff [00:34:38]:
So that's tricky. So for that reason, what I decided to do when I built Jazz is, like, I I saw the CRDTs that give you the shared set. I was like, damn. This is amazing. I want to build everything like that, but it feels like only part of the puzzle. You also need to solve user identity and permissions in a similar way. So what I've done there is to to couple CRDTs with basically good old public key cryptography where a user in jazz is just a cryptographic key pair, and we'll talk in a second about where that comes from. And when you make changes to an object, you actually sign those changes with your public key, which means that everyone else who gets your changes, no matter how they got hold of them, whether it was through a centralized infrastructure or peer to peer or whatever, they see the signature and they know, okay.

Anselm Eickhoff [00:35:29]:
This was definitely Charles who made that edit. That's kind of the the right access part. And for the read access, what you do is you you encrypt your changes, and then you only give the key to people who you want to see that object. Right? That means that you can now actually in a local first way. So on the client, synchronously, when you create objects and when you write to them by signing and encrypting them, you know for sure that the permissions have been set up correctly, and you don't need to trust the syncing back end to do that for you. That just needs to exchange the the the edits or you might send them peer to peer. And and all the edits that you receive, you can verify who did them. It gets a bit more complicated then because you might want to have complex permission structures like teams of certain people with different roles.

Anselm Eickhoff [00:36:18]:
So what, what Jazz implements there is something called groups, which is basically a scope for permissions where you can say, like, look. This person with this key pair is the admin. They added someone who is a writer and someone who is a reader. And and Jazz, under the hood, make sure that when you receive edits, for example, not only is a check that they have a valid signature, but that they have a valid signature by someone who has the correct role in that team. The teams themselves are also like CRDT co values, so they get synced together with everything else. And you can even nest groups, so, like, they can inherit from each other. And with that abstraction, you can build basically arbitrarily complex setups. Like, in Notion, for example, you might have a team and you want everyone on the team to be able to read and edit every page by default, but then you might want to ad hoc invite someone just to that page to also write it who's not otherwise in your team.

Anselm Eickhoff [00:37:14]:
And by using that structure of in inheriting groups, you can build all of that in a completely local first way without having to trust any back end, and and you can even verify every single edit yourself locally. That's very unique, and and, like, one of the hardest parts of that was to make that fast enough to be able to compete with a traditional trusted back end.

Charles Max Wood [00:37:37]:
Yeah. I'm trying to I I don't wanna, like, get into the weeds of how it's all implemented. Sure. You know, the the idea of crypto cryptographic, you know, asynchronous public private key pairs. I mean, people use them all the time. They just don't know it a lot of the times, you know, whether it's your HTTPS connection back to the server that's using the same ideas, the same technology, essentially, when you It's all in

AJ O'Neil [00:38:05]:
Yeah. It's all in web crypto and everything. I mean, like, it's

Anselm Eickhoff [00:38:08]:
it's not the spec

Charles Max Wood [00:38:09]:
that people use. So yeah. I mean and I I like the idea in the sense that

Anselm Eickhoff [00:38:17]:
Yeah. Uh-huh. Yeah. So it's completely abstracted away from you. That's the nice thing. I'm just telling you this as in, like, this is how it works. This is how you can make the permissions local first. But to you as a developer, you you basically you define your groups, and it feels like you said, like, Dropbox like permissions, and you're saying, oh, this account now has this role.

Anselm Eickhoff [00:38:36]:
The other quick thing that I didn't mention is, like yeah.

Charles Max Wood [00:38:40]:
So I guess the other question is, I mean, is there permissions around time? Right? So I add somebody temporarily to a group and then I pull them back out. All the changes during that time period are legal. Right? Yeah. Apply those. But now I've pulled them back out of the group. So if they send another update, I don't want it added, And so it handles all that too over time.

Anselm Eickhoff [00:39:03]:
It it and it handles all that because the groups themselves are CRDT, so they are full histories of whatever happened to them. So everyone can be like, oh, they were a member until then, and then they got kicked out. And for the read access, what happens is you just you rotate the key and give the new key to everyone except the person who got kicked out. Right. But again, like, this is getting into details. You as a developer don't really need to care. You just use Dropbox like at this account as a writer, at this account as a reader. It's really easy to build your UI around that to have, like, your little team thing.

Anselm Eickhoff [00:39:33]:
Right. And in terms of because I I kind of glanced over that where the key pairs come from because, obviously, you don't want the users to be handling key pairs. Like, no one uses crypto wallets for that reason. So Jazz kind of lets you have pluggable, what it calls, auth providers where, it has a couple native ones that are really nice. My favorite one is passkey auth where we're using the passkey feature to actually store the key pair. So the user experience to the user is like it just prompts you for, like, touch ID or face ID Right. But then actually stores the key on your device and only you have that, but it still gets if you're using Apple devices, it gets synced between them. If you're using Chrome and Android, it gets synced between them.

Anselm Eickhoff [00:40:14]:
So you actually have, like, an end to end encrypted app at that point. But you can also do something more traditional where, like, if you wanna use something like Clerk or Auth0, we have an adapter for that where the key pair gets stored in the user's private metadata. So after they log in, Clerk, for example, gives that to the front, and then the front can then give that to Jazz as the key pair. That means that basically Clerk and any admins you might have in Clerk are trusted with the key pairs for all the users, but that's kind of the case for any traditional web app already anyway. So you kind of you have the choice, like, how how deep you wanna go there. The nice thing is that even in this setup, neither the app developer nor the users have to trust me running the sync and storage infrastructure. Like, I still never see your data in plain text. I don't have your keys, but I can still do the syncing for you.

Anselm Eickhoff [00:41:05]:
Cool.

AJ O'Neil [00:41:06]:
Yeah. That's that's one issue that, losing private keys means losing data permanently because there is no email recovery for that. Now if you're storing it in Clerk, then you have a reasonably high assurance that that is going to

Anselm Eickhoff [00:41:25]:
be there

AJ O'Neil [00:41:26]:
tomorrow. But that's that's something that's a little bit

Anselm Eickhoff [00:41:31]:
You have

Charles Max Wood [00:41:32]:
to trust Clerk.

AJ O'Neil [00:41:34]:
Yeah. But I think I think I mean, obviously, if you're trusting Clerk for your users, you're already trusting Clerk for

Anselm Eickhoff [00:41:39]:
your users.

AJ O'Neil [00:41:40]:
So I I wouldn't I wouldn't lay anything additional there. But I I would I would seriously warn anyone from trusting passkeys as a primary source because I've done quite a bit of experimentation with it. As I imagine, you're well aware of the the drawbacks of it and the way that browsers implement it differently, the differences between, the Icloud ID versus the browser ID. And you could very, very easily, overwrite your private key, for example, for Icloud, and and not not knowingly. And and and perhaps you're taking I I know that there's certain measures that you can take that will prevent the private key from being overwritten and produce an error instead, but that's one I'm not I'm not yet comfortable with that. I don't feel like that one's mature for that use case. I think it's excellent as it's a built in password manager. Passkeys as a password manager built in, I'm a 100% on board.

AJ O'Neil [00:42:42]:
It's mature. It's good. It's ready. Use it. Go. But as something for storing, you know, you you've got, what, 64 bytes of of, arbitrary data you can store, and

Anselm Eickhoff [00:42:53]:
Yeah.

AJ O'Neil [00:42:53]:
It's easy to overwrite that.

Anselm Eickhoff [00:42:56]:
Yeah. I mean, to be honest, I've I've not encountered a situation where that happened, but it's it's good to know about that. And for that reason, it, like I think the bigger issue is actually still that a lot of people just aren't familiar with them. And and for that reason alone, it's it's like a no go for a lot of apps. I think there is a bit of an overlap here where, like, if someone really wants to build an end to end encrypted app, probably, they could that's the kind of app where the users would know how to use passkeys. But right now, yeah, that's that's just something that we offer. Most people want, like, a more traditional method anyways.

AJ O'Neil [00:43:32]:
Well, I I I think it's great, and I I love the way that it's being implemented and rolled out across the industry right now. It's very seamless. Yeah. I mean, typically, the way that it's happening is you just do your normal sign in, and then it pops up and says, you know, use Windows Hello

Anselm Eickhoff [00:43:45]:
or use

AJ O'Neil [00:43:46]:
face ID. And so a lot of people are using passkeys without even knowing that they're using passkeys because they've already been seeing it on their phone, they've already been seeing it on the Windows computer, and then it just pops up in their browser like, oh, okay. It's the same thing I've been doing for the last 5 years on my phone.

Anselm Eickhoff [00:44:01]:
Mhmm. Totally. Maybe not 5 years. Yeah. Exactly. But it people are getting familiar with it. What's nice about Jazz is, like I mentioned, that the auth providers are pluggable, and Jazz and, therefore, your app really only cares about the the account and the key pair. So you can totally start building your app against, like, with one auth provider, later on, switch them, and change absolutely nothing inside your app.

Anselm Eickhoff [00:44:25]:
You can also, like, offer your app to, like, enterprises who have weird custom SSO needs or whatever, and nothing about your apps logic around how accounts work, how teams and permissions work has to change, which is something really nice because, usually, this is a huge topic and you're, like, permission model in your back end is very tightly coupled to kind of the auth provider that you choose to use.

AJ O'Neil [00:44:49]:
Yeah. So do you have a back office for this to manage things, like a a UI by which a person who's administrating an application can get access to what permissions exist and what groups exist and such?

Anselm Eickhoff [00:45:06]:
Kind of, but we want to do a lot better there. So there is something called the Jazz inspector, which is, if you have to keep a foreign account, you can kind of remotely look into all of the state that's in that account. Again, because of how permissions work, as opposed to a traditional database where admins can just see all the data ever, by default in Jazz, the user kind of has to opt into letting you look into their account. But if they do that, and you might even hard code into your app that that happens by default, the typical pattern in apps that want a more traditional permission model is that they just create an admin account that admins have, that the server worker has, and every user automatically invites that to all of their groups. And then you get, like, this access pattern that's very similar where you can just see all your users' data. But we yeah. We so that's kind of the mechanics of it. What we're working on right now is kind of making that a more full fledged browser.

Anselm Eickhoff [00:46:01]:
For example, if you use Jazz Cloud as a service and you create an app in there and people start creating objects on their clients that, like, if they opt in or if you enable the default opt in, you can very nicely browse that as if you were looking at, like, a database UI, basically.

AJ O'Neil [00:46:18]:
So that's that's actually really interesting. I mean, I I think that the reason most people develop apps is because they want to aggregate user data so that they can manipulate it or sell it in some way. So the idea that by default, the user data is private, I mean, that seems like that appeals to a very niche set of applications. You know, like Telegram, some maybe some cryptocurrency wallets. But, I mean, don't don't most people that build apps, don't they want you know, like, even Slack, right, in Discord. Like, they get to see all the messages. You know? Like, with Discord, all the messages are visible by the Discord admins. They get to train AI on them that, you know, and say it like with Slack.

AJ O'Neil [00:47:04]:
Anybody on the Slack team can look at any of the messages. Anybody who is an admin of your Slack group can look at all the messages, and that's, I mean, that's generally considered a feature, not a bug. Although, I personally like what you're saying. I personally am on board with, yeah, encrypt my data. But

Anselm Eickhoff [00:47:23]:
but Yeah.

AJ O'Neil [00:47:23]:
You know, like, is is this what you think the market wants?

Anselm Eickhoff [00:47:27]:
So, like, pessimistically, I I agree with your statement that you just made. And this is why, like, again, to be precise, it's like it's the default on a protocol level that everything is encrypted. And what that means is that you can't just as easily build the the same trusted model where the app provider can see all the data you put in there. The only difference is that this trust relationship is now, explicit and verifiable, if that makes sense. And in this case, even, like, you would be like, sure. Like, Slack if if Slack tomorrow decided to use Jazz for whatever reason, you'd be like, sure, Slack admins can see all the data in my team. But, like, Garden Computing, who's running the Jazz service account, that's already an improvement. Right? And it still gives you, as the app developer, all the freedoms and flexibility that you had before.

Anselm Eickhoff [00:48:17]:
Interestingly, if you're if you care about analytics type data, you get much more high fidelity analytics out of Jazz by default because everything every object has the full history. So without instrumenting your app in any way or or registering any custom events just in the in the dashboard is the way we'll expose it to you. So you can see, like, oh, these 5 users from, like, these cities are working together on this object right now, or, like, this has been really hot over the last week. And, these teams are collaborating like that in a, like, way that's that's schema aware of of what the objects in your app are, and you get that for free just by, like, writing to the objects, basically. So in that sense, it's it's almost gives you more data that you can exploit as an app developer. It's, again, just that the trust relationship is not explicit.

AJ O'Neil [00:49:09]:
So one thing you mentioned there, the schemas, how do you handle the migrations?

Anselm Eickhoff [00:49:15]:
This is literally the hardest question of local first, and anyone who's building a local first framework or something like that will will tell you that. And the that's like local first in general is like it makes a lot of things that used to be really hard really simple, and it makes some things that used to be really simple a bit awkward. And migrations is maybe the most awkward thing because you're now basically confronted with distributed migrations. Like, different clients might update you out at different times, but still interact with each other at the same time. It's a tricky problem, and what we found so far is that the best thing to do is to just change your mindset a little bit where you you can't treat migrations anymore as just, like, stop the world. We'll change everything to this new thing and then continue the database. You have to treat it more as, like, protocol evolution where you can only ever add new fields, basically. And if you've built, GraphQL APIs, that should be familiar to you.

Anselm Eickhoff [00:50:16]:
If you've done anything with protobufs, that's kind of best practices there, where in these cases, you also expect clients, with the old schema interacting with you. So if you follow that same model, you'll be fine. And because it's

AJ O'Neil [00:50:32]:
such a new Is there a way to expire data that's too old? Like, if the data is more than 3 months old, just expire it?

Anselm Eickhoff [00:50:41]:
That's that's a separate topic, which is deletion, which is also interesting because it local first, and I think Jazz in particular kind of takes a, like, soft delete stance by default because you keep all the history anyways. Most of the time, you just want to soft delete. Now there are cases where for regulatory reasons or because it's really a lot of data, you want to delete things permanently, and you are able to do that. You basically you mark the object as deleted, and every client of the syncing back end will actually delete it.

AJ O'Neil [00:51:12]:
That's not that's not what I meant.

Anselm Eickhoff [00:51:14]:
Okay.

AJ O'Neil [00:51:15]:
Although I'm glad you answered that question too. What I mean is, like, all of us that are developing web apps, we all come into this case where we change some property that's you know, I think one of the one of the probably more common ones is if you change anything that's in a cookie, because cookies last forever. Right? Or you change you change some object that can exist out in the wild that's maybe not part of the schema. It's just an ad hoc object. And then you get this problem where this user calls in, and they can't log in, or at least they don't have the experience of logging. Maybe the authentication process succeeds, but their app is just, like, stuck in this error state. And then Yeah. The only way to solve it is that you have to clear out the cache because there's some little property where it's triggering an education in your app where it's like, if this, then do that.

AJ O'Neil [00:52:06]:
And so it passes the first check, and then it's, you know, if that, then do this, and then it fails. And it's in this limbo state that you didn't expect because some user that logged in 3 months ago that still has some local object and local storage related to how the auth object used to look like or how their profile object used to look like, gets the new version of the application code, and it can't, like, it can't regulate itself. Right? Like, you you know what I'm talking about?

Anselm Eickhoff [00:52:31]:
I I think so, but I think if you follow that principle strictly of only adding stuff, that shouldn't happen. Now you might make mistakes, obviously. You might make mistakes and the so your your question is mostly, like, what if a migration is broken? Right? And Yeah.

AJ O'Neil [00:52:49]:
Like, is there a well, it more it's it's like I I wanna fail safe. Right? So so one of the things you know? Yes. It would be great if if we were more perfect coders, and and I want that, and I want people to be more deliberate in their decisions and to be more mindful of, you know, what state they're storing in local storage or IndexedDB or their database or whatever it is. The reality of the situation is most people are not that mindful, and everyone makes mistakes.

Anselm Eickhoff [00:53:18]:
Of course.

AJ O'Neil [00:53:18]:
And so when when, like, one fail safe to have that like, I was just working with a buddy on a project. I said, okay. If you get a 401, clear out all the data and log the user out. If you get a 500, clear out all the data and log the user out. Because we're trying to build this in a way that we actually don't have errors. But if we do encounter an error, we just wanna say, okay. Wipe out all of the local states so that we don't end up in a loop where the person's trying to log in, but because they had a you know? That's the kind of thing I'm saying is providing a fail safe to say, hey. If the version has triggered from 3 to 27, that's more than 3 version changes, so just wipe out all the local state.

Anselm Eickhoff [00:54:03]:
So that's actually, like, a move that you would be able to do in a migration where, like, the and and, again, to be precise here, the migrations are a framework feature, not a protocol feature. Right? The the the protocol just gives you persisted arbitrary JSON, basically, that you can collaborate on. The migrations is just one part where you can modify like, one place where you can modify these objects. So and right now, we take this wild west approach where we're like, you can literally do whatever in a migration. You can mutate the objects any way you want, and it's up to you to follow these best principles. But that also means that if if you botch something or there's some weird unexpected edge case that you didn't think about, you can after the fact just be like, look. If the state that we're getting at the beginning of the migration doesn't look like any of these standard steps that we take in the happy path, just, you know, just throw that data away, like, whatever. That's something that you can do in a jazz migration.

Charles Max Wood [00:55:08]:
Mhmm. Yeah. I was thinking something more along the lines of, you know, let's say that, I was putting some data into these data objects that I found out, oh, under this regulation for the field I'm in, right, I'm not supposed to store the credit card number. Right?

Anselm Eickhoff [00:55:29]:
I think

Charles Max Wood [00:55:29]:
I think we all generally know this, but Yeah. You know? Or, you know, I I have some, you know, under HIPAA or some of the other GDPR or whatever. Right? This this is the kind of personally identifiable information that I've got to be, like, extra and especially careful with. And so having it on a local storage, you know, maybe maybe that, you know, for whatever reason, I have to have in some kind of controlled back end. And so I'm just gonna have to, you know, do end runs to the server for that kind of a thing. But everything else, I can run local first. Right? And so, yeah, I'm thinking in that case, I may I may have a migration that says, hey. Wipe out

Anselm Eickhoff [00:56:10]:
all of

Charles Max Wood [00:56:11]:
this. Right? And it'd be nice if I could do it on, like, a a you know, it's like this object is migrating to this new version, and so, therefore, just forget all of the credit card numbers rather than wipe out all of the

Anselm Eickhoff [00:56:22]:
Oh, yeah. Yeah. Sure.

Charles Max Wood [00:56:23]:
Or whatever object. Right? Something like that.

Anselm Eickhoff [00:56:28]:
Okay. This is going to be a bit confusing because I wanted to talk about something related, but yours is kind of, like, almost the worst case. And in your case, what you would do is exactly like you would do, like, a patch up migration that actually does hard deletes. Right? Yeah. And that's something that you you you'll be able to do as well. Most of the times, you would do a patch up migration that the soft deletes.

Charles Max Wood [00:56:52]:
Right.

Anselm Eickhoff [00:56:53]:
And what's nice about that, by the way, is that if if you mess up the patch migration as well, which trust me, I've done many times. And and like soft delete

Charles Max Wood [00:57:02]:
it. Yeah.

Anselm Eickhoff [00:57:03]:
You can unsoft delete it, and you can look at the whole history of botched patch migrations that happened to it and find something useful somewhere in there. Because that's what you do with the traditional database. Right? You try your best to write reasonable migrations. If they utterly fail, you roll back, or you write more migrations against it, and you do the same on a on a local level. But, yeah, I mean, so far, I I'm always honest, and I'm like, look, this is the trickiest part. This is the scariest part. So far, everyone who has built apps with Jazz has been able to to write these migrations correctly even though we provide no guardrails yet. We're kind of in a state where we, like, we give you all the tools and we wait for, like, what are the best practices around how to do migrations and then introduce guardrails on a framework level.

Anselm Eickhoff [00:57:49]:
But so far, it hasn't been an issue despite these people changing their apps around quite a lot as they iterate on them.

Charles Max Wood [00:57:55]:
Right. Yeah. I wanted to because we're we're already almost at an hour. We try and keep these to an hour, maybe a little more. We tend to go over Sure. An hour. But, anyway, one thing that I'm curious about then is AJ asked you, okay. You know, where is this not super well suited? What I'm curious about is, okay, So what kind of apps are people writing where, you know, if they haven't figured it out already, they're gonna be really well suited for this kind of a thing, where they're gonna look at it and go, oh, this solves a whole bunch of problems and makes my life easier as I develop this in the future.

Anselm Eickhoff [00:58:38]:
Right. So what's what's fun about our current adopters is that they're actually super diverse, and they're a good mix of, like, things that are obviously very good ideas local first to, like, this is almost not local first at all. I can maybe very quickly mention some examples. But what it's best for right now is if you really care about a good offline first experience. If you want to build any kind of app that has collaboration, particularly if it's real time, but also if it's not real time just like team abstractions, permissions, that sort of stuff, way easier to express. Yeah. I think these these are the ones where people, get the most value out of jazz right now. And, again, like, what is jazz not good at? Honestly, the biggest thing right now is just, like, we're early.

Anselm Eickhoff [00:59:24]:
Documentation is lacking horribly. We're working on it. We're trying to to patch that up by just providing good Discord support, basically. So that's the biggest thing. Like, if you really need basically. So that's the biggest thing. Like, if you really need it, you'll probably want to use it despite it having bad documentation. For everything else, you probably only wanna use it for an experiment to get familiar with it.

Anselm Eickhoff [00:59:43]:
That's kind of the the main bottleneck right now. So in terms of the adoptors, just to paint the picture, one of our earliest ones, they're building like an app for you for freelancers to collect invoices, out of your Cloudflare, your AWS students submit to tax authorities. But what the app does is it actually logs into your AWS and your Cloudflare with your username and password. So you kind of you need to be able to trust that app as much as you would trust the password manager. And and for them, obviously, the whole permission and encryption thing, was a godsend because they got all of that for free. And, they wanted to just make it a single player experience in the beginning just for individual freelancers. But because they build it with Jazz, they got, like, org features where you can invite someone from your team to also submit invoices by just adding a button, basically. So this was, like, a very obvious fit.

Anselm Eickhoff [01:00:34]:
Maybe the most unobvious fit was a a guy who's building a kind of social network with his team. It's called learn anything, like learn minus anything dotxyz, I think, is the domain.

AJ O'Neil [01:00:46]:
Mhmm.

Anselm Eickhoff [01:00:47]:
It's like a mix between Reddit and Quora, kind of like a learning social network where you can be like, oh, I wanna learn how to play the guitar or I wanna learn Rust, and it will have, like, a community curated list of, like, tutorials, blog posts, videos, and so on. So that's still, like, very much like a social network part. And they decided to base their entire app as Jazz. That's the only database. So in their case, Jazz actually, serves these initially static pages of content, and they already get, like, millions of visitors per week because they've good good SEO. So it's it's really stressing jazz in a way that's not local first at all. It just takes a traditional back end database role. But then as a user, like, probably in the beginning, you're just passive, but then you're like, oh, I wanna start learning this and then track your progress as you read different articles.

Anselm Eickhoff [01:01:37]:
You can take your own notes in there, and then it magically transforms into this local first experience, where you start having your own personal data that's local and really fast to interact with. But because they build it with Jazz, they didn't have to glue together different systems that are good at either of these. They could just use Jazz to represent all the data they have, whether it's, like, this global data across users or individual user data. Okay. These are kind of the the 2 best examples I can think of. If if people are really interested, you can check out some of my other podcasts where I list a couple more, but for the sake of time, I think that that gives us a good contrast. Cool.

Charles Max Wood [01:02:20]:
So if people wanna start building apps with Jazz themselves, I mean, what what's the best way to do it? Just npm install it and then spin up an app, or is there more to it?

Anselm Eickhoff [01:02:31]:
So what what I would recommend, Yac, basically. But, because there's so many new concepts, I would really encourage people, go check out the home page that kind of gives you a quick overview. Have a look at the documentation that exists, but most importantly, check out the example apps because this should cover a good ground of stuff that you can do with JaaS and just explain the best way possible, how to set it up, how to define your schema, how do you do stuff like image uploads, and and and lots of fun stuff like that. And then if you have any questions, hop on the Discord because right now we're in a phase, like I said, where we just we sit down together with people trying things with jazz, answer their questions, or even help them build their apps, because we learn a lot from that. And it it is kind of it works and it works right away. The nice thing is it is quite little setup if you decide to use JazzCloud because you just start a front end project essentially. And then for for whenever you get stuck or you have questions how to best build something, just just come and ask us on the Discord.

Charles Max Wood [01:03:31]:
Yeah. One other thing related to that is a lot of our listeners are already working in existing apps. Right?

Anselm Eickhoff [01:03:38]:
Yeah.

Charles Max Wood [01:03:39]:
It's not like it's,

Anselm Eickhoff [01:03:39]:
oh, I've

Charles Max Wood [01:03:40]:
got the perfect greenfield project for this. Right? It's I'm building this other thing. I'm already using React or Vue or Angular or, you know, just DOM APIs like AJ, you know, or web APIs. And so, if I'm looking at this and thinking, well, some of this sounds really nice for some of the features in my app and then some of the other features yeah, I'm gonna use the traditional back end because, you know, it it either already works or it seems like this is a clear win for just some of these other things I want to add. Mhmm. My question is, can you bring this in alongside the other stuff? Right? So let's say in an existing React app or Vue app and go, okay. These components are gonna use Jazz. These components are gonna use my existing back end, and some of these components are gonna do both, and maybe I have that server process running on the side.

Anselm Eickhoff [01:04:34]:
Yes. Yes. You can in principle. In in terms of front end bindings, React is kind of first class. We just launched Vue and very fresh and experimental Svelte as well. So that's not an issue, and you can use it from plain JavaScript as well, like I mentioned earlier. The the biggest challenge is in terms of, like, how does it interact with your potentially existing back end and state that you have. Easiest case is probably if the JaaS state and your existing state is completely separate, and you kind of only need to make it up just for the user identity so your existing auth works with Jazz.

Anselm Eickhoff [01:05:09]:
It gets more tricky when it does need to put stuff into existing databases, which is possible, but, again, no documentation for it. We would need to help you with it. So to be honest, like, right now, the people getting the most value out of jazz are greenfield apps, but it is possible to build more complex stuff. And over time, we will have more patterns and examples of that, for you to do that without any of our help.

Charles Max Wood [01:05:33]:
Right. I mean, just to give you an example of something that I'm thinking about. So top end devs, I'm building essentially, I'm trying to take it from podcast network to, you know, learning guided learning system. Right? And so one of the things that I want to add is a community section where people can actually, like, chat or interact, you know, something, but it's kinda like a forum or a chat room or something like that. And so I'm looking at jazz and thinking, hey. You know, this this might be really nice. I don't have to figure out how to, you know, web socket the thing through Action Cable on my Rails back end. Right? I can just, you know, I could just put jazz in on that piece.

Charles Max Wood [01:06:12]:
Right? And it just kinda exists outside of the, you know, the rest of the app because the rest of the app, when I search, I don't need it to search the chat log. I just need it to search, you know, the other learning resources that I'm providing people. And so I could conceivably do that. Right?

Anselm Eickhoff [01:06:31]:
Yeah. And that sounds like something that I'd love to help you build. And that's almost the ideal case of, like, a greenfield feature within an existing app that doesn't really interact too much with the app. So I think that that would be a very good case.

Charles Max Wood [01:06:44]:
Right. Okay. If people want to connect with you or learn more about you or Jazz, jazz.tools seems like a good place.

Anselm Eickhoff [01:06:55]:
Jazz.tools. Yeah.

Charles Max Wood [01:06:57]:
Social media or something or GitHub.

Anselm Eickhoff [01:06:59]:
Yeah. I'm I'm, Anselm. Io on Twitter and Blue Sky. And otherwise, if you wanna know more about our company, check out garden.co. Trying to be more active on Blue Sky with with everything. Seems like lots of developers are kind of congregating there, which I'm very happy about. And soon, we'll start putting out blog posts and and newsletters and so on. That's kind of where we're at.

Charles Max Wood [01:07:24]:
Yep. Yeah. It's it'll be interesting to see how that all goes, but, yeah, I am seeing some movement that way. So, yeah, makes sense. Alright. Well, we're gonna go ahead and, head into our picks section of the show. I'm gonna let AJ go first.

AJ O'Neil [01:07:42]:
Alright. Well, I did not think that my wife would like Dune, but I loved it so much that I said, hey, honey. Watch this show with me. You might not like it. She loved it. I couldn't believe it. Blew my mind. Of course, what she's talking about is not the story.

AJ O'Neil [01:07:59]:
It's just like, oh, the sex were so beautiful, and, oh, the the camera angles were so nice. I'm like, what about, like, the army and the like, I don't know I don't know if she got anything out of the out of the movie like the rest of us did, but but, yeah. So we're gonna we're gonna maybe watch, part 2 together. I'm I'm thinking she might get the 2 film collection for me for for Christmas. So I'm I'm waiting to to find out that, before we do. But yeah. So the all the dudes out there that, you know, you thought, yeah. I would never be able to get my wife to watch this with me.

AJ O'Neil [01:08:41]:
My wife is one of those wives. Okay? She wants me to watch Pride and Prejudice with her. And, she I played Portal, and she couldn't bother to watch that. And star wars is right out. So I was super, super surprised, but she enthusiastically loved Dune. So I will I will pick Dune, and maybe I'll throw up a a link here to the the 2 disc set. And so last week, we I think it was last week that we talked a bit about Blue Sky. I was able to get it installed and running.

AJ O'Neil [01:09:17]:
I left an issue open. So anybody who wants to know

Charles Max Wood [01:09:20]:
Oh, you're running a local Blue Sky.

AJ O'Neil [01:09:22]:
Yeah. I I I did, Yeah. I figured that out. They they use Docker, but the use of Docker just makes it more complicated and more difficult to install because you can just create you know, you could just git clone the repo and then node install and then set up your reverse proxy with Caddy. And so I just gave those instructions, along with some additional detail for some optional stuff. So when you see the instructions, you know, you don't have to do all of the things. It's just there's a couple of steps. It's like you set up the environment variables.

AJ O'Neil [01:09:58]:
That's like one half of the instructions is, you know, copy and paste this big, huge, long list of environment variables, and then, you know, optionally set up Caddy for SSL if you're not already using something else to reverse proxy for you. And then you need to have a it's a well known file. You need to have reverse proxy in particular apart from the /xrpc or whatever it is. I didn't my experience with it was kind of meh because it's like, this is literally a Twitter clone. And, of course, of course, my first 10 seconds of blue sky were the same as anybody's first 10 seconds of Twitter. I immediately was followed by bots with, you know, pictures of women from the chin down, claiming to want to be my friend. So I I just I don't know. I guess, join it if you want to.

AJ O'Neil [01:11:04]:
I I kinda I I don't see the allure of it because it's it's literally just a clone of Twitter with I mean, you can you can write a local server, and you can set up your data server, and that's cool. And you can set it up so that your data server is your domain name. So, for example, if you're, beyond code bootcamp.com, then your handle can literally be at beyondcodebootcamp.com. Mine is not. I didn't I I I played around with a little bit, but I just I was a little I I just wasn't that I wasn't that into it because it's it's just it's literally Twitter with the logo changed. And maybe a few features less and, you know, you got the local data store as a feature more. But, I mean, I guess, cool. Good.

AJ O'Neil [01:11:53]:
You know? Go Mhmm. Good then. But it yeah. If you wanna if you wanna install it, there's an issue up that's called it's called something like how to install with Node, no Docker. And and it's very, very simple. So if you wanna do it, I'd recommend it. If you're gonna join Blue Sky, I think that you have a moral obligation to run a personal data server. Because, otherwise, what are you joining it for? You're, like, throwing out the baby and keeping the bathwater.

Charles Max Wood [01:12:19]:
Yeah. Well, there there are all of the stupid, silly politics of people blah blah blah, Elon Musk, something something, blue sky. So, that's why I'm seeing people move. I I think it's all people

AJ O'Neil [01:12:33]:
I mean, yeah, if you're really interested in following information about Elon Musk, then blue sky is a great place to get yeah. Because, I mean, like, I think 80% of the posts are that. So if you really love Elon Musk, you just gotta know every detail about his life. Yeah. I'm sorry. I'm sorry. I'm I'm being a bit of a jerk, but I

Charles Max Wood [01:12:53]:
I'm like, he's trolling people. Okay?

AJ O'Neil [01:12:56]:
But yeah.

Charles Max Wood [01:12:57]:
But if that's where people are, I'll go there, and I'll talk to people. And if they're somewhere else, then I'll go there and talk to people.

AJ O'Neil [01:13:04]:
I I was just I was expecting something more. I was I was I was genuinely excited to try it out. I was expecting something more, and it's pixel for pixel. It's Twitter with a butterfly logo and an option to run a personal data server.

Charles Max Wood [01:13:24]:
Well, it's

AJ O'Neil [01:13:25]:
And a lot a lot a lot. Like, I will say I think the politics are heavier on Blue Sky, probably because I haven't followed anybody yet. But, like

Anselm Eickhoff [01:13:36]:
I think that's the big thing. Like, it I I tried it a while ago and gave up on it, and then with the wave of people coming and the the the starter packs, like, kind of re green knitting communities, especially among, like, dev tools. It's actually now at a point where I miss some of the most interesting people from Twitter, but it is quite high, like, value to noise, like, no ads, but that only was the case after I followed a bunch of people. So I think that's always the the caveat with social networks. Yeah. Well, but you you you have your personal

Charles Max Wood [01:14:10]:
mhmm. I I connected with a bunch of people there too, but, I got kinda dragged kicking and screaming into some of the dev community politics a few years back,

Anselm Eickhoff [01:14:20]:
and

Charles Max Wood [01:14:21]:
that that came right back to the surface the second I was in there. So I think it really just depends on what your experience is and who you wind up running into. But, I mean, I did have a couple of great conversations with some people on there too. So

AJ O'Neil [01:14:36]:
But the the whole thing about, like, there's no ads and, you know, small commute block, all of that's gonna go away. Because the the investors are gonna go from a round to b round, and then they're gonna need their kickback, and then they're gonna have to figure, well, are we gonna do ads? Are we gonna charge people money? I mean, I just there's no unique value proposition. It's purely a it seems to be purely a moral proposition. Right? It's it's like Yeah. There's more what what church are you gonna join rather than what technology are you gonna use? And so that's where I don't unless they have a unique value proposition where it's like, I can do this here that I can't do there, I have a hard time believing that it's gonna really bloom, especially because they're investor backed, and investors don't care about personal data servers. That stuff's gonna go.

Anselm Eickhoff [01:15:21]:
Yeah. I mean, I I agree with you, and it's it's honestly the part that I'm most nervous about that it's not apparent yet what their business model is going to be exactly, or if they're doing ads, how they're doing them. Because, like, I would love for blue Blue Sky to succeed just on the basis of it being an open protocol and hackable and so on. But until I see that, I kind of can't fully, believe in it. But, yeah, I'm I'm rooting on on on that basis. And so far, the indication seems to be that the people behind it are deeply aware of this conflict and are thinking about it in good ways, but I don't trust the fact that the introducing the monetization part is so slowly.

AJ O'Neil [01:15:58]:
Yeah. Microsoft's gonna come in and buy it and add Copilot. That is

Charles Max Wood [01:16:04]:
Yeah. If you're following along on YouTube, Owen Buckley's posted a couple of, comments as well, you know, about, you know, the algorithm or lack of algorithm and things like that. But it's anyway, it's it there's an interesting discussion to be had. Mostly, I went over there because there were people that had left Twitter that I wanted to interact with. And so, you know, as far as that goes, you know, maybe maybe Blue Sky just doesn't get traction and they come back or maybe they don't or I don't know. But for now, that's where some of the folks I wanna be around are, and so I'm there. And there are a whole bunch of people on x Twitter that I wanna be around, and so I'm there too. And yeah.

Charles Max Wood [01:16:46]:
Anyway so yeah. I I I apologize for

AJ O'Neil [01:16:52]:
my trolling. No. No. I'm I I I apologize for my for my trolling.

Charles Max Wood [01:16:58]:
No. There's I mean, it's it's it's a discussion that's happening in the community one way or the other. And so, you know,

AJ O'Neil [01:17:07]:
I I like what Owen says.

Anselm Eickhoff [01:17:09]:
Talk about.

AJ O'Neil [01:17:10]:
It's all just a bunch of yapping wherever you go for the LOLs.

Charles Max Wood [01:17:14]:
Yep. True. Alright. I'm gonna throw in some picks. So I always do a board game pick. I was at the, Timpcon a couple weeks ago teaching games. 1 of the games we taught was Imperial Miners, and I just posted the BoardGameGeek link. So Imperial Miners, it comes in as at a weight of 2.00, so it's exactly 2.

Charles Max Wood [01:17:41]:
2 is casual gamer friendly. It's it's got enough complexity to where it's interesting and fun, but it's not so overwhelmingly complicated that people can't figure like, I've picked some games on here that have a board game geek weight of, like, 4, 4a half. And it's like, look, this game's gonna take you 5 hours, and you're gonna get way into all of the ins and outs of how it's played. This is not that game. This game plays in I think we usually play it in, like, half hour. It says age 10 plus. That's probably about right. You can play it up to 5 players.

Charles Max Wood [01:18:18]:
I've always played it with 3 or 4 players. The so this game is a little different from some of the other games that I've picked where, you know, it's like, hey. You know, you're all interacting in this specific way. Imperial miners is like playing solitaire with other people. Alright? So, essentially, in the sense of you you're you're playing on your own board, and there really isn't anything else that anybody else can do to inter to mess with you. Right? So, essentially, the way it works is you're building a mine, and so you start with the top level of the mine, and, you get cards. So you get a level you have level 1 cards, level 2 cards, level 3 cards, and level 4 cards. All the level 4 cards are the same.

Charles Max Wood [01:19:06]:
They give you 2 points, I think. I I don't remember exactly, but they're all the same. So, anyway, you start with 2 of each card, and so you you play one of your level 1 cards because that's all you can do. Right? And then your next turn, if you want to, you can play a level 2 card that, connects to your level 1 card. Right? So you can't ever play cards that don't connect back to the surface. And they each do different things. They have different, teams or icons or however you wanna classify it, categories. And so, I think they're guilds actually is what they are.

Charles Max Wood [01:19:40]:
But, anyway, so they all kind of some of them play together. Right? So it's like, if you have other cards that are of this same kind, then you get, mine carts or diamonds, which are the points or, you know, whatever or or coins. And you can you can spend the coins to do other things, like you can, buy, essentially, moving your their technology tracks. You can move your marker up the technology track, or you can you can buy more cards that are more play things you can put into your mind. Right? Because there are, like, 4 slots for level 1, and so you can put in more level ones. But what happens is when you play a card, you get that card, and then you get to choose one of the cards that it connects to above it, and you they're offset. So you can pick between 2 if there are 2 cards above it. Otherwise, you just go to the the one that is above it, and then you, you know, you just chain all the way up to the surface.

Charles Max Wood [01:20:40]:
And so you do what each card says. Right? And then there's some other complications, like you can have a cave in. And so if there's a cave in, instead of getting that reward, you clear the cave in. Right? But and but there are reward there are cards that say, if you have for every cave in you have, you get so much money or so many points. And so sometimes you're playing that game.

AJ O'Neil [01:21:01]:
Emergency stop, Anselm has to go. I don't think you saw the message in the chat.

Charles Max Wood [01:21:06]:
Oh, okay. Do you have some pics, Anselm, before we go?

Anselm Eickhoff [01:21:10]:
Yeah. Quick one. You talked about Dune, AJ. I can really recommend the the the silo series on Apple TV. It's one of the most, fun sci fi things I've seen recently. But, yeah.

AJ O'Neil [01:21:20]:
Thank you.

Anselm Eickhoff [01:21:21]:
Was a pleasure talking to you guys. Nice to meet you. Yeah. Very very nice to talk about Local First. Thanks so much for having me. Take care.

Charles Max Wood [01:21:29]:
Alright. So sorry. I was on a roll. So, anyway, it's a super fun game. Like I said, it takes about a half hour. It's pretty simple. Everybody just goes at the same time and then gets whatever rewards, and then you do it again for the next round. And you play 10 rounds, I think, and then you're done.

Charles Max Wood [01:21:47]:
And at the beginning of each round, you flip over a card that gives everybody a reward or a complication. That's it. So I'm gonna pick that. I am finishing up putting together all the stuff for the AI Dev Boot Camp. You'll be able to get that at aidevbootcamp.com when that comes out. I'm hoping to have everything together for that, by tonight or tomorrow, so you can sign up. We're gonna start in the middle of January. It will Will be the 1st week.

Charles Max Wood [01:22:16]:
We're gonna run for 3 months. We're gonna have calls, at least a couple of calls every week, and just kind of walk you through anything that you're running into, answer questions, things like that, just so that you can build AI features into your applications. And that's everything from, like, help bots and stuff like that all the way up through, just sort of the I've got this text field and I click a button and it writes a summary for my podcast episode kind of thing. I mean, I'm I'm looking to build something for, the top end dev system that I just barely converted over to a SaaS where people can come in and instead of having to know which form to go edit the podcast, whatever whatever field in, they can essentially tell the the the bot, hey. Move the episode with Onselm from Monday, 8th or 9th or whenever this is gonna come out to, Monday, the you know, move it a week later, and it'll be smart enough to go in and change the publish date. Or, we have an episode scheduled with so and so to record on this date, and they say they can't do it. Can you move it back 2 weeks? And it's smart enough to change the schedule and update all of the guests and hosts that are planning on showing up and stuff like that. Or if somebody schedules an episode for Christmas, right, I can say, hey.

Charles Max Wood [01:23:39]:
Can you block out Christmas and move the episode there a couple of weeks? Or, hey. The the title that you have for this episode isn't great. Can you generate 3 more so I can pick 1? And it'll be smart enough to do that. So that's that's kind of the thing we're looking for. The system that we've been using to have the show notes written doesn't always get it right, and so it'll pick up on exactly the wrong thing and write a summary that we talked about Lord of the Rings instead of JavaScript. That happened once because Dan told the story about, how the Lord of the Rings got translated into Hebrew. And so it said, hey. They talked about literature, and it was like, well, technically, but anyway, so so that's the kind of thing.

Charles Max Wood [01:24:21]:
So I'll be teaching you how to do all that kind of stuff and how to choose the right LLMs to do that and how to connect to those services. I'm hoping to have, examples in JavaScript and Ruby. If you're doing some other language, you know, we'll give you enough tools to where you can figure out how to talk to the APIs and get authenticated and all that stuff, but you'll have to use whatever libraries in whatever language you're doing. So if that's Go or Elixir or something. I'm just trying to think what other what other picks I have. I could pick one that would piss everybody off, but I think I'll save that for next week. And, yeah, I guess I guess I'll just wrap it up there. I have redone the top end dev's website.

Charles Max Wood [01:25:11]:
I'm currently working through some issues, but if you point out an issue that I'm not aware of yet, I am totally willing to give you a discount or a free month to the JavaScript Geniuses, group or something like that. So just email me chuck@topendevs.com. And if it's not something I'm already working on or fixing, then, you know, I'll make it worth your while. So, anyway, those are my picks and then I guess we'll just wrap it up till next time Max out.
Album Art
Revolutionizing API Syntax and Schema Management with Jazz Framework - JSJ 663
0:00
01:25:44
Playback Speed: