Explore how software engineers use Effect to build reliable, production-ready software in TypeScript.
The role that schema plays in Foldkit
can't be understated.
The entire model, all
of your state in Foldkit
is represented as a schema.
And that unlocks all
sorts of really useful things.
One example would be
the Foldkit DevTools.
Like being able to see while your
application is running
exactly what the entire
state of the application is,
is extremely useful.
I'd say it's even more useful right now
when AI is writing most of the code.
Your agent can see
exactly what the current state
of the model is.
And as a human
reviewer, you can also see it
in a given moment what the
current state of your model is,
even if you didn't write the code.
Schema is really the
backbone of any Foldkit program.
And I don't think
Foldkit could exist without it.
Hey, Devin, it's so nice
to have you on the show.
How are you doing?
Yeah, thanks.
Thanks for having me.
It's good to be here.
How are you?
I'm doing great.
The two of us seem to have
quite a few things in common.
Both of us started as web designers early
on, and now we have a similarly
great taste in hats for those of us who
are just like listening and not
watching, we're both wearing the OG
Effect.orDie hat, which I think you can
get in the merch shop of Effect can
highly recommend it.
But aside from that, would you mind
giving a quick introduction who you are
You're the author of Foldkit, which
we're going to hear a
lot about in a moment.
But yeah, maybe you want to
briefly introduce yourself.
Sure.
Yeah.
I'm Devin Jameson.
I'm the author and maintainer of a
frontend framework called Foldkit.
I am a software engineer.
I started my career in tech as a designer
and have worked mostly on frontends
React projects over the last seven
years and excited to talk about all
those things today.
That's awesome.
So beforehand, you already mentioned to
me that Foldkit is not just a side
project now plays a really like important
role in your creative work life.
That being said, you still
have a full time role as well.
Are those like overlapping in some way?
Are you building Foldkit also for work or
are those mostly separate?
They're mostly separate and I still have
a full time job at August Health
that I really enjoy and Foldkit has just
become a kind of a second full time
job that I'm really passionate about.
And there are a few ways in which Foldkit
has snuck into my full time work,
but for the most part, they're separate.
That being said, we do use
effect and really enjoy it.
Oh, okay.
Got it.
This is what I wanted to ask next.
And I'm sure we'll, we'll cover that
quite a bit more in depth.
But so Foldkit, I just saw this pop up
like a few weeks ago on X.
And like effect is like so rich and so
deep, but usually if there's
like a community effect library, like
it's already good if it has like an
approachable readme, but the Foldkit
website really stood out to me.
So that already grabbed my attention.
Then I saw like how extensive and how
ambitious the Foldkit project was.
with those first
impressions, then I also got a bit more
of a sense of like what Foldkit is even
going for and then I realized, okay,
it's actually like a fully extensive
frontend framework that is not based
on React, but competes with React.
So that seems super ambitious.
And before I want to learn a lot more
about the bells and whistles that
Foldkit provides, I want to address the
elephant in the room.
Why build a new front-end framework that
is not building on top of React, but is
building completely from scratch?
So I'm very curious to hear about your
motivation, sort of the technical
insights behind it, whether you like,
we're using React a lot in the past and
have certain like gripes with it.
So walk me through that.
Yeah.
I've used React for most of my career and
I think React is a great tool for what it
does and I see React as, well, React is a,
it's a UI view rendering library.
And what I've seen over the course of the
last seven or so years is that every
project is architected differently.
You end up pulling in a whole host of
tools to solve whatever problems you need
to solve for that project.
Like I've used React with GraphQL and SWR
and Tanstack Query and RxJS and
fp-ts and different UI libraries.
And it's very flexible,
which can be a benefit.
I think it also has some drawbacks,
especially in the AI world, but we can
talk about that later.
And so, over the years I
aligned on React patterns that I thought
worked and in particular the ones that I
thought worked at "scale" and the
patterns that worked for larger teams.
And I think making a React project
maintainable came down to protecting
that architecture that you'd aligned on.
And that was, that's
always a big challenge, right?
Like you didn't really have an
architecture that you
could just hold on to.
You had to protect it at all costs as new
people joined the team and you built
more functionality.
And as a kind of side quest, I ended up
working on an Elm project a handful of
years ago and totally changed how I
thought about front-end development,
loved it, and then sadly wasn't able to
work on any more Elm
projects just because
of like where the market was
and where it still is today.
But I took those Elm
learnings to my React work.
And about a year ago when I started
Foldkit, I had some
recognition that maybe
an Elm architecture front-end framework
would be possible in TypeScript with
effects and I didn't feel like there was
any way to really do it right without
effect. And now we are a year ahead.
And it's a real framework
that people are starting to use.
OK, awesome. So I want to understand a
little bit more what you mean by
architecture in regards to React since I
think there's like multiple dimensions to
building React,
multiple things to consider.
I suppose you're not talking about like
how to do styling, whether you use like
style components back in the days or
probably Tailwind today.
Like that's not what you're talking
about, but it's
probably much more of like how
does change propagate
throughout your application?
Like we're not just building a static
HTML page anymore, but like we have forms
and we have buttons and hover
states and context menus, etc.
So React has like addressed all of those
when it came out in like a much more
principled way
compared to the jQuery era.
In some regards, it has much stronger
opinions, but in regards to some other
areas, it has much weaker opinions.
I think that part is like
most notably how data flows.
And I feel this is also where the field
of different
technologies have forked more
most like radically.
This is where you have
systems like Svelte or Solid.
And it sounds like this is also where you
felt the strongest pain when working with
React that you needed to basically
protect one uniform way of like the
architecting the data system behind it,
that it kind of fits your way.
And this is where like on that side quest
with Elm, you had the most pleasant
experience and now where you're working
with Effect, you felt, okay, can we
somehow bring those two pleasant ideas,
one pleasant idea and one pleasant
technology, can we bring them together?
Is there roughly like
frame that in the right way?
Yeah, yeah, absolutely.
And for those not familiar with Elm, Elm
uses something called model view update
for the architecture, which means you
have a single model, which is your
application state.
That is the only place where
application state can live.
Your view is a pure function of the model
and update is where transitions happen,
where you go from previous day of the
model to the next day of the model.
So it's a highly constrained
architecture, but through those
constraints, you gain a
kind of freedom, like in the same way
that if you're working
on a creative project,
if you give yourself constraints, you can
oftentimes find yourself being more
productive. That's what a lot of people
find in the Elm architecture.
Got it. So if we rewind the clock a
little bit, I mean,
Elm has been around for a
very long time. I think some people still
use it
But I think at the back when I remember it
kind of coming to be, was round about the
same time when React also
really started becoming popular.
And one technology took React by storm
early on, which was Redux.
And so I think Redux and
Elm had a lot of similarities.
I think I don't recall the exact details
back then anymore, I
think, than Abramov back
then. I'm sure he was aware of Elm and
maybe wanted to bring
some of the best ideas of
Elm to React. But I think this is also
like for people who
have maybe never had the
pleasure to build something with Elm, but
maybe they had the pleasure of building
something with Redux back then.
I think that's like the closest analogy.
Yes. Yeah. And I'm 95 percent sure that
Redux was inspired by Elm.
Like that's why Redux
exists is because of Elm.
I've only worked with Redux very,
very briefly, like a
handful of years ago.
And yeah, I think it's a nice tool for
state management in
React, it makes state
management more principled, which I would
argue is the most
challenging thing in building
complex React applications.
That being said, it doesn't solve the
controlled explicit side
effects problem that Elm
solves. So I'll leave it there and we can
figure out whichever
direction we want to go.
OK, no, no, this helps a lot.
And I think this is the
most important part for me.
And I imagine like most listeners to not
just like dive right into
the technology, but first
asking like why does
the technology exist?
Since like departing from React is a big
leap since I think
even though you mentioned
that most React apps are kind of built in
a different way when it comes to the data
architecture, etc., yet it brings a huge
level of familiarity.
And if you worked at one company before
that uses React and now
you come in a new one that
uses React, there's still a lot of
knowledge that is
transferable, which you need to think
through twice when you switch to a
different technology.
But there is precedent for that with
Solid and Svelte, etc.
And I think it's really understanding
what is the pain point
that is so severe or where
is the opinion diverging so much that it
really like that fork in
the road is worthwhile.
And I think this confirms my
understanding that it's all about like
how data management,
state management, change management
within a front-end
application and an ambitious front-end
application works and also in a way that
it is convenient,
intuitive, and clear for humans
and also agents to work that it like you
don't just build like a
little form, but you build
a massive system out of
it that is composable, etc.
And I think back then when I looked at
Elm compared to React,
I think what just spoke
to me is that you
kind of flip the gravity.
Everything in Elm was centered around
this idea of like how
data flows, whereas in React
everything was kind of centered around
components and more of
like how the view works.
And I think here you're taking like the
same bet again where you say
like what if we re-envision
this around how data flows or like the
view part is almost
like a commoditized problem
at this point.
So yeah, I'm very curious like with that
anchoring how you've probably like
studied the existing
technologies, you've probably studied
Solid, you've probably studied Svelte.
If we disregard React, what have you
looked at those
technologies and what did you like
and where did you feel like now actually
I want to take even a larger departure?
Good question.
There's a lot I want to say.
So I don't have a deep
understanding of Solid or Svelte.
I think in order to develop a deep
understanding of a
technology, you really need to build
something quote unquote serious and I
haven't had the opportunity
to do that professionally.
That being said, I do know that Solid
uses fine-grained
reactivity and so it's really
fast and you're updating just the dom
nodes that need to be
updated and I think Solid
has benefits for that reason.
Svelt eI know less about.
The thing that I can say pretty
confidently about both solid
and spelt is that like React,
neither of them solves architecture.
They are bring your own architecture,
decide your own
architecture or have your agent decide
your own architecture tools.
When you say architecture, you mean
purely in the realm of the front-end app.
We're not talking about API,
microservices, queues.
We're just talking about the client-side
experience, whether this is like a
calculator that doesn't
have any server state or whether you're
building a Facebook
client that talks over an API.
We're just talking about the front-end.
Yeah, thanks for clarifying.
They don't solve front-end architecture.
Specifically what I mean by front-end
architecture is how
exactly do you manage state?
How exactly do you manage side effects?
How do you manage browser resources that
you might need to pull in?
How do you manage ongoing streams of data
that are updating
state in your application?
that's the hard stuff about
front-end development.
Once you have developed a sufficiently
complex system that is maybe local first.
I work on local first stuff at August
Health and it gets
complicated once you start dealing
with a local database or a remote
database and complex forms.
Going back to your question, I think for
a handful of reasons, a highly
opinionated framework
that prescribes the architecture is
extremely useful right
now for both humans and AI.
I can keep talking about
this, but I'll throw it back.
I think you're spot on.
You mentioned that
Foldkit is opinionated.
I had exactly the same observation.
This is why it spoke to me.
It's not just opinionated about the data
architecture, but now also takes the bet
on being opinionated
about a particular underlying technology,
which is effect,
which brings us all here.
I think this is what makes it maybe a
more risky bet for someone else to adopt,
but for the people who are already in
the fold, no pun intended,
with the effect ecosystem,
I think that for them is even more
attractive this way.
If supposedly that the architecture is
exactly the way how they think about it,
and I think it's a very, very good
default, now you're also opinionated,
therefore embrace what the
effect ecosystem gives us.
And I think that unlocks a lot that other
technologies, whether React or Svelte,
they're much more agnostic to many
things, which is also a good thing.
This way they maintain their optionality
and people can use it
with many different things,
and there's integrations, but it will
never be as good and as natively
integrated as a technology
that really fully embraces
the underlying technologies.
And I think there is another side of a
coin when we talk about data.
Sure, it's like the architectural part is
how does data flow, what
is the source of truth,
what is derived, what happens when.
Events are obviously super important when
you build an interactive application,
but that data always has a shape and that
data has constraints.
And I think therefore, Foldkit is the
first front-end
framework that acknowledges that
and doesn't just give you a loose type
where in the next moment you can say,
as any, and there's no really hard
validity to that data, but
now you're embracing effect,
and therefore you're also embracing
effect schema, which I
think is a huge unlock here
where it can absorb a lot of complexity.
In all parts of the system, we're
probably going to talk
about forms and other things,
but we have in a modern front-end app,
you have so much data just
moving around all the time,
and all that data, you need to know what
you're working with.
And I feel this is another huge unlock
that you're embracing here
that I think makes the
entire batch really worth it.
I would agree. Of course, I'm
biased, but I would agree.
And I think the role that schema plays in
Foldkit can't be understated.
I mean, the entire model, all of your
state in Foldkit is
represented as a schema.
And so that's really the foundation of
any Foldkit program, and
that unlocks all sorts of
really useful things. One example would
be the Foldkit
DevTools. Being able to see
while your application is running exactly
what the entire state
of the application is, is
extremely useful. It would have been
really useful five, ten
years ago. I'd say it's even
more useful right now when AI is writing
most of the code, and your
agent can see exactly what the
current state of the model is. And as a
human reviewer, you can
also see at any given moment
what the current state of your model is,
even if you didn't write the code.
So yeah, schema is really the backbone of
any Foldkit program. And I
don't think Foldkit could
exist without it. In that regard, I mean,
you're not using that
language on your website, but now
I'm thinking about Foldkit as not just an
effect first front-end
framework, but also a data and
schema first front-end framework, which I
think a lot of form
libraries, et cetera, maybe have
sought compatibility or in our standard
schema compatibility, but
you're taking this way further.
Once you start embracing a schema, and
with my background, having
created Prisma back then,
working on Livestore, et cetera, schemas
are always at the core of
you can't have data without
schemas. Sure, you can say you're going
with MongoDB and say
everything is schema-less,
but your data has a shape and form no
matter what. It is very
messy and can take 10 different
forms, but ideally you still model that
with a union of a schema.
So I think this is something
aside from the architecture. You could
even make a different composition of your
bets and trade-offs.
You could, for example, say we're going
with React, but we're
baking schemas right into it,
and we leave the data architecture a
little bit more agnostic. But I think
here you're just taking
two super strong points together. There's
schema with a schema fold
data and the Elm architecture,
and that is the foundation. So to my
understanding, if we just
look into what Foldkit provides,
it is very extensive already. So if we
can just maybe do a little
bit of a comparison. If you
look at Foldkit, compare it to something
like React or something like Solid or
Svelte, where would you
say there's already parity and where
would you say there's the biggest gap
still? I suppose there's
no equivalent to React Native yet, but
when we're just talking
about the web as a front-end,
how should I think about
parity versus open gaps?
Yeah, I think the biggest gap between
Foldkit and React is
ecosystem, and that's a big gap.
There's a huge ecosystem of React tools
that you can just pull
into your project and use.
And I think at this point, on most of the
other fronts that matter for
developing web applications,
Foldkit is at or very close to parity.
And I think Foldkit also
has benefits that React
structurally cannot have because of what
React is. You mentioned earlier that
React is the unit of composition in a
React application is the
component. And a component is
managing state, it's managing side
effects, it's managing
caching, like memoization,
it's managing the view. And that's how
you write React
applications. You make a component,
then you make another component, you make
another component, you nest them. And
what tends to happen is your state and
your effects and your
caching and all this stuff
just accumulates across dozens of
components. And this is often if you're
doing a really good job,
if you're a really good React developer,
this is just how it works.
Foldkit is, you said it flips it on
its head and it says, no, there's no
concept of a component
that does something locally. Instead,
we're going to have a
global model. We're going to have
explicit messages, which are the
precursor to updating the model. We're
going to have explicit
effects, which are actual effects and are
called commands in
Foldkit, which we can get into.
And the view is going to be a pure
function of the model. And so React,
we're trading the local flexibility of
React for this globally coherent system.
And I think that is a
lot more beneficial than it
sounds on its face. That unlocks all of
the cool things that you
get with Foldkit and that
AI agents can also leverage Foldkit.
Yeah. So I mean, designing good
abstractions, I feel like this is one of
the most ultimate forms
of being an accomplished engineer that
you have opinions on
that and you can actually
build, go further than the abstractions
that there were before. I
think this is what really
blew my mind about effects and like ZIO
before then, like always
had a lot of admiration
for functional programming. And I feel
effect has really brought it
to a point where it's not just
like academically brilliant, but also
practical. And I feel like
one of the highest goals there
is always composition. I mean, when we're
building applications, our
ambition level doesn't decrease
quite the opposite. There's devices can
do more things than ever.
We now need to make them
responsive. We're trying to make them
work offline. There's so
many things that so much
entropy, which we need to somehow model
in our application. So
it's a matter of like,
how can your application even stomach
that? How can even whether
it's coding agent, whether it's
you, there's just like, like lines of
code, like adding up and
adding up. And like, you now kind
of need to having the amount of
complexity is one thing, how densely can
you like express that in a
way where you differentiate between
accidental complexity and
existential complexity. I think
ideally a system has close to no
accidental complexity, but it's all
existential complexity.
But then it's a matter of like, how do
you organize that? And
when you organize that,
and you can compose it well together,
then like the over
complexity of your system miraculously
like shrinks. And I think this is the I
think the underlying
abstractions that unlock that almost
like as an emergent property, that if you
model your application in
like this way, the overall complexity
of your system is lower than with another
technology. I think
that's like the money shot
here. And I think this is maybe maybe you
have thoughts on how
the compositional emergent
behavior of like building an application
with Foldkit compares
to something with react. So
you've talked about components versus
views and models and
commands, etc. So I'm curious, like
walk me through like the insights that
you had, like I suppose a lot
of that was also like already
based on like the insights that form for
Elm. But like walk me
through those insights, then also
like, like illustrate a bit how I should
think about that
compositional behavior. Like I remember
when I used react, like I had those aha
moments where like a lot of the
complexity that I had in
previous applications kind of disappeared
when I used react, the same thing
happened with effect.
And so I suppose you wouldn't be building
this if you wouldn't believe
that it even has a superior
compositional behavior. So I'm curious to
learn more about that.
Yeah. Yeah, I really like what
you said about accidental versus
existential complexity. And
I would I would tend to agree
that well, I'd put it this way. I think
if a program is really
complex, it should look complex.
And then as you look more at it and you
dig in and you understand
it, that complexity should
unfold and become clear as you develop
your mental model of what
you're looking at. I would
amend that in one way in that regard that
I'm almost thinking about this like as a
as a fractal, where like you basically
have like a shape and ideally
that high level shape doesn't
even look that complex. But you're
wondering, huh, how does
this work? And then you zoom in
the other complexity that you have like
zoomed away from like
disappears. And now you can look
a little bit more at the inner
encapsulated complexity. So I think the
yes, basically about
what is localized as much that can be
localized that belongs
together. I think that's the thing
to aim for. Yeah. And I think when I look
at like in particular
effect code, even if it's really
complex, if I if I zoom in and I look at
what's happening locally, I
feel like I can trust what's
happening. And then I can zoom back out
and given what I trust
about what's happening locally,
I can develop develop this global
understanding of what's what's
happening. And I think that it
that's very, it's very honest to what is
being modeled. And I think
Foldkit is doing the same
thing in large part because it's, it is
kind of effect like it has
its own architecture, but
complex Foldkit code, like
doesn't look super
straightforward and like
easy when you like first look at it, but
then you look at it more and you're like,
okay, I get it. This is honest. This is
clear. And do you want to respond before?
Yeah, one observation on that as well. I
think there's so many parallels between
Foldkit as a project that builds on top
of effect, but also
effect itself. I think the
the trade you're making with effect is
like you're learning a little
bit more of like a complex tool
kit. Like thing like wrapping your head
around like what an effect
is takes maybe a tiny bit
longer than wrapping your head around
like what a function is.
But once you have a very complex
function,
you've understood the concept of a
function, but looking
at that very complex implementation of a
particular function gets a
lot harder. Whereas like if you
have it expressed in effects, and you've
already like have your
check mark of like understanding
what an effect is. Now you look at that.
And that's actually
simpler. And I think it's a similar
trade here with Foldkit. Like you need to
build an intuition and
internalize what does it mean?
Like for some, what does a model mean?
What does a view mean? What does a
command mean? But once you
have that, now that lowers sort of the
complexity, like entry price for
something and you've already
you have that richer vocabulary that your
application that you want
to model that shrinks to that
existential complexity.
absolutely. And so in terms of you
mentioned composition,
maybe I'll talk about that for a second.
And then I think this could
be a good point to actually
look at some code. I think it could be
helpful. Yeah, I think if
you think it would be most
beneficial to like illustrate that
through code, let's
certainly do it. Yeah. Okay, cool.
Before we dive into that, like broadly
how I think about
composition and Foldkit is
I strive to make every piece of Foldkit,
whether it's model,
message, update, view,
command, subscriptions, et cetera. And
almost all of that comes directly from
the Elm architecture.
I don't invent this. There are a few
pieces that are new,
but the seams between them
need to be super, super like airtight.
And they each do exactly
what they say they do and
nothing else like ever. So you can trust
that this is doing one
thing, you fit it with this thing,
and then together you get some more
complex, interesting
behavior. So that's how I think
about it. And yeah, let's look at some
code. Awesome. So you're
going to share your screen
in a second, which domain like when you
built Foldkit and you
don't just build the system,
but you've also done a fabulous job of
creating a website for it, creating
documentation for it.
And now the job of the documentation is
for other people to form an
intuition. And so you had to
also pick examples that are most
well-suited to illustrate
the powers of Foldkit without
overwhelming a user to absorb the domain
first. So I'm also very
curious to hear more about that.
So yeah, in terms of examples, I
started, of course, with
the counter example and then
just tried to make something a little bit
more complicated, a
little bit more complicated and
run into issues that I couldn't support
with the current framework.
And so that's really just how
have evolved. And so I think if you go
through every example, they'll
progressively get a little
bit more interesting and complex. And
that's a great way to
learn about the framework.
So you're sharing your screen. You're
having the left side. For
those who are just listening in,
maybe now is a good time to pop out your
phone and look on the
screen, not while you're driving,
please. Or if you want to look at this
later, you can also find all the code
snippets, et cetera,
probably in the Foldkit repo. And we try
our best to give you an intuition for
what that looks like
just on audio. But it's probably best to
just look at the screen sharing here.
But what immediately stands out to me, I
suppose we're going to see in a moment
the source code for an actual
application. The application
we're seeing here is not just a counter,
but it's an app called Pixelforge, it
seems. And it seems like a
little like a mini-Photoshop
paint kind of thing. But this is already
not a trivial kind of
application that I think will
probably demonstrate the capabilities
quite well. So that's to be
said about the application.
And about the code, this is the very
first time I'm looking at
Foldkit source code besides the
docs. And what stands out to me here is I
have now a pretty good
intuition for what React code
feels like. I think most of us have. And
I have a good intuition for what
idiomatic effect code is.
And this is the first time I'm seeing
those things side to side
and where it feels like. I have
getting a first taste of what idiomatic
Foldkit code looks like.
And my first impression,
first impressions I think here are always
interesting things. It's really nice.
I think we're going to see there's a few
controversial parts
about Foldkit for some.
For example, I think Foldkit doesn't have
JSX, which we're
going to see in a moment.
But my first impressions are really nice.
Cool. Thanks. Yeah, I'll just give a
quick demo here of Pixel
Forge. So it's a Pixel Art app.
It's very simple. You can draw stuff. You
can change the color. You can do fills.
You can, let's see, you can do this
mirror thing, which is kind
of fun. So if I go to brush
and then do that, now I'm mirroring. I
can mirror both
directions. So yeah, it's just fun.
Fun little Pixel Art app. So we'll make
something kind of cool here.
I'm already noticing about the Pixel Art
app here, besides all the
tools you've demonstrated,
on the right side, I'm seeing a stack of
what looks like the
history of what has happened.
And I have a feeling, this is what I
remember about Elm and
what I remember about Redux,
something, something time travel. So I
think there's a first-class benefit
of working with
Foldkit, at least in this app.
Yeah. So undo, redo, going back to
previous states in the
model and going forward,
falls out very naturally from the
architecture. So of course, this is
something you can do in
any framework or without a framework, but
in Foldkit programs, this tends to just
be a lot easier to manage. Yeah. So yeah,
we can go back. We can go forward. So
and the idea here was, oh, we can also
just save our Pixel Art. So
the idea here was to create
something that was non-trivial, but still
approachable. And then
also just touch on this
while we're here. This is the Foldkit
DevTools. So we can see at
any moment what the state of
the application is. So like this is our
grid. These are all
our Pixels right here.
We can see. The DevTools are basically
just like a thing that lives
inside of the web app itself.
Got it. Yep. And then for any given
message, we can see we
entered cell x19 y16 here.
Got it. Yep. So the DevTools basically
gives us a view into the
current model, which I suppose is
the current state of the live
application, but also the messages. So
anything like the events,
anything that has happened within the
application, I guess we'll
also hear more about like what is
the message, what is the command, but
there are also commands and
there seem to be, it's a little
bit small, but it's just like mounts as
it's supposed to be. Yup.
Maybe we'll shelf that for
a moment. It like walks through a bit of
how the application is
built from a code perspective.
But I like the example app as something
that is like a nice
balance of not just a counter.
So it's reminiscent of like a real
non-trivial application that
has probably all aspects of
what is important. It has like little
forms, has like little
real-time reactivity, etc.
Yeah. Let's dive in through the code and
like what we see here in
the code is as for every
effect app, there's always like your
main, like the thing that
the entry point you run.
And we have the same thing here. Yep. So
this is the entry
point for a Foldkit program
conventionally. It's called entry.ts.
This is where you make your
program and then you hand it
to the Foldkit runtime to run it. So
making your program means pulling all of
these pieces together.
So our model, which is our schema
representation of the entire application
state. I'll skip flags
for a moment. In it, this is your initial
model. So you need to tell
the program where do we start.
Update is your transition function. How
do you get from one model to the next
model given a message?
View, pretty self-explanatory. It is a
pure function of the model.
Subscriptions, I'll also
skip this for the moment while we're
getting into the basics. Container where
you're going to mount
it and then some devstool stuff. So
that's it. And then making a
Foldkit application is just
deciding what all of these pieces are and
describing them. Got
it. Yeah. So what do you
feel like is the, we have a lot of
different entry points now
to choose from. I suppose the
model is probably just a collection of
different schemas. So maybe
that's a good starting point.
And I kind of like you driving this
because it's like, you're
seeing this for the first
time and getting a sense for what's
happening. I think that's a
nice way to go through it.
Imagine we're working on this project
together. I'm opening
the repo the first time.
And so I'm now trying to form an
intuition. Having used the app has
already helped form an
intuition. So now I'm wondering, okay, so
we have this grid thingy.
Okay, I see the grid in the model
and all of this feels immediately
familiar because it's
just effect schemas. So yeah,
we don't need to spend too much time on
that. This is like a very
concise way of how you've modeled
the application, which is always like an
orthogonal concern in the
first place that speaks to the
experience of an engineer. How good are
they to model the application
state? And I think one thing
where you and I certainly share the same
vision. I'm a huge fan of the Elm
architecture where you
separate the state that you materialize
from events. So here you're
modeling the state as a model.
And all of that is like you probably
don't mutate that model
state directly, but you probably
derive it from something that's
happening. So maybe we
look at that counterpart.
Yeah, so let's look at message. I think
that's the next thing.
But maybe just one thing to acknowledge
here. What we've seen is
that we have a schema to
model or to encode the shape of our data.
This is already kind of like
a world's first in at least
the TypeScript front-end world where as a
starting point, we're not
looking at how does the view work,
etc. How does the data work? And I think
this is already like a I
feel right at home here.
And I think most effect developers will
feel right at home. This is
very similar to how you build
a effect app. I typically start by just
thinking about what sort
of data do I have in this effect
program. And it's like just the same
here, just with like one
layer of an opinion on top
where you separate events from state. And
I think this makes a ton of sense.
Cool. All right, on to messages. So
messages represent
facts about what happened
in your application. And they are what
feed into the update
function, which is where
the next model is derived. So to look at
how state updates or
how the model updates in a
Foldkit application, the first place to
look is the message union
because this tells you every
thing that happened that
could result in a state change.
Got it. So this is basically when we
clicked around in the app,
we selected a different color
or we drew some pixels. This is like when
the app says, "Yes, that has happened."
It becomes a message.
Yeah, exactly. So if we do pressed cell
here, so we'll
actually click pressed cell.
We'll see here, pressed cell message, X5,
Y3. And then if we
actually go look at pressed cell
here, we'll see it as a message pressed
cell with a payload of the
X, which is a schema number,
and Y, which is a schema number.
It is a little bit more than just a
schema. It is a schema
and it is or like a struct.
And then it has a name. I suppose, is
that mostly just for the dev tools or to
persist some state? Why do I need to
provide that pressed cell name?
This is the tag. So this is how the
update function figures
out what message this is.
So it's basically like a tag struct.
Yep, exactly. Yeah, M is just a tag
struct under the hood that is callable so
you don't have to do
.make and there's a clear
convention for making messages.
Okay, got it.
Okay, cool. So yeah, we have now those
two different parts.
You've mentioned the update
function where probably from different
messages, you get to keep
the model state up to date.
I suppose those are just like pure
functions that where you
can splice in your data.
Okay, there seems to be some interesting
stuff here going on
with an interesting API.
So what am I looking at here?
Yep, so this is the update function. And
what's happening here is we
are matching on the message.
Got it. So we're using
the effect match module.
Correct. So update function takes the
current model, takes the
message. We use match from effects
dot value on the message. This is just so
I can infer the return
type. And then we handle
every message. So here.
Very straightforward.
We take in the old model. That's the old
model state, whatever it
might be the initial one.
It might be we've already done something
and then we take the new
message. The message could be
anything. So now we basically just need
to match over that message.
And like in the case of where
like whatever you click the messages
delete everything,
then we delete everything.
Makes sense.
Yep, exactly. And you also mentioned pure
function. Yes, update is a pure function.
And that means that every time it runs
given the same input,
it'll give you the same output.
And so just to go through this, like very
quickly, if the tool that is currently
selected in the model
is fill when the message comes in, we do
some work to figure out what the next
model is. We apply a
fill, we push history. So these are just
other functions. And then
we return the next model.
And then there's this other
thing. So this is next model.
Yeah, besides just like a pure function
that returns the next
model, but we're returning
a tool of the next state that we want.
And there's like the
second thing in the tool pool,
which I'm curious what that is. And there
seems to be a function,
maybe it's a helper function
called evo, maybe evolution or evolve.
That's my intuition. But
like, yeah, what are we looking
at here?
So evo is very similar to struct.evolve.
In fact, it actually uses
struct.evolve under the hood,
but it provides some stricter typing. So
you can't have keys
that don't exist in the
struct that is being passed in. So it's a
safe mutation, basically.
Yep. Got it. And then there's this, yeah,
there's this other piece that we
returned. So we return
the next model, but we also return an
array and there's one
element in that array and it's
save canvas next model. So this is where
commands come in, because
side effects need to happen
in applications.
So yeah, how does, and maybe just before
looking at that, this is
like one of the tricky ways how
you like model that in a frontend
framework. This is where reacts, like you
gotta like choose a way
of dying somehow, like a reacts way is
the notorious react.useEffect
You need to
perform that somewhere and like with
react, you get also, as opposed like a
huge percentage of just
the inherent complexity of a big react
app, or possibly even like
the accidental complexity of
a big react app is to figure out like how
do I do the stuff in the useEffect
In which order does
it happen? Like do I consider all the
cases? What about the
dependency array here? And so you're
providing a different way of like to
think about this. So again, there's
probably a fair amount of
nuance to this. We can probably only go
so deep. But I'm very
curious to like hear about the
inside behind this and how that unlocks
like better saner composability.
Yeah, great question. So first of all,
this comes directly from Elm.
This is the Elm architecture
through and through commands are an Elm
concept that Foldkit has
inherited. And the reason
this exists is the update function needs
to be pure. And it's
really useful. It's core to the
architecture that the update function is
not doing anything. It is
just describing things. It's
returning the next model. And it's
returning a description of the side
effect that the runtime
will then manage. And this is like where
the effect, not broadly,
but like the effect type
comes in or the effect value. Can you
just before we're looking at
that, can you briefly explain
and sort of the intuition of the app?
Like what is the non pure thing that is
happening here? Like
does it is basically because it draws
something or it could like play a sound
or something. So that's
not what makes it a not a pure function
in this case. Yeah, good
question. So in this case,
we want to save the canvas to local
storage. So like when I
refresh, we don't want our canvas to
go away. That's impure because it's a
side effects. Got it. Well,
for anyone who thinks like,
wait, isn't like local storage saving,
isn't that like a synchronous function?
Yes, it's a synchronous
function, but that doesn't make it pure.
Here's like many bad
things that can happen.
Yep. So if we actually go look at this,
save canvas is really simple.
It's a function that you've just like
derived from a DSL called command dot
define. So a command
is it looks like this is basically just a
little helper around an effect.
Yes, it is an effect with a name and
potentially some arguments that are
required for the effect
to run. Okay, got it. So a function that
returns a okay, that makes sense. And
like, I think this is
also an interesting like observation
here. I remember when I
first learned about effects and
like over six years ago. And I was
obviously had much more experience with
react back then compared
to effects. And I like why effect spoke
to me is because I can use it
everywhere can use it on the
back end, I can use it in the frontend.
But in the frontend, I was
pretty clear that it had to
coexist with react somehow. So I wanted
to I need to figure out like, how do I
make those two things
like happily coexist? Who calls whom?
What is the entry point? And like slowly
but surely, I tried to
figure out like some patterns. Over time,
the community also
figured out some patterns. But I
up to today, there's still like not the
one way to do it best. Like
do you have like, who's the
boss is react the boss and just like
calls out to effect ones in a while is
effect the entry point
and like effect is kind of responsible
for like managing react. And
like where do you like I want
to have my effect somewhere but like,
where's the entry point to have one big
one, etc. And so you
know, there's a very elegant
answer here, like commands
are the entry points for like,
this is the thing that like manages the
effects and calls the
effects. And in a very like, I mean,
this is probably was for you a very
delightful moment, I
suppose, when you like realized that
effect the elm concept of a command fits
so smoothly together with effect.
Yep. Yeah, yeah, exactly. That
was kind of the the original
insight. Was that like,
this looks a lot like a command in Elm
and it all it does it
does way more. But it like,
it fit into that box that was
noted to do this right. Yeah.
Yeah, yeah, I'm having a little bit of an
aha moment right here.
Like, I'm glad that we started
with like the more boring parts like
understanding the like the model
understanding the messages.
But now understanding okay, for the
updates, this is where like the the
boring data transformation
happens. But like the in some cases, you
also want the tricky,
effectful things happen. And this
is exactly happening here. Yep, yep,
exactly. So in this case, it's this is
this is a good place to
start because it's really simple. If
people are familiar with
effect, this will this will make
a lot of sense. We have this browser key
value store dependency. I
mean, this is the other great
thing about I think working this way is
like, this just looks this is just
effect, right? There's
nothing like Foldkit special
happening here. This is just effect. And
so by the way, a nice
mascot, you gotta have a fold-kitty.
Oh, that's a good idea. Yeah. And then
yeah, and then we do
we do our store dot set. And then at the
end here, we just return a
message back into the update
function. So in this case, the completed
save canvas, when it
reaches the update function,
I don't think it does anything because we
don't really care that
local storage just saved. But
if this were an HTTP request, we would
get some data here. And
then this is how our data would
flow back into update, we would update
our state. Got it.
Awesome. But what I just like
reflecting on what we've seen so far, I
obviously I'm like predisposed to the
ideas of like separating
events from stage like in the Elm
architecture, etc. I think it's like it's
really like embraced
by many different technologies. Also, if
you like maybe if you use XState
in the past, like a lot
of those like, it's all the same ideas.
But like just absorbing those
concepts now and like seeing
how they're exposed in Foldkit. There's
like, unlike effect,
maybe where I had to like the
first time I was introduced to a
layer it took me quite a
while until I had an intuition
for what a layer is or like how streams
work like in all the
different cases. But what I'm seeing
here, like, I feel already pretty
confident like having an
intuition for how this works
in the various scenarios like
given that I can inherit now my
understanding from an
effect that gives me an understanding of
like how abortion works, or like how
different things can
be composed together. So yeah, this feels
very smooth so far. Cool.
Glad to hear that. So in
terms of other things that I think are
interesting to look at for
this example, I want to touch
briefly on testing, if that's cool. So I
mean, we haven't closed
the loop yet on one thing,
which is probably like the most
straightforward part. Oh, the view, the
view, I totally forgot.
Yeah, exactly. We have something like
data and like, and side
effects, but we got to have some
pixels. So how does that look like? And
this is where we're
introducing like trigger warning,
we're not looking at JSX here. Yeah, it's
not JSX. Okay, so this
is the top level view,
in Foldkit, if you take some model
returns a document, so
this includes the title,
and then also the actual body content,
which you can see here.
Okay, so I feel like this is just
because we're so used to JSX-y things by
now. I want to absorb that a
little bit and then also ask
to better understand your opinions here
and maybe this was a clear
choice for you, maybe this was
also a non-trivial choice for you. But
what we're looking at here,
first of all, it's a view.ts,
not a tsx file. And like what is similar
to a React component is
like basically a function
that takes some stuff and returns, in
this case, a document. So that's
interesting. Is that document
here? Is that the DOM document or is that
like a document coming from Foldkit?
Yeah, that comes from Foldkit and it
represents the title and the body.
So you're basically with Foldkit, you
have a bit of a mapping
to what ultimately becomes DOM. But it's
basically just like you're
returning just a normal object,
the title, I suppose you could return
other things here as
well. And the body, you're now
composing out of those little helper
function, h. h seems to stand
for like a helper that you've
constructed out of a help HTML function
that is parametric over our
messages. So at least on a
type level, which probably helps us to
avoid certain bad
invocations. So I suppose like coming
from React, maybe that takes a little bit
of. Well, as humans, we
don't write code any way
anymore. So and the agent like
immediately adapts to
anything. But just to read it,
this is a little bit of a departure. But
in a way, it's also like,
it's just normal TypeScript.
I think I have an
understanding of like
how it works.
now I'm more curious about what made you
choose this direction, as
opposed to like following what
most people are doing and using JSX.
Yeah, great, great questions. So the
first reason is that
to some extent, Foldkit is part of the
Elm lineage. And you
don't have something like JSX
in Elm, this is how views are
constructed. And I really
grew to like that. And so like,
that's where I started, right? Just like
as a personal
preference beginning, I was like,
I really like the way that this looks. I
like the way that it
composes. I like that everything is
like a function or a list that just feels
natural to me. And
then on top of that,
I think at the type level, supporting JSX
could be really tricky. I
haven't looked super deeply
into it, but this kind of typing where
all of these attributes only
work with your message type
that you provide is probably a pretty
tricky thing to do with
JSX. And I'm not sure it's even
possible. So yeah, no, it doesn't make
sense. And I've been
like often felt held back by
where TypeScript was very
capable and JSX was not.
For example, how you have
with effect, like layers and the
context, how you can basically say like,
this effect requires a key
value store. You forget, you lose all of
that information when you
compose React components,
also like arrow boundaries, et cetera. So
yeah, this makes a lot of sense. So
the sort of like stylistic choice aside,
I'm now curious with how
I should think about like
data flow here. So the header, I suppose,
is like very boring,
doesn't have like any
interesting data things happening to it.
But let's look at something
that's like more reactive. So
how do I get my data? And how should I
think about this? Like, is
there with React and hooks,
the same function component basically
gets recalled all the time
with like the rules of hooks,
which takes quite a bit of like
getting used to and at some point it's
like, you're used to it
and like you embrace it. Is there
something similar happening here? Or how
should I think about
reactivity reactively updating my view
here? Like where does data
come from? When does what get
it? Yeah, good, good question. So this is
made really much simpler
because compared to React, because the
view is just a pure function of the
model. So there's no
there's no life cycle of a particular
view. There's some machinery for
batching messages and
handling renders in a performant way.
But basically on on
animation frame, view is called
with the model. And then the rendering
happens. Okay, and then that's that's
interesting already.
Yeah, so you're you're basically re
rendering the entire app every frame.
With the exception of lazy
or memoized components. Yes.
Interesting. Yeah, okay. So I'm very
curious to learn more about
this. Like on the one hand,
like that's how games work. And that's
fine. Like we have capable devices. And
in a way, it's almost like a good forcing
function to keep
bottlenecks away. Because like if it
happens on every on every
render, you'll notice much more
quickly.
yeah, it's an interesting trade off,
where I hope it affords you
a lot of simplicity. And I think we're
all like so afraid of like, like,
historically that Otis gets
called more often, but it's actually
fine. This react has different
bottlenecks that are much more
noticeable in real react apps compared to
like rendering it all
the time. There's like one
anecdote or like one situation that
really comes to mind.
There's like a very gifted engineer
Cheng Lu. He worked back then at Facebook
on the react team.
He showed me this demo once,
where it was basically a image gallery
and also Hacker News clone
that has like infinite scrolling
he probably built
the largest data set he
could find and like really
tried to build a very, very ambitious
application with us the image, like both
the image gallery as
well as the the Hacker News version,
like he demonstrated
scrolling the Hacker News version,
for example, always had like nested
comments that were all differently sized
the image gallery had
very smooth like animation from the grid
into details, etc. Like
those things were abortable.
And this felt like buttery smooth. So
first, I basically thought, okay,
he's showing me like a
native Mac app, until I realized this was
like a web app. And I've
never seen such a fast and smooth
web app before. Like he really like
showed to me how capable the the web
platform could be. And I've
asked him like, Hey, how did you build
this? And he did the exact same thing. He
basically said like,
I'm basically just re rendering the
entire the entire app on each
animation on each frame. And
the thing that made it fast is by not
having to do all like the crazy machinery
that react gives you.
So there's probably like situations where
one is a better trade off
than the other. But this if he
would have said that to me without giving
me this demo first, I
would have thought he's crazy.
But like having seen the demo, that's
like was the ultimate proof
that this is a very attractive
trade off. So I'm very, very interested
in like seeing how that plays out.
Yeah, yeah, I think it sounds like at
first blush, it sounds like well, if
you're if you're re if
you're re computing the whole view on
every animation frame, then
that sounds really bad for
performance. But I don't think that
that's the case. Like that's the same
thing that Elm does.
They just have a really, really good
V-DOM diffing and patching
solution. And so right now,
actually did just did like a big
performance push. So Foldkit was very
slow, because I just
wasn't thinking about performance.
Because like, why think
about performance when like,
I'm the only person using this and I have
been for the last nine
months and like, my mom knows
about it, you know. But then it got to a
point where it was like, Oh,
wow, like people are people
are using this, they want to use it more.
So let's let's think about
performance. And the main thing
was just getting effect out of the hot
path, just because like on
every render, if you're doing a
bunch of Effect.gen, and you're like
pulling in like, like dispatch, it's
just, it doesn't really
make sense. So just like making all that
as like vanilla and optimized
as possible went a long way.
So right now, if you do the to do MVC
benchmark with like 100 todos
an optimized Foldkit
application is about as fast as a
unoptimized react 19 application. So in
my mind, optimized means
using create lazy to memoize parts parts
of the tree. And in my
mind, that's, that's good enough
for the one production use. I mean, this
is, I think also analogous
to effect here is effect
for like a certain kind of shape program
is effect the fastest way
to run that in JavaScript?
Probably no. But other things matter way
more like, how can you
like really unlock the,
the like IO bottlenecks that you have in
your application? Like, how
can you build a like that?
You did you not like penny wine, pound,
pound foolish here, but
that you actually optimize what
I'm saying. And I think what matters in a
frontend app, sure, you
don't want to have it lag.
But like you want that it gives you the
affordances of a complex and ambitious
frontend app. And I
think this is where thing that actually
matters is like the
complexity, how does the complexity
scale and measure. And I think that's
almost like an
interesting, it's probably hard to
to quantify, like since
like lines of code is
always weird. So I think this
will always be sort of like a mishmash of
like a qualitative metric and a
quantitative metric.
But I think this is why we're here with
effect, we believe there's a
better way. And I definitely
also take that trade off. Yep.
that being said, I
would also like, why not make
Foldkit faster eventually? Oh, yeah, for
sure. Yeah, that's just
yeah, that's not the bottleneck
to anyone using it right now. Exactly.
And I think this was maybe
that was the starting point for
like other more like modern takes on what
a frontend framework is.
And I think it's also like very
interesting. And if you build maybe a new
chat app that has like millions of
messages, maybe that
matters more. But I think for like a good
catch all default for like many apps
where someone is like
effect pill to begin with, I think this
is a very interesting starting point. So
I think I got a good
understanding now of like the basics of
Foldit, maybe we can,
unless there's like a thing in the
app that you that you wanted to show
last. I'm sure there's like ways how to
integrate with other
great bells and whistles off of effect,
whether it's like streams
and layers, etc. But maybe we
can zoom out a little bit and hear more
about like your path ahead of like
where are you hoping to take
Foldkit over the next few
years? You've mentioned that your
mom knows about it. That's great. Like
through this podcast
a lot more folks find out
about it. Get to use it. What are you
currently looking for? Are you looking
for people like using
it giving you feedback? Are you looking
for people who actually maybe want to
join you building Foldkit
like become contributors and
maintainers? Are you looking for people
who build ecosystem packages?
Let's talk a bit about the future.
Good question. So over the past month or
so, I've been really surprised by how
much interest there has been in Foldkit
And a lot of this
originated with, well,
I'm
Teej, do you know on X?
they posted
about it. And that was the first,
like, it kind of caused a little bit of a
wave of interest. And then
the, I went on effect office
hours a couple of weeks ago. That was
another little wave. And
I'm here. And honestly, like I
wasn't sure if anyone was going to care
about this project or be
interested. I just wanted it to
exist because I like really like effect
and I like that I feel like
there's a gap here. And so
I'm, I just feel like at this moment,
very like grateful
that there's any interest.
In terms of like where this might go or
like what the future looks like,
I'm really just focused on getting to a
place where I feel
really confident saying like,
this is version one of Foldkit. And I
think it's pretty close. Like, I mean,
there's a lot of stuff
we haven't talked about. There's like,
there's Foldkit UI,
there's story and scene testing in
Foldkit, which is I think, probably one
of the coolest things about the
framework, honestly.
There's like how it works with AI, like
over MCP, how just agents
work with Foldkit in general.
And so like all those pieces are in
place, but I'm focused
on filling in various gaps
before I feel like, okay, this gets the
V1 stamp. And then beyond that, it's
really just about like
continuing that iterative cycle. I don't
feel like I know,
like, oh, a year from now,
this is where I hope the framework is. I
don't have any like major
expectations, but I think also
like the effect community is awesome.
Like people are like
insanely smart and like,
want to be helpful and are like always
building things. And like,
I feel like I'm kind of just
like a part of that and trying to
contribute and also like
riding that wave to some extent.
Yeah, I mean, honestly, like that's my
take right now. And yeah.
That was wonderful.
I think there's like
enough material to do a bunch of
follow up episodes. Just scrolling
through the docs sidebar gives you a
taste. Like we've spent
most time now on the basics getting an
intuition for Foldkit. But there's like
so many cool things.
Like sure, we've looked at the DOM
renderer, but you seem to have support
for custom elements,
which I feel like is a heavily under
explored area of the web. Like even if
you would have just said
my take on Foldkit is like not the data
architecture, not
effect, but like I'm going
to take a new step of like custom
elements or like web components as they
were called in the past.
I feel like that alone is also like very
much worthwhile exploring
seems like Foldkit works
with that you have a canvas render, which
is like super cool. I have
this was one of the many areas
you have to completely opt out of React.
And there's like the canvas
can do so many interesting
things. There's an amazing project called
React Glide Data Grid, I
think, which I'm using heavily.
It's like basically a React data
component, like a data grid table
component with like infinite
rendering, etc. It's like crazy fast
built by an amazing
engineer, Jason at Glide.
And there's like one in my opinion, like
the best like data table
component in React. And like the
reason why it's so fast is because it's
like embraces the canvas.
And like you seem to with
Foldkit like just like allow those
things to like interweave with each
other. That's like an
emergent property of like flipping from
view first to data first. And like the
canvas doesn't matter
whether the model gets materialized into
like rendered as like little like
rectangles or lines,
or whether some like DOM is re-rendered.
So that is super cool. And
then like another thing that
stood out to me is like, you have
basically the frontend
complement to a lot of like
concepts that make effect great, like you
have, you can take
basically the error from your
application and render it etc. So all of
that, even though I
haven't put on that glove yet,
it seems like it might fit like a glove.
So I'm very much looking
forward to getting my hands on
that. And what you've said about the
effect community
means a lot to me as well,
because I have in 2020, when I was one of
the first people like to
get involved with effect,
like one of the biggest downside at that
point was like there was
like absolutely no community,
there was like no ecosystem, etc. And
like it
had the right ideas. But like
everything that the React ecosystem had
going for it and all of those other
ecosystems, there was
just like a void in effect. And that was
kind of very daring. And
now we have one of the best
communities there is like a really rich
ecosystem Foldkit as an
amazing, like very sizable
contribution to that ecosystem is just
like what makes me and so
many other people very excited
about effect. So thank you so much for
like all of like the love
and energy and like countless
efforts you're putting into Foldkit as
someone who's building
similar, similarly sized projects
in the past. And so I think one of the
most important things is
like having enough energy
to keep going. So I wish you that for the
future. And I'm really,
really excited to get my own hands
on Foldkit and giving it a try and
looking forward to having you back soon.
Thanks. Yeah, but really warms my heart.
Really appreciate it.
Awesome. Hey, Devin, thank
you so much. This was great.
Yeah, thanks.
Thank you for listening to the
Cause & Effect Podcast.
If you've enjoyed this episode, please
subscribe, leave a review
and share it with your friends.
If you haven't done so already, you can
join our Discord community.
And if you have any questions, feedback
or suggestions about this episode or
about Effect in general,
don't hesitate to get in touch.
See you in the next episode.