[Music]
Hey, welcome back to another episode of Svelte Radio.
It's that time of the week again where we talk to you about Svelte.
That was a really weird intro.
I'm joined by my co-hosts, Brittany and Anthony.
Hello.
Hey, what's up?
What have you been up to?
Nothing.
We're quiet this week.
Yeah, very, very quiet.
Anthony in particular, just staring up at the ceiling.
It's more like, you ask me what's up, I'm looking, just checking.
I mean, nothing, obviously.
Terrible joke.
I know, but I'm allowed now because I'm a dad and it's a dad joke.
But no, I mean, it's been a tough week, actually.
It's been a really tough week, so maybe I'm just exhausted.
I'm not sure.
But yeah, it's all go again now.
It's all go.
Yeah.
All right.
Cool, cool.
That's good.
Glad to have you back.
[Laughter]
All right.
So today we are joined by another guest.
It's Thomas G. Lopez.
Welcome.
Thank you.
So you are the creator of a pretty popular UI library in the Svelte ecosystem, right?
It's called MeltUI, hence the title, Melting UIs.
And I cannot also see now that I've misspelled your name in the title.
Sorry about that.
[Laughter]
That's fine.
So, Thomas, you recently became a Svelte ambassador as well, right?
Yeah.
I'm so happy about it.
I was so surprised.
[Laughter]
I was rooting for it.
I actually was talking to Hunter, who is also a Svelte ambassador for a long time.
Like, oh, I would love to be a Svelte ambassador and stuff like that.
But yeah.
And then it just popped in.
Oh, that's so awesome.
Yeah.
We're so glad to have you.
You've added such great contributions to the community.
Yeah.
Thank you.
Let's talk a bit about MeltUI.
And maybe, actually, before we do that, why don't you introduce yourself?
What do you do?
Are you a software developer?
Yeah.
Probably.
Why are you here?
Why are you on the podcast?
I just popped in here and they let me.
I found the link.
It's like the same as ambassadors, right?
Just find the link and there you go.
Exactly.
I just got an invite link, a secret one.
So yeah, my name is Thomas.
I'm a front-end developer working at AppWrite.
I've been coding for a while now, seven years maybe.
But my front-end experience only started in college when I was more or less 18 years.
And yeah, I've been coding with Spelt for a while now, but it only became my full stack
for everything, like for work and hobby projects too when I joined AppWrite.
But I already was doing hobby projects with Spelt before that.
I've always been keen on it.
I even wrote a portfolio with separate ones.
Wow.
So yeah.
How did you find Spelt?
Did you originally use some other framework?
Yeah, my first framework was Vue, but then for work reasons, I moved on to React.
But then I think maybe looking at Stack Overflow surveys or a Fireship video, or I don't know.
Spelt is always the popular kid in the block, right?
Everyone loves to talk about Spelt.
So I think I just tried it out once and I really, really liked it.
Awesome.
Now, I was just saying that you wrote the hype wave.
I think it's interesting because yeah, Spelt gets a lot of mentions, doesn't it?
I think I see it mentioned a lot.
And then I always thought it was unpopular.
Like it wasn't...
No one really used it.
Then one day, suddenly everyone mentions it at every opportunity, which is weird.
Yeah, it really gets the fame of the popular, beloved framework.
Kind of like Rust is the loved language.
I'm not sure nowadays, but Spelt is like the loved framework for JavaScript ecosystem.
Yeah, I think a few people got it from different avenues.
I heard it from Syntax, listening to Syntax and Scott talking about it all the time.
And then the surveys kind of picked it up and then the developers started using it and liking it.
And so each survey had it popular and then that brought in more people.
And so we have different waves of people coming in.
But it's interesting how people found it.
I was actually going to mention that about the waves thing.
I feel like you had a couple of people, like the very early adopters, like probably Empathy.
You were probably a very early adopter using Spelt 2.
Spelt 1.
Spelt 1, even.
Oh my goodness.
What did that even look like?
Nobody knows because it's gone in the ether.
Double braces everywhere.
It might have been Spelt pre-1, to be honest.
I can't remember what it was, but it was lots of double braces.
It looked kind of like Spelt 2.
What was Spelt called before it was Spelt?
Ractive, was it?
It was Ractive, which was different to Spelt.
It was Rich Harris, I guess, just exploring reactivity within a framework.
And then I think it got launched around the same time as React first came out.
And React got that popular momentum behind it, I guess because of Facebook.
And so even though it had some great ideas, it kind of disappeared into oblivion, really.
And then Spelt was like, "Okay, but what if we did this?"
And the API became a bit more honed.
It looked a lot like Vue back in the day.
Vue was already there as prior art.
So it intentionally looked a lot like Vue because Vue had some good ideas.
And that's when that...
So Spelt then got popularity.
Around the point of 3, really.
But 2 as well, yeah, 10 out of 2.
That's when I started using it, for sure.
I remember the Spelt 3 Hacker News post.
That's probably how I found it.
Really? Wow.
Yeah.
In my head, that's the first wave, but it's probably the second, in a sense.
I feel like it trickled in before that.
And then you got the Spelt 3 release because it changed so much,
and it was so much better developer experience-wise, right?
There's also the "Thinking Reactivity" video,
which showcases a lot of Spelt 3 syntax,
which actually pulled me back in.
I had tried Spelt, used it a little bit,
but pulled back in to React because of work and stuff like that.
But one day I saw that video and I was like,
"I really should use it again."
Yeah.
The funny thing is, Rich Harris actually comments about a company,
a Brazilian company called Stone, which used Spelt internally.
And I worked there and I didn't know about that.
It was actually, they used it, it powers the handheld things when you scan your...
The POS.
Yeah.
Yeah, yeah.
It powers those, crazy. Just because it was low overheads.
Do you know the funny thing, though,
is they had that insight to use something more performance for their POS machines,
but then they were still using React Native
that embed web views for their mobile apps with low 3G coverage and stuff like that.
Sounds like a lot of people didn't enjoy that experience,
like with bad connections and stuff.
Exactly. I'm not sure how it is today.
It's been a while since I've been there. Maybe it's changed since then.
Yeah, I think the guy who did it at Stone, I think he left.
So maybe the same impetus wasn't there to roll out Spelt
and everything else as well. I don't know.
Yeah, but it's a really big company.
It was like when I worked there was like 5,000 people or something like that.
Wow.
So to roll out that company-wide, it takes some time, right?
Yeah, absolutely. Absolutely. Yeah.
And then after the Spelt 3 wave, we had the, I think, Spelt Kit was probably next,
but that took a couple of years probably before we got that next infusion of people.
Well, it got announced, didn't it?
And then it took two years to get it out.
I guess Spelt Kit was two waves then, the announcement and the release.
Yeah, maybe two waves.
What's important about Spelt Kit too is like, at least for me,
when launch was like, "Okay, now I can actually use Spelt Kit and Spelt in general in production."
Because of course you could use Spelt.
And since everyone was doing server-side rendering and stuff like that,
it would be really weird if you didn't use it.
It would also be weird if you use something that's not ready for release, like 1.0.
So when Spelt Kit launched, it was like, "Okay, Spelt is now ready."
Yeah, I think the wave of Spelt was, you say it got popular around 3,
and I think the video helped.
But I think also, for me, when you were writing Spelt 2, because it had that embedded...
Like you exported a graph by the component, like a hash with stuff in it,
like computed block and things, and it made you have to do a lot of gymnastics
in order to get variables to other parts of the object or part of the component.
So I think that put people off generally.
The same reason view changed in the end.
And it was the kind of hooks idea that came from React that made Rich and others think,
"Well, hang on, why don't we just put state at the top level?"
And at that point, it makes more sense because if it's the top level,
it's not embedded in an object.
It means you can access it as you would any global variable.
And I think that was a massive shift.
Then everything became simpler.
And people again didn't like it because it was less obvious what was React
and what wasn't, what was computed and what wasn't.
But when they realized, it's like, "Oh yeah, that's much better."
Yeah. And then of course, the latest thing, Runes.
Runes.
Which we'll probably talk a bit about today, but probably more towards the second half.
But yeah, let's get into what you've been working on, Thomas.
So I think the first time I saw one of your projects was when you submitted
the Radix Svelte package to the hackathon last year, this year.
Earlier this year.
This year, yeah.
Yeah. Time doesn't fly, I guess.
So what was that? What was Radix Svelte?
So Radix Svelte came from a popular React project called Radix UI,
which is a headless library.
For those of you who aren't familiar with what headless means,
it's just like components that don't come with their own markup or styling.
Meaning they are completely customizable.
So it's a way to be wrapped into your product,
like completely into your own design system.
It was something I was really missing in the Svelte ecosystem.
Like there were some libraries that were headless,
but they either were missing some components or too much activity to maintain,
or they just didn't have that DX or the features that Radix had.
So I tried to port it to Svelte. That's what Radix Svelte was.
Don't remember the exact, like which spot you got on,
but you did win some prize, right?
Yeah, I think I went and got fourth place, if I'm not mistaken, for best library.
But you've since abandoned Radix Svelte, right?
Well, that might be a bit harsh, but so you started working...
That broke my heart.
But you started working on something that I hopefully think,
hopefully you think it's better, the new project?
Oh yeah, for sure.
So then I started working on MeltUI.
It was actually a bit funny, just for a bit of context.
Radix Svelte came out, and then Shaxi and Svelte also came out.
Hunter talked with me, he came up with that product,
which is also a port from the existing best product.
It's Radix UI, but we built styles with the old ones.
You can modify them, but it's easier to get started with, basically.
And then I talked to Hunter, like, "Hey, I don't think Radix Svelte is working out too much."
It's when I started MeltUI, yeah.
What kind of issues did you run into?
Basically, working... How can I explain this?
There were some limitations with the way I was doing things, like component-wise,
that made it a bit harder to style and customize the components.
One of them is due to how you style components in Svelte.
For example, let's say you want to style a component in Svelte.
So we have scope styles, that's how you would style elements.
But to pass in scope styles to a child component, you can't do that.
You can, using wrappers and compacts and stuff like that,
but you would have to use a global selector.
And I get why it's done.
It's a well-designed limitation, but it's a limitation nonetheless,
and I wanted to make something really customizable.
So there was that, and there was also another thing.
Radix allows you to change the element that's actually rendered.
So let's say you have a tab button, and you want to change it.
I don't want it to be a button, I want it to be an anchor tag.
With Radix, you just put the original Radix, you just put the prop as child.
Then whatever you pass in that component is what's going to be actually rendered.
But to do that in Svelte, it's a little bit less ergonomic.
You would have to pass in slot props and stuff like that, and actions.
It would be a little bit too much.
And I felt like I was battling against Svelte framework.
I was just copying what Radix had done in React, using components,
and I was battling against what Svelte was made to do.
Melt gets a different approach.
Instead of shipping components, we should put what I call builders.
Builders are just a function, and they return for each element
that a component is structured into, a store and an action.
So that's a little bit more understandable.
Let's say you have tabs.
Attach components, so you have a bunch of buttons,
and the content associated to a button.
Tab one, content one. Button two, content two, and so on and so forth.
So we would ship a button store and a content store,
and also a button action and a content action.
The store contains the attributes.
The action contains any interactivity, any scripting, any event listeners.
And you just attach that to an element. Why?
Just so I can now, since I'm working with elements and not components,
I can do whatever I want with them.
I can style them using scope styles.
I can change what element I want to use.
It's much more flexible doing it that way.
And I can create my own components with my builders,
and then now it's component builders.
It's more direct interactivity with the DOM
rather than having that component scoping with the Svelte markup, right?
Exactly.
And, well, use the platform.
Yeah. And if anybody wants more detail on any of that,
I had Thomas on the Sirens stream,
and he showed how Radix worked and then how MeltUI works.
So if you want to actually see any of that, go through the steps.
It's on YouTube on the Sirens MeltUI stream.
Yeah. I also did a presentation-- sorry.
I also did a presentation on Svelte London,
where I created a builder from scratch
without importing any dependencies and stuff like that,
only using Svelte to see how a really simple builder can be done.
It's not that complex at all.
It actually made it easier to ship out new builders
than it was creating new components in Radix Svelte.
Does this mean that Svelte doesn't know about the DOM updates that have happened
because you're manipulating the DOM directly, or am I misunderstood?
I mean, they kind of-- since I'm using Svelte Actions,
they still kind of know--
yeah, they kind of still know about the DOM updates and stuff like that.
I'm still using-- Melt is still dependent on Svelte stuff.
So I even use lifecycle methods, which I want to remove,
but I use unmount and undestroy and all that stuff too on the components.
Why I want to remove them is just because--
so you can call the builders outside the component if you want.
Right.
But yeah.
Like when it's created, it's using the actual Svelte stores in Action,
so Svelte is still tracking that stuff.
It's just directly interacting with the DOM through Svelte.
And I kind of need to use--
like when I pass in a store to a component,
I'm not just getting the reference to the component or something like that.
I'm spreading the store value with that dollar syntax and whatnot.
Right.
So yeah.
Which is-- actually, it's an interesting thing.
Before, Melt was using--
I really didn't want to have to pass in spread attributes and an action.
Like, they are two separate things.
So at first, I did this really hacky thing
where I would just pass in the store.
I would pass in an ID or some reference.
And then internally, I would use that ID to document.
That's very selective.
And then use the event listeners and stuff like that,
using tick, Svelte tick, and stuff like that
to make sure the element was created before.
It was really hacky.
And eventually, I found a bug where basically,
you sometimes wouldn't get the reference to the element
or the events wouldn't be attached.
They would always have to be reattached.
So if you ran it in bytest, you'd have to use sleep
every time something changed.
You would have to wait for milliseconds.
I was like, yeah, this is not working.
Let's use actions.
Yeah. Actions are nice. I really like them.
So what kind of features can one expect from one of these builders?
So I'm looking at the website here, and you have a ton of builders.
So you have an accordion, an avatar, checkbox.
Why would you use a builder for a checkbox
rather than just an input regular HTML element, for example?
A lot of the builders replicate, as you said, normal HTML elements.
But the thing is, HTML elements are notoriously hard to style,
some of them.
For example, a select.
A select is one of the most requested things in a headless library,
especially because you can't currently style a select really well.
You can style the box, but you can style the options themselves.
So with Melt, well, they have the same functionality
as a normal select mostly, but now you can style them.
But it's not only that.
You could try and build a select yourself, which is styleable.
The thing is, it's missing a lot of accessibility concerns,
which are not easy to build out from scratch,
and keyboard navigation and all that.
I have a question about native selects.
How do these translate to different platforms?
If you're using them on iOS or a mobile device,
how does that select box...
Does it just look the same as you've styled it?
Or like a date picker, for example,
if you used a date picker, does that use the native date picker?
How can you get around that stuff?
It depends. You can change it yourself if you want.
For example, what you could do, since Melt is really flexible,
is let's say that, okay, in desktop,
I want to use the native select-- not the native select, sorry.
I want to use Melt Select Style on my own, right?
But on mobile, so that the select doesn't overflow the screen,
even though we do have helpers for that.
Or, I don't know, you really like iOS's and Android's native select options,
well, you can change that.
You could do-- With CSS selectors, you could just change
what is being rendered. You could also just not apply the melt action
when a certain breakpoint is being passed.
That's something you could do.
But the benefits, too, of using actual divs and stuff like that
rather than selects is sometimes some of the--
Even styling just the select box between different browsers
and operating systems is a bit hard.
They use different properties. Some properties don't work
in a certain browser and stuff like that.
While styling a div is really easy, right?
Styling a div and making it look the same
in different operating systems and stuff like that is much easier.
I say a div, but it could be any element.
Would that be a CSS selector from Melt,
or would that be an if block in your spelt markup
to use a native select box?
Can Melt actually style a native select box?
I guess that's where I'm asking, is it a native select, or is it divs?
No, normally we use-- For a select, it's a button,
and then the menu itself, the options, are just divs.
But the actual clickable options should be a button,
but you can use a div if you want.
I think you would have to do an if mobile something
in the spelt markup for that.
Yeah, or you could also just use CSS selectors,
like use display none after a certain breakpoint
or something like that.
You don't need to use ifs to detect the size.
That's why it's even more progressive enhancement friendly.
It's something I actually want to do too,
progressive enhancement examples,
meaning I do something like if browser,
like if JavaScript is enabled,
then I show the Melt UI component.
Otherwise, I just use the native select.
That's something you could do.
I feel like you could use the action for that,
and just attach the action to the outermost.
So an example of select you would have,
I don't remember the syntax off the top of my head,
but it's a select, and then there's options inside.
Yeah.
Yeah, option element, right?
So you would put the action on the actual select one,
and then you would just replace that with whatever.
Yeah, we could do that.
We do some similar stuff, for example, in avatar.
You have an avatar component, which has a fallback,
and whenever the image is loaded, we just hide the fallback.
Yeah, we could do that, actually.
It's a good idea.
Because then it would work even if JavaScript was disabled, right?
You would still have the select kind of thing there.
Yeah, we would just require you to actually create a select element
in your markup and stuff like that, and duplicate the options,
because the way options work in Meld, it's a little bit different.
We don't use the native option element, right?
You would have to duplicate markup a little bit, which is the downside.
Yeah, that's also a downside if you do it the other way.
If you did the if mobile in the markup,
you would also have to duplicate markup.
Exactly.
It's the same.
Exactly.
Yeah, I really enjoy progressive enhancement and SSR stuff,
doing stuff without JavaScript.
It's very exciting to me.
And it's one of the things that breaks my heart working in Meld,
because I know that all of them require JavaScript,
and I really, really do like progressive enhancement, too.
I love doing experiments with it.
I did a Reddit poll, which is fully non-JavaScript-friendly.
It works fully with the server.
So it breaks my heart a little bit, but I do want to address that at some point.
It's sad to me that a lot of the elements that we have to create
need JavaScript to make them fully accessible,
but we are getting there with HTML elements.
They've added a lot of HTML elements,
and Open UI is doing a lot to come and add more elements
that are actually native to the browser that are fully accessible, too.
Yeah, I'm pretty excited about the popover API, the select list.
I don't remember what--
Yeah, I was just going to mention it.
Yeah. Some really exciting stuff is coming up.
There's dialogue now.
We have lots of things that we didn't have just a couple years ago.
There's a search element as well.
There's a search element?
Did you say "search"?
I did, yeah.
Isn't input "search"? Hasn't that been around?
Like a combo box?
No, so it's really just a semantic element.
It doesn't really do anything.
It just tells the browser that this is for search.
But would it be input "search"?
But it just is a search?
No, it's just search.
What is it?
It's just an element.
But inside of that, you would put a form and stuff.
I guess it means you can interact with Control-K or Command-K or whatever.
So you would have to put a form and then a search and then an input?
I don't remember the exact order of things.
I'm going to have to look that up after this
because I have to make a global search bar.
It's very simple.
That's something I want to do, Mel.
I was going to say that the reason these things are exciting is because they're boring.
If that makes sense.
It's great. I think it's great.
This stuff is not boring to me.
This is literally my entire day.
I could just talk about this all day.
I mean boring in terms of something that is not fancy rather than not interesting.
Yes.
Yeah.
That's true.
It's really an infrastructure thing, a really low-level thing.
And there's lots of different ways to do this stuff.
And so it's kind of complex problems that you have to figure out what's the best way,
what's the best API, what's the most developer-friendly.
It's really kind of difficult to figure out what's going to be the most...
I guess the best DX and then also be the most performant.
And just the nicest to work with.
It avoids reinventing the wheel and it avoids bike shedding, I think.
And that's two massive points of value for me.
Imagine how many hours people have spent building these things over and over and over and over again.
Just because it doesn't exist.
There's Redix UI, Zed, Melt, React, Aria, AriaKit. I can go on.
That is literally the point of Open UI.
That's what they're trying to solve is they're building components for the web
so that people don't have to keep doing these design systems over and over and over again.
So you have native elements that you can just use and style how you want.
And they are headless, so you can just style them to your heart's desire.
But you have accessible native elements that just work and are styleable.
Yeah. The thing is, the only bad part of the web in general is things on the web that are native need to be backwards compatible.
So if, I don't know, someone shipped a dialogue element and said, "Oops, maybe this shouldn't be that way."
It is now. So there will always be stuff on top of it.
But yeah, of course, having native elements there that are much easier than, "Hey, you need to install a packet and you need to learn how to use it."
And maybe it gets abandoned or something like that.
It's obviously easier, and I think Open UI is a fantastic thing.
I would much rather have all of these as native elements so that I wouldn't have to create Melt.
And I think there's always going to be other UI libraries because people want choices for styles.
And they want easy components to bring in and style their own thing.
So there's always going to be a million of those.
But to have the native elements without the JavaScript is the goal.
For sure. Of course. Yeah.
If we had everything working natively, we would maybe have 10 million different style libraries.
Yeah. I agree.
Instead of me doing Melt as a handless library, I would do a styled library instead.
You would be helping Hunter with ShadCN or making more styles for ShadCN.
Exactly. I do like my CSS.
Speaking of ShadCN, that uses Melt UI, right? Under the hood?
Yeah, no, it does. You choose Stratix, but then it's refactored to use Melt.
Maybe we should specify ShadCN's spelt because ShadCN started as React library and that's by Vercel,
but ShadCN's spelt is not directly affiliated with that.
And I know this is a spelt radio podcast, but we should specify that just to clarify.
It's very easy to get people to like, "You said this!"
But then take it completely out of context.
Yeah. Classic.
But yeah, ShadCN is built with Melt UI.
And when I started Melt UI, I thought, "Hey, I want to do another thing,
but I still want ShadCN's spelt to work out,
so I'm going to try and have all the components Redix spelt into Melt."
It's still not a thing, but almost all of the components that you have in Redix,
you'll have in Melt. They're still missing two or three, I don't know.
So you two are just collaborating and working together,
building both libraries to help build onto the other one, essentially.
Exactly. I'm not working too much on ShadCN's spelt.
Mostly sometimes I'll enter XMES for some feedback or something like that.
But yeah, in Melt UI, he contributes a lot.
He's been working a lot on the date picker, which is super hard.
Yeah.
Because time zones, locales, accessibility.
He gets the really frustrating components.
He worked on almost all of the menu components too.
And I'm just there doing tabs, which I love.
[laughter]
Yeah.
I call it a little box.
I feel like Anthony has issues with the time zones.
I do. I have issues with many things, time zones and date pickers and everything else.
We built our own a long time ago,
and we're now slowly replacing it with a native date component.
To be fair, we built it because I think Safari had a 13-year-old bug
where the date picker wouldn't render.
It's just 13 years.
Just 13 years.
Oh my goodness. Did Jim Simmons finally get it fixed?
I believe it got fixed. Yeah.
I think it probably was that emphasis from her.
But yeah, so now we can go back to using native once again and be happy.
As long as they don't break it again.
I swear, as soon as they hired her, Safari just took off like a rabbit with everything.
Like a flying turd.
Yeah, Mozilla needs to hire someone for Firefox because, like I said, I love Firefox.
I know.
I still use it. I'm using it now, in fact.
Yeah.
I'm now back to it.
That TreeTab extension.
If TreeStyleTabs doesn't work, try PanoramaGroup.
It's cool, too.
I just wish it would collapse.
That's the only thing I wish it would do, is collapse and expand.
Then TreeStyleTabs works for you.
Okay.
Do you have a workflow that you use to follow, like,
if you're watching ShadCN libraries for updates,
do you have a workflow for watching updates on that library?
And when updates happen, how do you track that?
So, to be honest, like, Melt is more concerned with the Redix UI side of things,
and they don't add components as frequently.
They are working on the farm components as a better, but, yeah,
they do things a little bit more slowly.
They actually are focusing a lot on Redix teams,
which is kind of like Redix patente as well.
Yeah.
So it's not something that concerns me too much in that sense.
Yeah, because it's the other way.
Yeah, and ShadCN itself sometimes, yeah,
they have some components that are not in Redix.
They created their own ones.
For example, the combo box one.
ShadCN itself has an autocomplete component,
but Redix doesn't have an autocomplete one.
And the way that ShadCN, the original one, has the autocomplete,
it's different, actually.
Normally a combo box has inputs, and when you click on that input,
it opens a bunch of options.
So a mix between a select.
You write it, and the options get filtered.
The way ShadCN works, it's not that way.
It's a button which opens a menu that has an input and the options.
So the input is actually contained in the menu, which is weird.
Yeah.
Yeah, it's different.
It's actually pretty.
It's really pretty.
But if you look at the Y-Aria examples and patterns for combo box--
Are filters at work?
I think that's how they work.
We have an accordion that comes down, and then we have a search input,
and then it filters a list.
That's fine.
I think that's fine.
I think that's fine, probably.
[LAUGHTER]
But normally--
Sounds confident.
Even though I'm doing accessible library, I'm still learning.
Accessibility is really hard and nuanced, and there are thousands of people
who know much more about accessibility than I do.
I'm really actually looking forward to a course by Sarah,
and I don't know how to pronounce her last name.
Oh, Sudan.
Yeah, exactly.
And she's working on an accessibility course that's going to go out this month.
I'm really hyped for it because I really want to grab it.
People who are doing--
I think it's on early preview for some people,
and they're saying really good stuff about it.
But yeah, I'm just trying my best to learn accessibility stuff
because it's hard.
Even though there are conventions, sometimes conventions aren't super
well-defined in some places, too.
There's nuance.
It's not like a strict science.
I'm going to shout out Ben Myers, too.
I'm actually wearing one of his shirts, HTML shirt,
but he's also big into accessibility.
He works for Microsoft on the accessibility team there
and puts out a lot of good content on accessibility.
Yeah, there are a lot of really good accessibility content creators
who write tons of articles.
Some components which look simple are really hard to build
and think about, like, two tips.
Yeah, yeah, yeah.
I mean, accessibility is not easy.
So the course is called Practical Accessibility.
Exactly.
It's going to be linked in the show notes.
All right, let's talk a bit about these new magical things
that are coming in Svelte 5.
Runes.
Runes, yeah.
Nice.
So you're pretty excited about Runes, right?
Yeah.
It simplifies your work immensely.
So much that he could not take his vacation.
Like, he was on vacation talking in the threads.
One day I was like, Thomas,
there's a beautiful landscape, stop looking at this card, focus.
But then I was at the hotel,
I need to write a Twitter thread about why Runes are great.
I mean, I'm at the hotel at night, it's fine.
Yeah, that's true.
You can't see anything outside if it's dark.
Exactly, exactly.
What is it with Runes that are particularly exciting for you?
Maybe actually we could give a short intro to Runes.
Does anyone want to give it a try?
What are Runes?
Runes are magical symbols that are going to increase
the developer experience and fine-grained reactivity of Svelte.
Touchupd, is that you?
[laughter]
No, I did not type anything.
I'm kidding, I'm joking.
Do we want to know what the actual Runes are?
Certainly.
Runes are compiler hints, right, for Svelte,
so that Svelte can figure out what should be and shouldn't be reactive.
They also work in JavaScript and TypeScript files.
They're not just for the compiler, right?
Yeah, and they're kind of compiler markers.
They're not even methods that you import or anything.
There was a discussion about this exact topic today,
which is why I was waiting for everybody else to kind of say
what they were first.
But I think, yeah, basically that's it.
The best description probably is a compiler symbol.
There's another library that wants to use the same word
for a slightly different concept, and I'm wondering,
like, is it the right thing to do?
Is it not the right thing to do?
But, yeah, so we'll see how that pans out.
Signals?
Well, so signals are different again, aren't they?
Signals are under the hood now.
So signals are something that the browser has,
or browser supports, I think.
Oh, does it?
Not yet. Not yet.
Not yet.
So it's not yet native, but it's kind of planned,
like it's a potential upcoming thing.
Are the signals also coming as a browser API,
or only observables?
I think I said, I read somewhere on Twitter,
that there were library maintainers talking about signals.
Because Twitter is the source of truth.
Well, I mean, these people...
You give them a high...
I know.
Reliability score, or whatever you call it.
Just giving you crap.
Yeah.
It did sound kind of sketchy, right?
Oh, I read on Twitter.
Yeah.
But if you said, "Oh, no, Rich Harris tweeted about it,"
okay, that's more credible.
Yeah, I don't remember who it was.
I don't remember who it was, but yeah.
And they have loads of numbers of the name.
Yeah.
I think one thing that I've seen a lot in...
So there's a runes channel on the Svelte Discord now,
and I see it a lot.
And people think that the runes are functions.
They just look like functions, but they're not.
Which is, I guess,
it's not super clear that they're not functions.
I wonder if there was some other way to make it clearer.
At the same time, like, Svelte already...
Svelte has a delicate compromise between
it needs to be valid JavaScript syntax because of tooling,
but at the same time, we want this to mean something else.
For example, you would have $2.something,
like a variable equals something.
That actually translates to a let assignment
and then a reactive statement, right?
Something like that.
The difference here is, though, that no one uses labels.
Everyone uses functions, is what I would say.
I agree. I agree.
I'm not the kind of person that needs to know
what everything is doing under the hood,
so it's not a function under the hood.
I guess I assumed it was, too,
because you're passing in an argument,
and it looks like a function.
Not in the derived one, right?
I don't think you pass in a function there.
I don't keep up with all of this stuff.
No, you derive your pass in an expression
and in fact, you pass in a function.
The curious thing, too, is that since they look like functions,
with TypeScript tooling, you can also do things
that are normally restricted to functions.
For example, in TypeScript, you could do
const count equals double, which is a function,
and pass in a parameter.
But you can also pass in a generic, right?
Double is not the best function to pass in a generic.
But you could do double, then that generic symbol,
which I don't know the name, which looks like arrows.
And you can also assume that with rooms,
you will also be able to do that, like state,
and then pass in something like a door,
like an inside derived to say what the type of it is, I think.
I may be totally wrong.
But in props, you will be able, I think.
Isn't props up in the air?
They've talked a lot about props
and what they're going to do with it,
if it's going to happen or not,
but it would be a big DX lift for the way props
are currently handled because of how we have to do,
especially in component libraries, how we have to do
spread props and rest props.
Yeah, I was actually talking with the other ambassadors
the other day about this.
I was doing a component where I had to type props somewhere,
and then I already had typed them,
and then I have to explicitly declare off them.
And in those cases, the DX is massively improved.
But I can also see where in some other cases,
it's not so much massively improved.
Sometimes you don't need to do that.
Sometimes you just want the type to be automatically
inferred by an assignment or something like that.
And now it's not going to be the case with the props room.
So it's a delicate balance.
I had a thought in your case.
Could you not do a one-line export and commas
and just an equal to your whole type instead of...
Like export-led props, right? Something like that.
Well, export and then you have to do them separately.
But you do it as one big object instead of export-led
and the whole list of them.
That works?
Yeah.
To the alert.
I'm going to have to look into this.
Because Red Expel was written like that too.
A bunch of export-leds, just a big list of export-leds.
Oh, yeah. And it gets really annoying when you've got a lot of them.
And if they've got default values, you can do them in line like that too
in the commas, but that is kind of hard to read.
So some of those I would pull out.
But if there's just no default value, I would just put them in an object at the end.
Damn, I really didn't know about this.
I feel like a fool, especially because I did do export with object syntax
for like class, class name, right? Export class name as class.
Huh, okay. I'll have to look into that.
What room are you most excited about for Melt UI?
I would say actually, I won't say there's a specific room, to be honest.
I'm just excited about it as a whole because of what it brings.
For example, one frustration that comes up with Melt a lot,
not as a consumer of Melt, not as a creator,
is passing down stores or something like that.
In Svelte, let's say you have an object and you have stores inside that object,
which is my case.
I have the const dialog equals createDialog, and have dialog.elements.roots.
Let's say I want to pass that in to an element.
So, dot, dot, dot, dialog.elements.$root.
Oh, that doesn't work. That doesn't work.
You have to remove the root from there and do const root equals dialog.elements.root,
and then you can spread it.
With rooms, no, you just do dialog.elements.root.
I would change the syntax so it's more concise.
But yeah, you can just pop it in.
So that's one thing I'm really excited about.
I'm also excited about -- this is not Melt-specific --
but just being able to use the same ReactiveSyntax in Svelte components
and then copy-paste into a function in JavaScript
and just do some getters and setters.
That's marvelous.
That was a huge win.
Yeah, exactly.
It always irked me, like a lot of people coming from other frameworks,
like, "I can do this with a custom hook with Vue Composable.
Can you do that in Svelte?"
I'm like, "Probably, but sometimes it would be a bit of a headache."
Now you can. Now it's easy.
So, I mean, now, like in the future, with rooms it will be easy.
I am excited to actually learn more platform stuff
because I don't really know much about getters and setters
because I've never had to use them, and now I get to learn more.
Well, maybe, unless they give us something to prevent us from having to write it.
You can always do it on your own, right?
If something was added, it would probably be...
I don't have time to learn that.
Okay.
I don't have a need for it.
If I had a need for it, I would, but I just don't.
Yeah.
Because there's been talk about adding a helper thing, right?
Like a runify or a box thing that would do this stuff for you.
This is something that I'm really curious about.
When I first... I went through a rule of CursorRootRooms.
I learned about Rooms. I was like, "This is amazing."
Then I tried to do export. Let's... a state, right?
From a TypeScript function. It wouldn't work.
And I was like, "Rooms suck."
[laughter]
Just kidding. I wasn't like that, but I was like,
"Huh, this is an oversight and stuff like that, and why is it this way?"
Because I already knew about the concept of signals,
and I know that Svelte uses this underneath it.
But then I understood, "Hey, you're not supposed to think of this as a signal
or think about signals. You're just supposed to use this."
But my interpretation of it was like, "Think of this as a variable."
You can't export a variable from a TypeScript file and then just modify it.
To do that, you would need getters and setters, just like a normal variable.
So that's when it started to make sense.
So state is kind of like just telling stuff like, "Hey, watch this little guy here."
It's kind of that way, just saying, "Hey, this is reactive.
Pay close attention to this one. That's it."
Yeah, under the hood, it uses signals, but it's unlike view and solid
where you have access to the signal reference, right?
You can hack it a little bit. Not hack it.
You can create a function that has its own internal state
with its own getters and setters, and just use that.
It would look really similar to solids or views implementation, if you want.
Which is, I'm curious, what's it going to look like when rooms are released?
If there's something new that's going to come up because of getters and setters,
or if the community will adapt and just start using a convention like that somewhere.
It's curious. I know that the state not giving us access to the signal reference
was intentional from a design point of view to avoid spaghetti code and stuff like that,
and avoid not being able to track what's going on.
And I agree with that, but I'm curious how the community or how rooms will change
until it's released, or how the community will adapt when it does.
I'm curious how the browser API is going to develop, too.
Yeah.
Yeah. There's been...
Browser APIs tend to always be a little worse than what frameworks make the DX a little better
than what browser APIs tend to be.
And I would rather use the framework because it makes the DX better.
Hence, Web Components are always my go-to awful API of death.
Yeah.
[laughter]
Well, yeah.
They're not bad if you use Svelte.
But it's a framework that has made the DX of Web Components better.
Well, I always hear from Web Components fans or advocates that they're really easy.
Just use... And then it's like Extensible.
Lit.
Yeah, or Lit.
Extensible.
Well, then that's not Web Components.
Exactly.
But the same thing can be said here.
Let's say that signals are hard to use, raw or whatever, it's fine,
because Svelte's abstracting over that.
And when it goes into the browser, that will just be an automatic flip,
and you'll use the browser native one.
As we do with a lot of the observers.
If they're not in the browser, we'll create them.
If not, then we'll use a native...
If they're not in the browser, we'll create them.
If they're in the browser, we'll use a native one.
And it keeps everything pretty simple.
And you'll just do it under the hood and keep the same DX for us.
Exactly.
For us, for ourselves as well.
Power of Svelte. Compiler.
Yeah.
Actually, one weird thing about Runes, of course,
is it's almost like a step away a bit from that kind of compiled reactivity
to more real-time reactivity, which is interesting.
Runtime reactivity.
Yeah, runtime reactivity.
Yeah.
But this is something I'm also eager about.
Sometimes reactive statements, since they work with static analysis,
they have these weird behaviors that you don't expect,
because you're not a compiler analyzing it statically.
You're a human.
And while when you work with Svelte for a long time,
you are mindful of these.
Sometimes with a more complex component, you miss those.
I recently was working on that.
I read my chat.
I was like, "Why isn't this working?
Why is this happening?"
And stuff like that.
And I switched the reactive statements.
Oh, it works.
Yeah.
With Runes, that won't be a thing, which is really exciting.
You just said "app-write," and I just realized we didn't even get to that.
And we've been talking for almost an hour.
Yeah.
The new app-write website.
Built in Svelte and Kit?
What's this about?
Exactly.
Is it the landing page?
App-write has been working on its new brand for a while,
and with that comes its new website and docs.
Why does app-write do two?
Website is more like blog, and some landing page stuff,
some cool animations, just so newcomers can see what app-write is all about,
with some really fancy design that our design team has worked tirelessly on.
But also much better to work with docs.
Well, for users, we now have search in docs, like everyone else.
But yeah, there's some stuff, interesting stuff I want to get into there.
How Svelte helped us into, in our brief time,
I don't know how much time we still have.
But yeah.
So it's built in SvelteKit, which is amazing.
Not only because I love Svelte, it's now much easier to develop
compared to our last stack, which was PHP with Docker.
Each time I had to change a single line of code,
Docker compose, or I'm a noob at Docker.
I'm familiar with that. I have to do that, even with our Svelte app.
Oh, yeah.
And then it's just like 15 seconds, and oh, I forgot a line.
No hot reload, just manual.
But even barring that, I really love SvelteKit's developer experience.
It was really great to develop using it.
It also helped me a ton.
As I said, we really wanted this site to be visually appealing
and interesting and unique.
And so we had a bunch of animations, for example, on the landing page.
And I love making animations interactable.
So I don't use only CSS transitions and web animations,
and stuff like that.
I also use Svelte's transitions and animations for stuff
because it's so much easier.
For example, sometimes I simulate an entry entering into a database.
I show the table.
And instead of me manually animating, like,
"This element needs to go down. All of these need to go down."
And then one pops up, like with CSS, I just add it to a Svelte store
and just use Svelte transition and animate with slides and fades
and stuff like that.
Super easy, really, really easy.
In that sense, it helped quite a lot.
I used it a ton there.
One thing that was really cool, too, just like file-based system routing,
stuff like that, we're using static files for our tutorials and blogs
and stuff like that, together with something that's not well-known
and I think should be, which is a Markdoc processor.
Have you all heard of Markdoc?
No.
You know MDX, I assume.
Yep. MD Specs.
MD Specs, yeah.
Yeah, that too.
So MDX is what Astro uses and React folks use,
and then we have, of course, MD Specs, which is also a great thing.
I use it a ton now, actually, MD Specs.
But Markdoc is a thing by Stripe, which is also a Markdown processor
that allows you to put components and stuff in there with props.
But the thing is, there was no adapter for Svelte.
Then my team lead, Karsten Bittman, created a Svelte preprocessor
to allow using Markdoc.
It's actually published on NPM and stuff like that.
You can check it out, and it's what FWrite Websites uses.
And I think it's really, really awesome.
It's pretty cool.
And we use it with normal Svelte kit, so we have the name of the article
in the folder, then plus page.markdoc.
That's it.
We use it a ton there.
It's also really helpful in that sense.
I feel like Svelte preprocessors are one of a big pro in Svelte.
It's not something you're going to use all the time,
but I really love preprocessors.
It's not something I've seen in other frameworks.
Yeah, it's something that definitely gives you control over doing something
that's your own, almost like a custom language on top of Svelte,
which is quite amazing, really.
Could be a foot gun as well.
Of course.
Everything is an escape hatch and a foot gun, right?
With great talent comes great responsibility.
Yeah.
We use it in Melt, actually, since we have to spread the prompts
and use an action.
We actually have a preprocessor that just uses a single action,
like use Melt, then you pass in the element,
and that's it with a preprocessor.
But yeah, I think that's a little bit about it.
It looks great.
Anything else?
I was going to say, just a little over halfway down the site,
there's the cards that just swipe in, and it's so cool.
So if anybody has time, ibrite.io, and just swipe through the cards.
It is super cool.
Thank you.
Yeah, it was pretty great.
One challenge with those animations,
we're making them like between certain animation states,
you have to interrupt an animation.
And when you go back, it needs to start back from scratch.
But I'm using JavaScript.
It's an async function.
You cannot interrupt an async function.
I had to do some really wonky stuff in there to make it work.
It works quite well, but it was definitely interesting
using some custom style stars for that too and stuff like that.
If anyone is curious enough and crazy enough to try and understand
what's going on there, it's a little bit interesting.
I also modified, created a custom flip directive for the animation.
I overwritten it a little bit.
The way flip works is it just scales it up or down
according to where it's going.
But then the internal elements gets warped.
So I modified it by passing CSS variables that you can apply internally
to inverse the scale warping.
I feel like that was good to do too.
That's why I like Svelte.
It's pretty extensible with these transition directives
and all its directives.
Yeah, definitely something that I think--
I would probably mention it all the time on the podcast,
but if you're using other frameworks like Vue and React,
you're not accustomed to having these things built in.
And they are really nice.
Once you use them, you're like, "Oh, this was so easy.
Maybe I'll just keep using Svelte because why not?"
Exactly.
It's quite a--they're enduring features.
They're not like must-haves, but you love them so much
that you don't want to abandon them.
Exactly.
How do I do transitions now?
Oh, the library?
It looks like it's all open source too.
It is. It is.
So we'll put a link to it in the show notes.
I think we've chatted a bit about Rune, Svelte, the website.
Let's move to the next section here,
which is our most popular section,
the unpopular opinions section.
Who wants to go first?
Does anyone have an unpopular opinion?
I have an unpopular opinion.
If we need someone to go first.
Okay, I mean, it's usual.
Go for it.
My unpopular opinion relates to what we talked about earlier
about not reinventing the wheel.
My unpopular opinion is reinvent the wheel.
The reason I say that is because a lot of me saying
that don't reinvent the wheel actually made me realize
that sometimes someone who has a great idea
needs to reinvent the wheel because that's how we progress.
That's how we find--
The wheel was square.
The wheel may well have been square.
The wheel could have been triangular.
It was.
Well, the first wheel--
It was square at first.
Yeah.
Yeah, the first wheel was square.
If they didn't reinvent the wheel,
we would not be on the wheels we are on.
Exactly.
There you go.
So I guess, yeah, do reinvent the wheel.
Yes.
Now, don't do it for the sake of doing it.
Do it when you feel that there's a need,
when you've got an idea.
It's felt, it means reinvent the wheel, right?
Kind of.
Yeah.
I don't have an unpopular opinion.
Think outside the box.
My unpopular opinion was just going to be that browser APIs,
while I like having them, are not great to use.
But I don't know that that's that unpopular.
Depends on the API, I suppose.
I'm excited for the temporal API to expand.
But I mean, it's just because dates are awful.
Can I have two unpopular opinions since Gareth doesn't have one?
I love to talk, as you can all see.
Sure.
Perfect.
My first one that I had thought of was,
free commit hooks are bad or unnecessary most of the time.
Oh, why?
It just slows you down.
Like, commit is just me saying,
"I want this at a point in time."
Most people will just like, no verify it,
or like, it's stuff that should be caught by our CI anyways, right?
Okay.
I am going to disagree with you.
You want to know why?
Mm-hmm.
Okay.
So we have Prettier set up in our code base,
and our CI will fail if Prettier is not ran.
There's no pre-commit hook or anything before I set up one
to run Prettier on the code base,
and then it fails in CI once it builds 20 minutes later.
So you have no check between.
I mean, if it takes 20 minutes to build your product,
then yeah, I would say it's mostly fine.
But I would say most projects don't take that long.
So my pre-commit hook runs on anything that you have committed.
So it runs on like a few files.
It takes like a second,
and it just runs Prettier on the files that you have committed.
Still, I would say that if you're going to use hook,
like a git hook, do it for push instead of like commit,
because I just want to save my state.
I don't want anything getting on the way.
Pre-push hooks, I still don't like them,
but they're preferable in my opinion,
much preferable than a commit hook.
I think I disagree.
I disagree because the pre-commit hook is better
in that you're not going to have a commit full of errors and problems,
and then have another commit that cleans them up.
If you want to make sure you can commit easily without any worrying,
then you can just do dash dash no, dash very far on the end,
and then it won't run any hooks.
So you can always escape it.
Yeah, but that's the thing.
In a team, if people share that up,
like they'll be like, "Hey, this commit's an error,
I just want to save my state,"
and it just will not verify it anyways,
then why have it?
But I understand what you mean.
You can squash later when you want to save your state,
and you've got a bunch of commits where you fix stuff.
You can squash them all together.
Whereas if you're doing it on pre-push,
those commits are already in.
I suppose you could squash them in retrospect,
but I don't know.
Yeah, normally that's what's going to happen
when you're going to put it in a PR,
not when you're working on it.
But yeah, my opinion is really unpopular.
Yeah, it is.
We do squash and merge at the end too.
But then we have some teams that rebase
and some teams that merge with master,
and that's really annoying too.
Yeah, we just started using squash in mouse,
and it's so good.
It's the first time I'm using squash mergers, honestly.
And they're so clean.
My second unpopular,
this one I think you will agree with me more.
Performance is more important than you think.
A lot of people, when they go and say,
"Hey, I'm fine with using something that's not as performant,"
or something like that,
because in the end it doesn't matter or something like that.
But I would say it matters.
It doesn't until it does.
Someone may have a device that's not as powerful.
You may end up implementing a feature
that is going to be a CPU or something intensive,
stuff like that, and then you're stuck.
Then you're stuck using something that's not performant,
and changing from that is going to be a pain.
So if there's a good default,
like something that by default is performant,
and it's a good tool,
not only performant, but it's generally a good tool,
like Svelte, it's performant, and it's a really good tool,
then I would say that performance is a really good selling point.
Some people try to downplay that a lot.
I think it kind of depends on the framing.
From a front-end framework point of view,
I think that makes sense.
But from a back-end point of view,
I think you're generally in a position
where you can just throw more strong, bigger,
better servers onto the issue.
Like if you don't have to use Rust
to optimize your back-end kind of thing.
I also agree.
It depends. I agree with you.
Yeah, I'm talking more on a front-end framework, I guess.
But I agree with you on that.
Okay, I think that's our controversial or unpopular opinions.
Maybe we should change it to controversial opinions.
Then we can pick a lot more stuff.
Maybe not. I don't know.
Let's move on to picks.
What are your picks?
Who wants to go first?
Anthony, you look like you're--
I have another TV show.
Yeah, I'm pensive.
I don't think I have a pick necessarily this time.
Let me unpick.
Nothing is interesting to me in the last week.
Only unpopular opinions.
You've been too busy.
I've been too busy.
Yeah.
To be fair, yes.
All right, Brittany?
Invasion.
Another TV show?
Yeah, this last episode, it's just building up for the end now.
So this last episode was a little slow,
but it's been really good this season.
Yeah, I like it as well.
It's good.
All the Apple shows have been really good.
They're knocking it out of the park.
Have you all watched Severance?
Yes.
It's amazing.
Yeah, very good.
They're taking a while for the next series, though, right?
The next season.
Every show has done that.
And it's so long between them that I need almost to watch the season again
because I forget everything that happens.
This is why--
Maybe they do it on purpose.
Well, I don't watch the season,
and then I just have to kind of catch up as I go along.
But it's a problem.
Or watch a 20-minute YouTube recap.
Well, this is why I like it.
I join the whole binge-watching thing.
Just wait till it's all done and released, and then watch it.
Yep.
At your leisure.
Yeah, but also I like participating in the hype.
I join the community, like, "Did you see that episode?"
Yeah, true.
Yeah.
That does feel like it's coming back.
Yeah.
The weekly shows where you can actually have conversations about them
rather than binge-watching everything.
Weekly shows are much better.
I wonder if Netflix kind of realized this
since they've started splitting up their seasons into multiple parts.
They've started doing miniseries and, like, loyal parts series.
Yeah.
I think so, yeah.
Okay, I'm going to pick now.
So my pick is The Continental.
It's a TV show based on the John Wick universe.
It's like a three-episode miniseries.
Oh, that's pretty good.
I recommend it.
If you like the John Wick universe, of course.
John Wick isn't everyone's cup of tea.
That's pretty awesome.
That's my pick.
Okay.
My pick, then, will be the Berserk mangas.
When I was a kid, I loved animes and stuff like that,
not too much of mangas.
I kind of stopped for a while,
and I always wanted to read Berserk as a Dark Souls and stuff like that.
And now I can't stop buying these massive books that my girlfriends were like,
"We're going to have to buy a new shelf."
[laughter]
It's a pretty good manga.
Yeah, I'm really enjoying it, and it's made me start watching anime all over again.
So, yeah.
[laughter]
It's pretty fun.
You're from Brazil, right?
It's complicated.
I was actually born in Switzerland.
When I was three years old, I moved to Brazil,
but I'm actually Portuguese because of my family.
[laughter]
All right.
But I feel like Brazilians watch a lot of manga or anime.
Oh, yeah, they do.
They do.
It's a pretty big thing there.
There are a lot of anime cons, like Comic-Con, but for anime only.
I've been to some.
It's pretty fun.
Yeah.
That confirmed my suspicions.
Well, not suspicions, but Brazilians like anime.
Yeah, it's pretty big there.
It's pretty big there, for sure.
At least where I live.
[laughter]
Yeah.
With that said, we have come to the end of the show.
Thank you for joining us, Thomas.
Where can people find you?
Thank you.
Oh, yeah, on Twitter @ThomasGLopez.
Mostly Twitter is where I'm at.
And the Discord threads.
Oh, yes.
And the Discord room threads.
The Smelt Discord on the room thread or on Melt's Discord, too.
[laughter]
We'll put links to both.
And, yeah, again, thanks for joining us.
Thanks so much for inviting me.
Thank you.
It was great.
Yeah.
I'm glad you liked it.
And for everyone who's listening, thank you for listening.
Again, we will see you next week.
Bye.
Hey, it's Kavir.
If you like the show, please drop a review on your favorite podcast player.
It would help out a lot.