¶ Intro
Imagine if you could mock up an app just based on React use state or like equivalent things, and you build your UI around that. but then magically your app actually works and like all of the status persistent and you can share it with other users and, you have permissions on there and you still only wrote front end code. That's kind of the Jazz story Welcome to the localfirst.fm podcast.
I'm your host, Johannes Schickling, and I'm a web developer, a startup founder, and love the craft of software engineering. For the past few years, I've been on a journey to build a modern, high quality music app using web technologies. And in doing so, I've been falling down the rabbit hole of local-first software. This podcast is your invitation to join me on that journey. In this episode, I'm speaking to Anselm Eickhoff. Creator of Jazz and founder of Garden Computing.
In this conversation, we dive deep into Jazz to learn how it works and which use cases it's a good fit for by exploring various apps already built on top of Jazz. Before getting started, also a big thank you to Rosicorp and PowerSync for supporting this podcast. And now my interview with Anselm. Hey Anselm, so nice to have you on the show. How are you doing? Hey Johannes, doing good. How are you? I'm doing great. I was looking forward to today talking to you about Jazz.
I know a little bit about Jazz and as I'm generally trying to scan the local-first ecosystem, but super excited to have you on the show and dive deeper, learn a lot more about Jazz, but before we dig in, do you mind giving a quick background and introduce yourself? Oh yeah, of course. I guess I've always been like interested in the web.
I think it technically, I started with like Flash for people who remember that, but I very quickly got into making websites, just static ones first, kind of doing web design for local shops in my hometown and that became more and more serious. I learned about Rails and like building whole web apps and what that even meant. And I guess most of my career kind of spent being like a full stack consultant, building apps for lots of different industries.
And typically I would be just like one man army doing like product design and building the backend and the front end and just building kind of the first version of that app that was ready for production. And then doing the next one and the next one and so on. And that was lots of fun. And I learned a lot, but over time, especially when you build lots of apps that are very different in nature, like who they serve, how they work.
You still notice that there's so many things that you have to do again and again and again, and they don't even really have to do with each app. And you're, you're. You're using these tools that are supposed to be like high level frameworks for building web apps, but you still need to do so much yourself, redundantly each time. Like people who build web apps will know stuff like, why do you have to do user auth and permissions every time or like file uploads, this is like super simple stuff.
and that always like nagged me. and particularly like, it seemed like. What you're really trying to do is just share state between different users of the app. And why, why do I have to build a whole stack and why is it so weird to do it? But I never really had a good, good solution for it. Right. And that's kind of what, what brought me where I am today with Jazz. And yeah, happy to tell you more about that.
Yeah, that journey definitely resonates and, sort of in a similar counter reaction, in, in 2016, just led me back then to starting GraphQL, which later turned into Prisma. So I feel like that's a common, somewhat common story to like, from like the previous trauma of like doing something over and over again in a way that doesn't quite satisfy you, where you feel like, Oh man, we can do so much better. so that story definitely resonates.
I'd be actually intrigued to hear a little bit more about some of the specific aspects, but I'm sure you'll, you'll cover that in comparison to Jazz. So, and Jazz is actually not quite the only thing you're doing since you're doing this under the umbrella of Garden Computing. So before diving into Jazz, do you mind giving a quick idea of like, what is that umbrella and what. led you to that?
¶ Garden Computing
Yeah, sure. So it actually started with an app called Garden, which was kind of like my take on what should a Notion clone look like, what kind of other ideas do I have, I was really fascinated by Notion when it came out and by Figma just like setting this new standard of like, it not just being like a higher fidelity app.
But one where like multiplayer and like rich multi user interaction is like baked kind of into the very fabric of the app and then the app itself is just like kind of like features on top of that, right? And I was like, this is cool, but I think It still doesn't feel fundamental enough. Like the multiplayer ness of it and like also the aspects that we now call local-first that I didn't really have a name for back then.
and I was like, okay, I want to do something like that, but I want to do that part even better and then build like even cooler features on top. And that, that was Garden. And yeah, I did a bunch of experiments there and that's. That's pretty much what, what led me to what, what Jazz became as for like Garden Computing as an idea for a company or bigger umbrella. I can get more into that later, but basically the idea is that.
I'm really fascinated by abstractions, by like powerful abstractions, by abstractions that are tall and like span many levels of, of understanding. And very often they come from like academia and research, right? That's where people find like really new, better ways of describing and building things. But they're obviously very abstract, very hard to approach for most people.
and from my experience as a. Full stack web dev, I'm, I'm like very in touch with what people are using day to day and what, what the mainstream developer is like and cares about. and I just love the idea of taking these new ideas and kind of like finding ways to package them in a way that makes sense for the mainstream. And that actually makes. What we use in the mainstream, a little more enlightened.
So I think in the broadest sense, that's, that's what Garden Computing for me is about and like Jazz and local-first is kind of like the first step in that journey. And I love the vibe overall of like Garden Computing. A garden is something that I think that's just, I'd say if you'd ask anyone, they'd probably associate it with like a nice, comfortable, homey feeling.
If you think about a garden, does this maybe even, you have a very personal relationship of like, maybe you put together the garden, maybe you care after it, or maybe not, maybe it looks a little bit wilder, but there's something very unique and something very personal to our garden compared to like a very Industrial, like hyperscale, like that doesn't sound like a garden to me.
and also like the use case that you've mentioned sort of like a Notion esque thing, I think Notion is also like there, there's this term of like a digital garden. so all of that is like a vibe that very much resonates. And it also resonates that you're saying you didn't actually start right away. with designing Jazz as a local-first tool, but that you're rather stumbling into it through working on an actual app.
Since there's also the analogy for me, the parallel that while working on Overtone, I also realized, okay, this is a data foundation that I'm working on that doesn't just work well for Overtone, but also for other apps. So I think this is one of the most authentic ways to Really think of a new data abstraction. So now with that background, can you give me an introduction to Jazz?
¶ Jazz
Yeah. So like, to audiences like this, I introduced Jazz just as like, a framework for building web apps in a local-first way. That's probably the simplest way to put it. That of course requires you to already know what local-first means. So I think maybe a nice way to explain it is to go a bit more in depth on like how through trying to build Garden, I kind of discovered what I thought it needed to be. Because in many ways I didn't like sit down and be like, Oh, I want to build this app.
I want to build it in local-first ways. and then I'll make a local-first framework to build the app because. When I started building the app, I didn't even know about local-first. I didn't know about that as a term. I saw apps like, like Notion and Figma. and I guess systems like Git, where it feels different from a traditional SaaS app with a centralized server and it has these really nice properties and it actually feels like it's suddenly very easy to do multiplayer, to have offline support.
And to like be really serious and honest about the fact that what you're building with your app is a distributed system and not like some thin client around like the app basically just running on another computer, on one other computer. so I was like, okay, I want my app to be like that. And I started building the app and I had all of these crazy ideas in terms of like features for Garden. Part of it was even like, it should be like a visual programming language in there and like.
I actually didn't get too far on that because very soon I was like, okay, what's, what's the infrastructure I need. That's like fabric that, that just has in the data layer, multiplayer and users and permissions and sharing and working on your device, but still being able to sync to the cloud. So I started building that just as part of Garden, right. and very soon just through like. abstracting and encapsulating the code. I had this like separate layer that did all of that.
and a big part of what made that layer possible was learning about, Ink and Switch and their blog posts and publications, seeing auto merge as the first CRDT that I encountered and being like, Oh, even just the idea of having like, synced state between two text editors is super interesting. Like, let's. Build the layer around that. And then once I had that layer, I looked at it and I was like, damn, this is like really interesting, not just for Garden.
but I kind of want to build every app ever like this now. thinking of all the apps I had built in the past, all the other apps I still wanted to build or the apps I didn't even know I could build yet. And I'm like, if I feel like that, probably other people will too. They just don't know yet that it's even possible to have this abstraction. So therefore I should probably try. And make this a framework. And that's, that's the origin story of Jazz, right? That makes a lot of sense.
And, it also, there's, this interesting dance of, being irritated and confused by some problems, this desire of like, could we do better? You kind of hope we could do better. You don't quite know yet how to do better. You see some proof for other apps. Being able to build something in an experience that you wouldn't quite know how you would replicate that.
You go on like looking around for ideas and luckily they're, very smart people, like the folks associated with Ink and Switch who are also like write about that and inspire others. And that leads you to maybe also like be very. compelled by those ideas, but maybe you have some slightly different takes. And so this is where, where it evolves. that makes a lot of sense. And I see a lot of like parallels there for like past endeavors and current endeavors that I'm on. So this is what led to Jazz.
And I think there's like a lot of similarities for how other data technologies, like in the local-first space came to be and, throughout the further conversation, I'm sure we'll learn about what makes the specific flavor of Jazz, how that compares to others, but maybe we can best approach that by talking a little bit more about the applications that, Jazz wants to empower. So can you, give me an idea of like, what is like a typical app that, Is just naturally now built with Jazz.
And what are some apps that you've like intended Jazz for?
¶ Jazz early adopters
Right. I guess one thing I will add in terms of like, what's special about Jazz and we'll go more in depth about that later, but like while building it as part of Garden, I realized that the responsibility of this layer.
It's actually not just a data layer, it also needs to, or like, I wanted it to also handle user identity and permissions because that's other, other, because like, that's what allows you to go from having a local-first app that kind of syncs between your devices as a single player user to just extending that model very naturally to multiplayer. and it just always felt like these two things, user identity and permissions also need to be part of that abstraction.
And that's kind of, that's the most special thing about Jazz, I would say. and that has enabled it to support quite a, like, wide range of different apps that, that even surprised me. and you kind of, you have apps that are like obviously local-first and are like a very good fit, and they are some of the ones that, that already felt the strongest benefit from adopting Jazz. for example, like I, I think Garden is a good example.
We're actually almost at a point now where we can start building Garden again, based on top of what Jazz is now. That's, it's like Notion. It's very clearly a local-first app. One of my favorite early adopters, they're an app called Invoice Radar, which is basically, it lets freelancers collect invoices automatically from like cloud providers and other things they use that send them invoices, manage them, and then submit them to tax authorities, for example.
And that's an area where like, yeah, having it local-first is really important. And the people who were building the app already, I think also without knowing the term at the beginning, knew that they wanted to build it that way. And then they found Jazz and they're like, Oh, there's like a framework that Just lets you build apps like that. And once they started building it with that, they were just able to get to like an MVP of their apps so quickly.
So that's kind of like, almost like an obvious success story. Right. But then there's other ones that are really surprising that start to push the boundaries of what a local-first app is, or does the framework even only need to be for local-first app? one I'm building myself with, my girlfriend that I presented in Berlin at our local-first conference is an app called Succulent, which is basically a Hootsuite alternative, like a social media scheduling tool.
And it's like 90 percent a local-first app where you can like plan drafts for Instagram posts, for example, on your device and you prepare them with the pictures and the descriptions and the hashtags. But then it has this component that's like not local-first at all, because like in order to meaningfully schedule posts to be posted, you need to have a server worker.
and, typically this would mean that, well, you just need to build it as a centralized, like, SaaS app where all this logic runs on a server. But, What I realized with Jazz is like, you can actually take this local-first concept further and the server worker can just become yet another local-first client to the shared state.
And then you get this really funky arrangement of like, you have this local-first app for authoring all this stuff and then just this little worker that whenever you're online and your stuff gets synced. It will know about what you're trying to do and then you can go offline again and it will post your posts for you by like interacting with the meta API, for example. So that was already a bit of a stretch of what Jazz can do.
But honestly, the most ambitious and most out there things in terms of what you can build with Jazz have been from like other early adopters. So one of the crazier ones is This guy Nikita is building an app called LearnAnything, and you can check it out. It's already public. You can go to, I think, Learn Anything. xyz. It's, it's like a cross between Quora and Reddit. It's like a learning community where you can be like, I want to learn how to play the guitar, or I want to learn TypeScript.
and for each topic that you might want to learn, you find this like community curated list of like really good links to other resources, like videos, blog posts, whatever. and that's just the social network, right? And the crazy thing is, he's already getting a bunch of impressions just from SEO, so you have like lots of, First time visitors and all of the state that needs to be loaded for each of these potentially huge topics, which have like thousands of links or something like that.
And he decided to completely pivot his stack to just use Jazz for everything. And I think one of his motivations is that, For each individual user, he actually wants the experience to be local-first in the sense that you can also have your own kind of like notion, like notes about the topic and your learning progress in there and manage your own collection of links and so on. But then through sharing it with others, again, it needs to have the scaling properties of a social network.
And that really, really stretched Jazz, but he was able to kind of like, Self publicly launched already and a version of his app completely built on Jazz. And so far it seems to be working. So, so that's kind of an interesting one. another one, which is very early and we'll have to see if it works, but it's basically like a local-first spreadsheet app, which is just like really intense in terms of like how much data there's in it and how like finally granular the interaction will be.
And then the last use case I'll mention also really surprised me because it actually uses Jazz to do much less than a whole app where, it's at this huge enterprise and they have like CI pipelines for like their build processes or whatever. but it's really hard to look at them and see what's going on, which builds are passing, which ones are failing. And it's all in this like super old system with a really clunky API. And this person just wanted to build like a dashboard for that. Right.
And that's really annoying. They decided to use Jazz basically just as a layer that makes that clunky old API real time and really easy to build UIs around. So they again have like a server worker that makes requests to that API and then maintains like a version of the state of all of the stuff in Jazz. And then they built a really thin client with Jazz and the two, like the status shared between the two.
And then they were able to super quickly build a really nice dashboard, where you see a real time updates of what's actually going on. and I, I think you can start to see like how these are actually all. Really weirdly different. And yet everyone was able to use Jazz as this like small tool that does a lot very successfully. and I have to say as a caveat as well, these are very brave people. Like Jazz is early in many ways. Some of its APIs are clunky as well.
The documentation really isn't there yet, but all the important like magic is already there and I think that's what allowed all these people to move quite quickly and confidently and the parts that still have friction are problematic. They were kind of able to work around it. I think that's kind of a good representation of where we're at as well. That sounds incredible. That's such a wide range of different apps and different use cases.
you mentioning InvoiceRadar, for example, I'm actually one of the early users of InvoiceRadar, I've been using it for multiple months now, and I can confidently say that, I would have probably not started to adopt it if it wasn't local-first.
Not because of like, that I say like, okay, now I have this bar Everything has to be local-first, like I still adopt other tools, but in this particular thing is, one of the, main ways, how this tool works is by getting access, like actually log in access to the various places that you where I pay for an invoice.
So this tool needs access to my Notion, to my Slack, to my Hetzner columns, to all those like very critical places I wouldn't give anyone access who I wouldn't really, really, really trust. And that level of trust, I can't just give that to like an arbitrary SaaS startup, that wasn't around like a couple of years ago. Even if it was around, I would still have trust issues. And that trust issues thing. They very elegantly address by, saying like, Hey, the entire thing runs all on your computer.
Like. All of like the login credentials, et ceterall of that, like not running in the cloud, like all remains on your computer. and so this is how that afforded me the trust and I've been using it. And, it works amazing. And I think it's built by folks, who are like very confident in sort of like front end development. And I think Jazz empowers them to like leverage their strength. And a lot of like the data moving around, that is taken care of.
So that is like a use case that I can already as a user speak to. And then I want to also hear more about the Learn Anything use case, since that's, to me, seems like it's actually stretching, quite on the boundaries of where local-first is even considered a good fit.
I think, if you hear about local-first, like where App use case works well, that's more around like data that's all like centered around a small entity, whether it's one user, whether it's one document, one workspace, one small team, but the more I think it's actually used sort of like as the counterexample, the more something is seen as a social network, the more local-first also actually becomes increasingly tricky to model around, to scale, et cetera.
So I'd love to hear a little bit more how, Learn Anything and how Jazz helps with this sort of like end boss of use cases.
¶ Edge use cases
Yeah, I'll, I'll go into that. There's two more things I want to say about Invoice Radar, because, I think that ties in quite nicely with what makes Jazz special, particularly for like your particular sensibilities as a user where like, yeah, you need to put your login credentials in there. Why can you trust it?
And part of the answer is, well, it, because it only runs on your device, but then even then you might want to, and I think they're working on like a mobile companion app to Invoice Radar. So you can also just like scan and paper invoices with your phone. So obviously it's like 2024, you want sync between your devices, right? Maybe you're no longer just like a solo freelancer, but you have like a small company and you want other people in your team to submit invoices as well.
And how do you do that while maintaining the trust that you have with the credentials and your invoices? And Jazz's answer there is exactly what I mentioned earlier that. User identity and permission is also part of the abstraction that it offers you, and it solves those in a local-first way as well. And we, again, we'll go into that later, but basically it uses public key cryptography to do permissions and auth.
And what that means is that, Their app can actually use my infrastructure to sync data between your devices or between members of your team. But my infrastructure only ever sees encrypted data and that way you can still trust that app despite having these modern properties of like sync, cloud persistence, and so on. for them, what it meant was that they envisioned their app initially as only like a single player experience. And it already makes a lot of sense there. And they were like, okay.
Later on, maybe in a year or a bit more, we'll add like team and organization features, and that'll probably be like a huge topic, right? But because they build it with Jazz, the idea of users and permissions is just like baked in and literally all they had to do to make it multiplayer was to build the UI for a little invite button. and their, their app was like multiplayer team ready from day one while preserving all of these like privacy and data protection guarantees.
Anyways, just like a short addition to that. I'm also really excited about Learn Anything for exactly the reasons that you mentioned, because I didn't think that quote unquote local-first could stretch that far and that's maybe where I'll go into a bit of a spicy take and ask the question of like, Just how useful as a term is local-first really, because it's really good at describing local-first apps, right?
But the abstractions that we build to make local-first possible, or at least in my case, what I'm trying to build with Jazz, it actually feels like something slightly more general than that, where like one thing I like to call it is like it's distributed state, and you already see that a little bit with apps like Succulent that has a server component, I don't know.
We have a couple examples with server components that already stretches it, but it's still just Jazz and it's, it's distributed state, not just across end user clients, but across server workers. But again, the trust relationships are now explicit. It's not just frontend and backend, but all these individual things. The way it works in Jazz, by the way, is that the server workers also have an account like a user and you need to invite them.
Two specific pieces of data for them to be able to see it and do stuff with it. so I really liked this idea of distributed state. And then, I also had this like coming to Jesus moment with Jazz where I'm like, what I'm building here is actually a distributed database. And I have to be honest with myself that it's a database. And, I don't know how many people that are listening or watching this are familiar with Redis.
But one way I always like looking at Redis is that it's like, it's, it's kind of like an exploded database. It doesn't give you the nice high level relational API that, that usual databases have, but it gives you all the little tools that you need to kind of build your own database. So you can have like your raw key value store and then different ways to build indices or like spatial lookup structures and stuff like that. And that's really powerful. And Jazz is kind of similar in a way.
It's like, I would say it's like an exploded distributed database with permissions built in. And once you start thinking about it like that. There's suddenly way more use cases where it can be a useful tool, including stuff like the, being this like real time layer in a purely backend setting, or you could imagine using Jazz as like a, distributing configuration for apps.
So like anything that's a distributed system where you might have network failures, nodes going offline, but you want to have meaningfully shared state with like History and auditability. You can actually use Jazz for that.
And I think even though I'm trying really hard to envision all these different use cases and build for it, there's probably a ton more that people will come up with, just by having something that's so flexible without like a narrow minded use case of like, this is for local-first apps or like, this is a database. Does that make sense? Totally. yeah. And I would love to dig in a little bit more into the social network aspect.
I think the exploded database analogy is, is very useful and maybe that also addresses a little bit how, Jazz is able to stretch beyond that, but can you make the, a little bit more specific? when you.
Remember other people, me included, saying that, for local-first, anything that's looks and smells like a social network or like a global, like basically if you have a lot of strongly connected, a vast set of strongly connected data points, this is where local-first has a harder time to sync all of that. And it seems like that would mean you need to sync literally everything. So you need to.
Chop off certain points in the everything is connected graph to not let the user wait forever until all the graph data is there, but to only show the user what they actually need. So how do you work around that? Or do you need to sync everything? That's kind of like, other than the like user identity and permissions making Jazz special. That's I think the only other big point that makes Jazz special is that from the beginning I kind of knew that it had to be.
Super granular when it comes to which chunks of data are you loading? And it's, it's much more, it's basically on demand by default. And the underlying data model is like an infinitely big graph of data that can reference each other. And you like. Load sub graphs of that as needed.
And for like a very local-first or classical app, that means, well, you kind of end up everything that one user needs or like a small team of people needs and there it's very obvious how that works well, I think the surprising insight is maybe that even in something crazy like a social network, even where you have single nodes, like people who might have a lot of followers, it's actually still quite like manageable graphs that are quite independent.
And what doesn't work is in my design sense, you can't ask the app developer to have to come up with the boundary of like, what is a chunk of data that makes sense to be loaded at once. I think maybe you could get away with it for an app like Notion where like the document is an obvious boundary to do that for, but even there it's kind of annoying and gets in the way, particularly with sharing and so on. So I think you just have to adapt that like a hundred percent granular mindset.
And then it turns out, Even the very highly connected graphs, they're actually manageable in size, and it is feasible to load them to display, for example, one learning topic and Learn Anything, even if it has thousands of links and thousands of people interacting with that topic. That's actually, in the grand scheme of things, not that much data to sync. And on my infrastructure, which is kind of inherently distributed.
It's like, obviously geographically distributed because that's like a nice metric to kind of chunk data up against. you can also start doing something very similar to sharding where you basically co locate data that is often accessed together, again, on a very granular level. And then suddenly even this like really hot data with lots of people interacting easily fits. into a single node, even a single core, and it's feasible to sync it to clients who all want roughly the same stuff anyways.
and if you're being honest, like databases face exactly that problem and that the way it's solved usually is just by scaling it,, like making your database node huge so it can fit all of the data for all of the users and then distributing and scaling databases is a hugely complicated topic and I think in many ways local-first is actually an answer to that in the sense that in the most extreme case you're like well we only need to worry about the data of one user and we'll
have a system that manages the data for one user, which is their machine. but then the abstractions you build to make that possible, if you include the granularity, actually also let you do everything in between where, yeah, you, you can have a couple of nodes collaborating to sync and persist and serve like, Subgraphs of that, like infinitely big data. Does that make sense? That makes total sense.
And before we're going even deeper here, and I think we're stretching a little bit into some like implementation details here, et cetera, which are super interesting, but maybe we take a little step back as a application developer who wants to build something with Jazz. Maybe you can walk us through, what does that look like?
So just to give a little bit of like a spectrum of options, we had Matt Wonlaw on the show where we, for example, talked about CR SQLite, where the idea was that, you replicate a SQLite database across devices. So this is where you have already Something that developers are very familiar with, which is a relational database that you can just embed in the app and then query. So that's one approach.
we heard from the folks working on AutoMerge, which is a CRDT based system, so where you rather think less about a database that's replicated. But more about individual documents, that are being replicated and state based as you change the CRDT document, those state changes are being propagated.
and there could be also other options, for LiveStore, for example, I'm following more of like a, what I consider a combination of both approaches where you distribute a event log and you recompute a, in this case, a SQLite database from it. So there's various flavors, various trade offs, which path have you've been going down with Jazz and maybe also why.
¶ How Jazz works
Yeah. So the meta comment there is that like, after you think about it for a really long time, a lot of these approaches end up actually being the same, but it really matters, I think, in terms of contrasting different frameworks and solutions and introducing people to the idea in the first place, from which angle you approach it and like the. It's like a replicated local database that's relational is a very obvious one. And there's a lot of people doing that really well now.
the document one is an obvious one. I think you'll be able to predict what, what my issue with it is that it like makes you. Put the boundaries, but I'm basically doing that. I'm doing what AutoMerge is doing. It looks like state, and I'll say that a bit more precisely in a second, but again, it's a bit more granular.
And the way I describe it typically, like the audience that I have in mind is actually not full stack developers or backend developers who are very familiar with relational databases, but in my case, frontend developers who are familiar with Local UI state on the one hand and kind of making requests to APIs as like the only external system they ever need to worry about.
So the story I tell this Imagine Frontend developer is that imagine if you could kind of mock up an app just based on local, like React use state or like equivalent things, and you build your UI around that. but then magically your app actually works and like all of the status persistent and you can share it with other users and, you have permissions on there and you still only wrote front end code. That's kind of the Jazz story and that's what the API looks and feels like.
So if, if you build an app with Jazz, typically the first thing you do is. You actually do something kind of database y, which is that you define a schema just to describe kind of what is the shape of data, which kinds of objects are the main abstractions in my app. interestingly, you don't have to model users at all because that's just baked in. So it's very nicely like, what are just the concepts that are specific to your domain that you're, addressing with your app.
And once you have the schema, you can just start having state of objects in that schema and build UI around it. And you can create objects of different types out of your schema locally, and you can create like, groups, which is kind of like the permission structure in Jazz and put objects in groups and then like give users access rights to groups, all like you can do these things literally in an on click handler of a button.
And it feels kind of illegal because of how simple it is, but that's it. That's how you build apps with Jazz and you can get very far with just that. As apps get more complicated, you can kind of. abstract things all kind of similarly to how there are solutions for not letting UI state get too complex. and the other thing you might need to start, if you want to talk to external systems like third party APIs, you can build the server workers that I talked about a couple of times now.
But the nice thing is you can build. If you also write them in TypeScript, for example, you just share the same data schema that you're using for the front end. And it really just feels like one, one small addition to your otherwise purely front end code. That's, that's kind of the Jazz experience, right? That makes a lot of sense. And I've just in parallel. going through the Jazz landing page here, where you have, this really cool chat app and 174 lines of code embedded here as well.
We can just see exactly that, like a little schema definition of this case for this chat app. There's just like a message. Class, a message concept and a chat concept. and that's it. You can use it right away in your React code, in your other code, and fire away. and you've also have here the user concept where you see like, okay, something is owned by me and then the chat, for example, is owned by a group.
what if I want to go a little bit more specific here and enforce certain Permission rules, that are more specific to my app. what is the story in progression there? So the way that that works is that it doesn't get more complicated than groups and objects belonging to the group. So like whenever you create an object in Jazz and like, I should say the name for them, we call them co values, like collaborative values. You have like co maps that are kind of like.
JavaScript objects, co lists that are like collaborative arrays, basically. and just like you can represent a lot of different kinds of data with JSON, you can represent a lot of different kinds of collaborative data with co values, right? And each co value has to belong to a group. The group is like the scope for permissions, and it simply has user accounts in it with a certain role. The three roles that exist are Reader, Writer, or Admin. They do exactly what it says on the tin.
and they then influence what people can do on co values. We can talk in detail later how that works under the hood, because I think that's interesting as well. But for now, that's all you need to know. And that maps quite naturally on onto a lot of stuff that you want to do in apps. But then the question is what about more complicated situations? And the answer there again is the granularity.
Because if you wanted to every, each co value, like imagine like a kind of tree of co values representing the state of a more complicated document or even like a folder of documents. The way that looks like in Jazz is that they're actually each individual CRDTs that just have plain data as values in their fields. Or they can have references to other co values.
And that's how you build this, like, potentially infinitely big graph, and you, like, load whatever you need to, like, display right now, or what you want to have offline. But the nice thing is that the groups that these co values belong to, and the permission structures, therefore, are kind of orthogonal to the, like, data references. So you can reference a co value, That belongs to a different group that has different members or where the same members have different roles.
And that way you can build permission structures that are just as granular. And you can even have like something like a notion document where like a small block might only be editable by some people. does that make sense? totally. you, you've been mentioning the reference concept that is giving you the kind of like a relation for a key kind of concept between different kinds of documents, and I think this is also describing the.
the boundary between one thing that needs to be synced and then another thing that needs to be synced. And if you model a thing like a network with that, how does, Jazz, how does it know where to, uh, how much it needs to sync? Where does it need to stop? Is there, so one analogy, for example, in GraphQL . maybe not everyone is familiar with that, but it's like a query language that is language agnostic and can be implemented with any sort of backend.
And this is where you can also define a schema kind of similar to this here. and aside from the schema, describes the potential graph of queries, or set of queries in a specific query. you need to very explicitly say, those are the things that I want to query. So let's say we model a file system from this, where we have folders and files and folders can have folders and folders can have folders in a GraphQL query. You need to say, actually, I want to, you need to explicitly lay out.
I want to go like all the way to like level three. So you need to say, I want to grab the folders and in that folders, I'm going to grab again, the folders. And I want to, there again, grab the folders, but you can't self recursively, infinitely, traverse. Is there a similar kind of explicit depth to how jazz should sync something. Is that determined at runtime by a React component, for example, is there some sort of middle ground? How does that work?
So there are kind of, and it's a really good question because like, that's kind of, you need a system that solves that. If you don't have the explicit boundary of like, this is, we can either sync all of that or nothing. Right. And the file system is a good example because it's. It's kind of potentially infinitely deep, but you're probably only ever looking at a subset, so how do you do that?
And the way, the quick and dirty way you do it in Jazz, which is actually really fun to just, again, super quickly build your eyes that work, is that, Jazz tries really hard to make covalues look like just plain JSON objects. And if you have co values with references to each other, they look like JSON trees. So what do you do then if like at some point you might not have a co value loaded? Well, then it just says that it's in a TypeScript sense that field is either the reference thing or null.
And,, if you try and render a specific tree in a React component, you can basically just use optional chaining to like render like this far. And if it's not loaded, show like a little spinner or something. But the funny thing then is that Jazz notices what you are trying to access. And it's like, Oh, you're trying to render like three levels deep. And you try to access this thing that we don't have yet in the background triggers a sync of the needed co value.
And once that's available locally, it re renders your component. And now that's not null anymore, but you actually have the JSON state for that co value and you render it. So very naturally by like building your UI and just deciding to render. What do you want to render it will lazily load exactly what's needed. And you can even manually do pagination like that by just having a little stateful, like, oh, I want to render 10 items and then you only drill down into the first 10 items.
And then like you hit a button or you reach the end of a scroll list or like. Elements become visible on the screen and you just ask Jazz to access more of them, even if they're right now, not, not available. And in the background, it will load more. That's the quick and dirty way. Super nice for prototyping stuff.
It's a bit weird in terms of user experience, because you end up with a lot of spinners and they like, they resolve really quickly because Jazz is fast, but it still looks unfamiliar to people. So if you want to give people a more polished experience of maybe one Loading thing until a bunch of status available. That makes sense as a unit. There is a way of specifically specifying a loading depth and that's.
That kind of looks like GraphQL lite, but because you only need to specify fields that are references, you don't need to say which plain data fields you need because they're always loaded. yeah, you, you, it's, it's actually very similar to Prisma. You just say which references you want resolved and then the Jazz hooks. Won't give you anything until all of that is loaded and then they give it to you as a chunk. That makes a lot of sense.
So you're basically just specifying sort of the graph of the references, not the individual fields of a document, since you typically want a document as a whole, that makes a lot of sense. And that's also, as I'm thinking through how I would model something for Overtone. when I have a music app and I want to listen to music, if I'm currently ermbarking on a train journey or on a like traveling somewhere where I don't have perfect connectivity.
I want to like that lazy loading just in time as I like click on a playlist. if I don't have connectivity, then at that point, it kind of breaks a bit of like that local-first promise. but I also understand like, let's say, Spotify is thinking about building it in that way. Spotify can't just sync the entire catalog of like all of Spotify on a single device. So there needs to be like some cutoff point. And I think while prototyping doing the just in time lazy loading, that's great.
But then as an app developer, in this case, for example, me building Overtone, as I better know, okay. I want you to find some rules of like, that stuff should always be there, like prepared for me going on a, on a train journey. And that would probably in this case be. For all of my playlists, make sure like all of like the tracks for the individual playlists are at least the metadata is there and possibly then have like also some rules for pre downloading some tracks.
If I have the rights to do so. that makes a lot of sense. And that seems like Jazz provides a really nice trade off of making, providing a easy way right away to prototype and then, dial it in to match the user experience that you want to provide.
And I guess I met the comment here with like, because you actually just now asked a very precise, interesting question, which is like, well, what if you ask it to load a chunk of data and not give it to you until all of it is there, but then your connection drops, what should actually happen? And like nothing being loaded, then it's actually a. Like you said, an outcome that violates local-first a bit.
So there, then we need to be more refined and be like, well, maybe show a spinner for everything for like two seconds and then give up and just show me everything that was actually loaded. and what we're getting to there is that I think like, look, I think it's starting to become clear how local-first in general is this cool new way of building app and how Jazz in particular things really deeply, how to make that easy for you as a developer.
But most of the challenges with local-first and with multiplayer, by the way, I think are UX challenges where we're like, well, what, what should happen? And that's something that we figure out as we try to build and dog food, our own apps. As we see what, our first adopters build with it and what makes sense to their particular developers and how you want to expose all of these different, like, is it loading? Is it locally available? Is it locally available?
But it's like, not quite up to date with what we know the syncing server has, but we didn't have a chance to get that yet. And there's like so much complexity in there. And in different situations, you need to expose like more or less of that. So I think beyond just like.
Making the sync and making the data persistence and making the permissions work, which like we're pretty good with now, there'll be a lot of like API design and also like educating developers and just figuring out UX together, like as a field, I think. I definitely agree. And like just the scenarios that we've now went through over the last couple of minutes, I think already go surprisingly deep.
For example, like the partial, like if you want to load everything and then you say, okay, I don't have everything, in some cases, it's fine to show a partial set. In some other cases, it might be like really nerve wracking for a user where if you don't signal like, Hey, we've just, we, we can't say this is everything. We've just fetched so much since otherwise a user might assume, Oh my gosh. Like this app has like lost some of my data.
and so this might, in some cases might be better to not show anything and like explicitly let the user know, like, Hey, we're sorry. when you come online again, we'll do our best to get everything in here. sometimes you also like from the data you fetch, maybe you want to like, let's say you, you shouldn't build a bank account this way, but let's say you build a bank account and you've just fetched a bit of like your, your like transactional history.
And it misses your latest, like, big check that you cashed in. Basically you added money to your bank account and it's not in there. And you think, Oh my gosh, like my bank account is like lost all of that money. Obviously you won't build an app like that, but I think the analogy kind of like translates where you derive data from other data and where it could be like really bad, you missed something. So this is really interesting to dig into the user experience aspects.
And that might also make for a really interesting future conversation, but I want to, Dig a little bit more into, into another related topic, which is the localfirst.fm podcast. And what brings all of us together is that we think we can do better how we build apps, at least in many app use cases, and Jazz shows for how many app use cases that applies. And so that means We, as a whole, as an ecosystem, we need to convince the people who are not yet in that small but growing ecosystem.
We need to convince them that we have a very interesting way how to build apps better, that are simpler to build, better for end users, etc. And I think each technology has their own specific, benefits, how that's, is a, is a good fit for, for certain app use cases and particular developer types. Like you want to target more like the front end developers. what is your approach to talking to developers?
How do you want to market Jazz to reach the right people and sort of the, I think you have a very interesting take on sort of developer psychology.
¶ Marketing approach
Yeah, yeah, totally. Because I think like, look, we're all facing the same challenge. Like you said of like, we understand how this is better and how it can benefit a lot of different kinds of apps. but counterintuitively it's, I don't think it's really about selling the benefits. I think the one big benefit that really does make sense. And it's valuable to people as just saying, look, like you've got like a 10 X better developer experience. It's way faster to build apps.
It's way easier to reason about. There's way fewer moving parts. I think that's kind of universal across all the different solutions. different solutions differ in terms of like what traditional parts of the stack they replace. I've put myself in the shoe of like replacing a lot of the pieces because I do auth and permissions, and by the way, you can also store binary data in Jazz.
So suddenly you don't need blob storage anymore and binary data just becomes part of the data you have locally and can be referenced just like JSON like data. and it's so easy to just think about what are the obvious advantages of that if you are totally bought into this and ready to build your app like that. That's kind of the easy part, right, to make. to explain that. But the biggest question is like, why should you even bother?
And why should you give up this really proven, familiar way of building apps? that means the biggest challenge is that it's so new and alien and different. So I think the trick has to be How can we make it look familiar and how can we make it look like something that already exists? And that's, I think where exactly the different audiences or, ways of telling that story for different products come in because, saying that you're replicating a relational database into the client.
That's taking something very familiar to like backend developers and then doing one little step away from that. And then like, Oh, and then it has all these benefits. Right. I feel like, yeah, I've made it hard for myself because I'm basically trying to replace the whole stack. And that's a story that actually, again, it works really well for frontend developers because the whole stack was never part of like where they had agency to begin with. So they're happy.
Full stack developers and especially backend developers aren't so happy because you're like. You don't have to do all of that stuff anymore. It's replaced by this giant pile of magic. I think like, I mean, what we identify as developers is being clever and building stuff ourselves. Right. And I think a big part of what keeps really complicated stacks and ways of doing things in life is honestly just the IKEA effect of like.
Well, but I built this myself and I like, I picked things that are individually good at what they're doing, but I put them together in this really clever way and local-first is like, it's just, it's so powerful that it takes away so much of that doing stuff yourself. That it's a real danger in terms of adoption and like not bruising people's egos secretly.
so one attempt I had was like, well, can I kind of not make Jazz one giant package, but more smaller ones so people can glue stuff together again. And I think that's kind of counter to like what makes Jazz powerful, which is exactly that it is a vertically integrated thing where even the different parts of like. CRDT, stage sharing, and user identity and permissions. They are actually very tightly knit together. And that's why, yeah, that's what makes Jazz special, I think.
But, the other way out of that, I think, and this is something I just have to do way more, is to have really good, like, under the hood documentation. And the cool thing is, like, I think CRDTs kind of get thrown around as this like mysterious new thing that magically solves everything, but like, it's really complicated. Don't worry about it. Like, you can read about it in some research papers if you really wanted to, but I think the way I've implemented CRDTs in Jazz is actually very.
Very straightforward, in the sense that it really follows a particular viewpoint of CRDTs, which I think is best represented by a blog post called, like, Data Laced with History, I think it's called. And it's basically just this, the simple idea of like, look, you just keep all of the edit history on an object around and that's what the object actually is. And then the current state is just a view over that history.
And if everyone has all of the edit operations and the full histories of different people collaborating on a document, then you eventually get the same state and that's it. and like, just as simply in like five or 10 more minutes, I could describe to you how then Jazz adds cryptography to do the like. Read and write access control, but it's actually not that hard.
And I think having really neat diagrams and kind of like a medium level explanation that people can read through in like 15 minutes and feel like, okay, these are the parts that are inside Jazz. And now I know like, if I wanted to glue stuff myself together, what I could glue together or which systems I would need. But I won't bother. It's enough for me to know. What's going on and that in itself already makes me feel kind of clever.
And then just going like extra deep on all the details for the people who want to be really, really clever. I think that's going to be important. and probably each framework has their own equivalent of doing that. And like, it's not necessary to use it at all, right? That the APIs that you use, if you build Jazz are much higher level and are much more in terms of like abstractions that an app needs, but.
Yeah, I, I think DevTools, the biggest challenge is that you are selling to developers, so you need to speak to developers egos, right?
Right. And I love the way how you framed that in the Ikea effect and how you, yeah, it's, it's like this delicate balance you want to, like, I think we can all get on the same page that we want to collapse as much complexity as much as possible, But developers still like love the abstractions, love putting things together and, like figuring out the delicate balance of having something that's already somewhat put together and does what they need, but then you can decompose it and
like compose it again in a different way. I think that's sort of like where the, where you need to apply like a little bit of like special sauce. and I think this is what you've already, laid out very, very nicely with Jazz, with like the APIs look amazing and the apps that are being built on top of it already. I think a really, really good proof for that. So slightly switching gears.
Jazz is no longer just a technology, but behind Garden Computing, you've also, I think you've thought about that for a longer time and recently took the step to actually, Turn Garden Computing into an actual company and build out a commercial offering around Jazz as well. and I think you've recently, took on a initial round of pre seed funding, so congrats on that.
but I'd love to hear a little bit more about what that means for Jazz as a technology, what your thoughts are on possibly offering a commercial product, sustaining the company otherwise around that, and how you're thinking of like Going beyond just working on this yourself, but possibly, scaling out the company or like hiring other people. So very curious to hear your thinking on that.
¶ Building the company
Yeah. So I think again, going into it from like, how did it come to be? I think it's important to say that, like, I'm not someone who's like trying to do a startup for the sake of doing a startup. I was very much like thinking of it as like an open source framework and was building that as like a good tool. And in a similar way where like the fact that it is a framework kind of became apparent to me while I was building it.
it became apparent to me that like, okay, even if you have all of these abstractions for distributed state and local-first, and that's all like, it feels very peer to peer. And I think in our legacy, we have a lot of peer to peer thinking. and that obviously influenced me, but I had this moment where I'm like, okay, if I really think about what I as a user want from the app, for example, very pragmatically.
I want sync between devices that works even if the devices aren't online at the same time. So I need some kind of centralized syncing infrastructure that also does persistence for me. Right. so that very obviously became a part of Jazz and then I'm like, it's actually kind of hard to run that at scale and to run it well and have it have low latency and so on, and that's something that a company could do as a service.
Right?, and it being open source, of course, you can also self host your own version of that either on a single node for like a small app, or you can be brave and try and scale it yourself. That's totally doable, but there's just obvious value in someone doing that for you. And the interesting extra component there is that. Because of the encryption, you actually don't have to trust that infrastructure with your data.
You can just use it for syncing and persistence, but know that it will never see your data, your user's data, whatever you care about. so there's this kind of like really useful service or product.
presented itself to me and I'm like, okay, this doesn't just feel like it wants to be a framework for people to really have that local-first development experience where you only want to have to worry about the parts that actually make your app, your app, and now you don't have to solve state syncing and permissions yourself anymore, but you would still have to build syncing infrastructure. That seems kind of weird.
Like. I think what you want as an application developer is to use a service for that, because then you're actually only left with your app. That's what I would want anyways. So like, okay, this is starting to feel like a company and I think I'm in a good position to build that company. and then it became a question of like, okay, I, for a long time, my plan was to bootstrap it.
and I did try to go into YC and raise VC funding, but I think we, as if Field are so early that it's, it's really hard for outsiders to see the potential in that. and what it took for me to have any success with that was to get Jazz to a state where it became obviously useful to developers. And they could start telling these like first success stories of like, wow, we actually built the SAP way quicker than we would have otherwise.
And then to do that in like a public setting, like the local-first conference in Berlin, where then investors can see that and be like, Oh, this actually really speaks to developers. And that's like, That's like an early signal they understand, right? So that's, that's what allowed me to raise that round. And now I'm in the, in the very fortunate position to have investors who understand how early we are and how much work it's going to take to really bring this into the mainstream.
And starting to have the person power through like hiring my first couple of employees who I'm really happy with and who, who really get it as well. And they're building their own apps with it as well. where I'm like, okay, we can actually speed run, the features that we need to reach parity with what traditional stacks can offer you, in the way that I think we need. That's, that's kind of the switch that happened there for me.
And before I had all of these ideas in my head of what I kind of knew Jazz needed to do, and believe me, I thought about everything. It's all somewhere on the roadmap, but I didn't really know what was most important, right? But the nice thing about having early adopters is that just becomes super obvious because they'll be like, They'll be blocked because Jazz doesn't have like this and we just built that next.
And that's kind of the journey that, that I've been on actually, since before the investment for about a year now. and now I have the luxury of being able to like tackle a couple of these at a time. that's kind of where I'm at with it. And the goal is to really.
To build a service that makes sense both for individual developers, for whom it will be the first point of contact with local-first or distributed state, for small companies to build, successful apps super quickly and kind of like being able to reach a much wider economy of small companies and individual developers who can now meaningfully build real things that are useful to people and maybe because. It's so much easier to build things. You can now build products that target smaller niches.
And that's really interesting. And also to just give a tool for like bigger companies or even enterprises to be like, Oh, it's actually really hard for us to build high fidelity apps. Figma like notion. We want these because we have lots of people and lots of teams that interact, but we don't have the know how to build something like a sync engine. That's just way too complex for a company to do itself.
But if that's now an off the shelf abstraction and there's kind of like an obvious either third party service or something that you can deploy on premises. That's really powerful and interesting and I think enables a lot more bigger companies to build their own software as well and have it immediately be as good as the best, like, SaaS apps we have right now. That's, that's kind of the potential I see in it and what I'm trying to address in the, in the medium term. I like that a lot.
And that also makes me think about, like the, this concept called small giants. I think it was also, I think I first learned about it on the Metamuse podcast by, that Adam Wiggins did in the past. Hopefully it comes back at some point. but this is where they did one episode about the idea of small giants.
And this is basically that a very small team, possibly could be like just, an individual small team, et cetera and they can build products, reach a really wide audience without having to build up all of that load and to. Like, for example, WhatsApp was when I think it was acquired before billions of dollars by, by Facebook, was still a very, very small company. I think, they've been, I don't get the numbers exactly right, right now, but like, I think within 10 to 50 people where they've already.
Reach like billions of users. I think similar for Telegram, well, Telegram is a little bit in the news right now, but, I have a lot of admiration at least for like how they built the product in terms of the craft, et cetera and it's also similar there. There's a very small team that can still reach a very wide audience.
And I think this is what local-first can really empower, where you can empower a lot more small giants to serve a much more richer, diverse set of use cases, where a bunch of current existing products could be replaced by local-first products, but not just by one local-first product, but a hundred different kinds of people who have specific use cases. There are a hundred different small giant. Build products specifically for their use case, for their niches.
so instead of like having, 10 very, very large monopolies, like, dominating a particular segment, let's rather have like a thousand individual builders reach smaller slivers and have products that fit particular use cases. And I think this is where you can empower them. They can focus. Similar to Invoice Radar, focus on specific use case and then, use a syncing service. So that makes a lot of sense. And I'm looking forward to that future.
before we close out, I'm interested in hearing your perspective on the more, the bigger web ecosystem as a whole, as you've been building apps within the web space for a long time, now you're contributing a, better development suite to that, but I'm curious whether you have any sort of strong opinions on the web development world that we live in.
¶ The web is fine
I think my strong opinion on it is that I kind of don't have one, or like there's a lot of critical voices that complain about all kinds of things about the web and its state that are completely fair. Right. But I think what kind of gets lost within that is that the web is actually fine. And it's not only fine. It's, it's like, it's amazing. It's like, I think first and foremost, it's this like crazy distribution mechanism.
and, I think, you talked about this in a previous episode, that like, you can just send your grandma a link and she'll know. What to do with it. Right. and it will, she'll see what, what you see. and that's crazy. That's something that is just so at the core of the web. And, sure. It's kind of weird that like JavaScript got tacked onto like a document representation and so on, but it is a really powerful VM.
That is super dynamic, would make anyone who likes Lisp or Smalltalk proud if you really think about it. But it's like, everyone has it. The best minds of our generation optimized it to the death. And you just get all like, CSS is crazy, but you can do a lot with it. and you just get all of that. And. It's kind of not doing what it was originally meant to do.
It's kind of like an app distribution system now, but because it's so flexible and so malleable, I think my big point is actually that we can just make it do whatever we want. for example, when I think about Jazz and what Jazz does, the way Jazz works is, is it's actually like a high level framework and then like a protocol underneath it.
And it's a very minimal, simple core that does like, the implementation of the CRDTs and like how to sync them, how to persist them and the cryptography, like how do the permissions work? That's all like defined. And then like you get higher level features on top. And if you look at that, it's kind of like a new networking protocol. And in many ways, it's like what I think the web should have been like just taking seriously that we're building like this.
Network of distributed nodes that have partial state and being able to represent user identity and permissions across that. so like one kind of pessimistic take would be that like, Oh yeah, that's obviously better, but we'll never get there because we're stuck with the web and this like centralized client server model. And that's like at odds, but like, it's not at odds at all. We've got web sockets and we can just build.
The protocol on top of client side JavaScript and server side JavaScript and hopefully soon other server side programming languages and native apps and, communicate over the web socket or maybe soon web transport or like HTTP 3 or whatever. It's like you can actually do a lot of crazy stuff with the web and, we can just like, yeah, just embrace the fact that In the history of computing, we almost never replace things.
We just add archeological layers of like, we're building the thing that we really want, but we have to build it in terms of what's already there and like widely available and it's actually fine. And that's, that's. How like you kind of have the psychological aspect that we talked about earlier, where like this crazy new thing has to look and sound familiar, but also very pragmatically it has to be implemented based on things that already exist where you don't have to really replace anything.
That's, that's kind of my take on the web, right? Right. I love that. I did this year, I did a three week journey through some of the national parks of the United States. And we also, spent a couple of days at the Grand Canyon where we just See like those like massive, massive, like layers of layers on top of layers that just reach back, I think like millions of years.
I don't recall the exact facts anymore, but I think it's a very good observation that, we rarely replace something categorically, but we just build on top. Maybe we phase one thing out, but that takes like, decades often. And, it's kind of a miracle how capable the web has gotten, given how weird it is and how many words it has. So I think I like that observation a lot. And, yeah, given the, given often the web for me is like a love hate relationship, I think the love still dominates there.
¶ Outro
So, uh, Anselm, this has been a really great conversation. I've learned a lot about Jazz. I've been very inspired by the way, how you think about the entire space overall. So maybe you want to have a, you have a last chance to plug anything, give any shout outs, but other than that, I'll thank you for your time. Yeah, I mean, thank you. I really enjoyed this conversation as well.
Definitely shout outs to Ink and Switch because they are my biggest inspiration and what kind of, what gave me a lot of the ideas in the first place.
In terms of plugging stuff, again, coming back to psychology, like I can tell developers about all the advantages of Jazz and so on, but like, So far, what has worked best in getting them to adopt it for even like a small experiment or even getting them to start doing the guide and the official docs is just being like, look, I've got these like shiny holographic stickers for Jazz. And like, I've got boring stickers as well. And like, everyone can get them at meetups.
I put them on tables and stuff, but like, if you want one of the special shiny ones, you have to build something with Jazz. And like, if you just do the official guide that counts as doing something with Jazz Just show me like wherever you are in the world, either we meet in person somewhere or I'll mail it to you, but you, you get the special shiny sticker. Okay. That's the deal. All right. There's, there's a first on the podcast. There weren't any holographic stickers yet.
So I might just as well give this a try afterwards. And the next time we see each other, I might steal one of those. But thank you so much. Thank you so much. I really enjoy myself. Thanks for having me, Johannes. Thank you for listening to the Local First FM podcast. If you've enjoyed this episode and haven't done so already, please subscribe and leave a review. Please also share this episode with your friends and colleagues.
Spreading the word about this podcast is a great way to support it and help me keep it going. A special thanks again to Rosicorp and PowerSync for supporting this podcast. I'll see you next time
