XState is everywhere at WebinarGeek w/ Nick Worrall
Baptiste Devessier: [00:00:00] Hello, everybody. Today, I'm with Nick, a web developer from Webinar Geek. He will show us the tools they develop and how they use Xtate in their products. Can you introduce yourself a bit, Nick?
Nick Worrall: Hey, everyone. I'm Nick. I'm a, yeah, as Baptiste says, I'm a developer at Webinar Geek. It's like an all in one webinar tool where we've got like a streaming page where presenters can stream their live streams to viewers.
And it indicates it integrates all with like the company's business tools as well. And all their marketing automation, automations with like MailChimp and all the good stuff like
Baptiste Devessier: that. Do you want to show the product you build maybe to get another view of, of the product and where it is used?
That's a good idea.
Nick Worrall: Cool. Yeah. So what I've got now is the webinar platform the webinar platform is actually built with the Ruby on Rails initially. But for some of the more [00:01:00] intricate parts of it, like the streaming page we wanted to be able to use React on the front end to really get those interactions correct.
So this is what it looks like as soon as you enter the streaming page. We're asking for your camera details, your microphone details like, like you would see in other different applications. And this is the, like, the heart of the, like, the streaming page. So normally instead of this OBS virtual camera, you will see my Facebook because we're recording it today.
I don't want to do that to risk anything. And also I can have a viewer side by side.
Baptiste Devessier: We are using a squad cast to record the episode. Maybe if we use the webinar gig, it would be, it'll work better.
Nick Worrall: Yeah. Yeah, I guess so. Yeah. Yeah. . So here, here we have like the presenter on the left within the streaming app.
And then here we have the viewer on the right. So each of the viewers has got their own personal watch link to, to the webinar. And then when the presenter clicks on the start webinar button. Then they'll be then visible to the viewer, and they can see [00:02:00] what the presenters are doing and what they're talking about.
Within Webinar Geek, we've got the option to have different slides, you can start different videos as well. We've got stuff like polls and quizzes. So if there's a poll that's been asked, then the viewers can vote on a poll. which one they would like to see. We've also got the same option for quizzes. We have a q and a module where the viewers can ask a question.
They'll be seen over there. They can be upvoted. The presenters can answer with, uh, some text, or they can even start like a live answer to start talking about it within within the context of the webinar. As well as that we've also got lot, lots of chats, mm-hmm . As well that the viewers can interact with either publicly.
Or privately. And yeah, we've also got the option to actually bring a viewer on stage within the webinar as well. So allowing [00:03:00] the stage options to be open, the viewer can then join with their camera and also be present on the stage as well. So they can ask questions in real time. And then once they're done, it's easy enough to head back to the audience.
And. Yeah, I guess that's that's a demo for now. Let's assume. Yeah, yeah.
Baptiste Devessier: I'm wondering who is using your, your product for webinar? Teachers cooking teachers. I don't know.
Nick Worrall: Yeah, so it's a company primarily based in the Netherlands. So there's a lot of Dutch companies mainly using it.
And those range from the financial sector to the, we've got a lot of universities and Holland using it to educate the University of Utrecht they use. They use quite, quite a lot for a lot of their webinars. Yeah. So the, the, with webinars, they're very generic, so it can okay. Anyone could really use it for any of their, their tools.
Baptiste Devessier: That's great. Where is instate use specifically on these pages?
Nick Worrall: Yeah, [00:04:00] good question. So the streaming page, X stage is kind of like the backbone of how we are able to take events happening from different sources. And then kind of managing the logic in a like a, a nicer way. So we've got events coming from the, the APIs where we've got like Phoenix events coming through to say when a new chat messages made when a new question is made.
So we've got events coming from there. We've also got like a web RTC service. So when people have joined like the actual call and then we can listen to events over there, as well as handling any errors they have over there as well, like if they. As they drop out we, we know how to clean that up because often in Like calls like this with the internet people are dropping out.
Okay. Also on replays as well We're showing like a video player So we want to be able to listen to events coming from then as well when you pause and play the video We're able to like pause any like running Interactions as well, like the polls and the quizzes like that. So yeah, it's kind of managing all these events [00:05:00] and then also transitioning into different states to say what events can happen.
What events can't happen, for example, starting and stopping the webinar. That's a good, good one, which has an inherent state machine way before the webinar has started, you're in a, like a not started state. After that you're in a live state and only then the presenter of the webinar can say, start the webinar.
And then after that, you can, when you're in the live state, you can only stop the webinar. And then you go into an ended state where the viewers can't see. The, the presenter anymore.
Baptiste Devessier: Yeah, I feel like state is very suited for your use case. I've played a bit with WebRTC with video players, and I know there are many events coming from different things and it's very hard to handle if you don't do it strictly with state machines or options like this.
Nick Worrall: Yeah, I completely agree.
Baptiste Devessier: I understand the benefit of using XState here. Maybe we can dive a [00:06:00] bit into how you use XState in your, in your team. First, how many people do use XState at Webinar Geeks?
Nick Worrall: Yeah. So we've kind of, cause the application was built in Ruby before we've kind of got a split on the front end and the back end.
So the back end of normally using the Ruby and the APIs that they give us as well as updating the WebSocket messages and then the front end. There's a like mainly reacts developers. There's about seven of us all using x states, over there,
Baptiste Devessier: right? so seven developers using x state and Do developers collaborate with designers on x state?
to to design the Like the figma to design the states
Nick Worrall: Yeah, yeah, exactly. We've got one designer in the the front end team who's designs on Figma kind of correspond one to one with states within a, like a state machine, which is we, we, we kind of use that. And then we can share the state machine with them.
So [00:07:00] they understand how, how their diagrams are getting mapped to the flows within the, within our application. Great.
Baptiste Devessier: And do you use stately tools to visualize the state machines? I think it's better for non developers to understand state machines visually like this.
Nick Worrall: Yeah, de definitely like the, yeah, the visual aspect.
'cause the, the designers and the product owners don't necessarily read the, the code. So yeah, stately tools gives us a, a nice visual way to show what is going on with, with the, like the states within the state machine. And yeah, as I say, having that map to the, the Figma diagrams that the designers created, they can understand, um.
See, see like their diagrams kind of brought to life within like the state machine. We, once we have that, we can also talk about flows within like a high level concepts with a language that everyone can understand. So we know. If something's wrong, then the product owner can tell us straight away rather than having us do something and then build it all and then say it's all wrong.
[00:08:00] So being able to spot those bottlenecks early on is really good with the stately tools.
Baptiste Devessier: Yes, this is the true power of state machines. And how many state machines do you have in your codebase?
Nick Worrall: I counted them just this morning, and we've got currently 138 state machines. They, they range from like small to large some, some small ones being a, like a small throttling machine, which allows you to send an event and then only allows you to send another event to the same thing every second.
As well as other ones which control the whole like big overview of like the, the webinar. So going from like checking your system settings are okay to going to the actual webinar page. So they range in size, size, quite a lot.
Baptiste Devessier: Nice. I'm wondering when you work on a team with many developers working with Xstate do you end up with merge conflicts or things like this often?
Nick Worrall: Sometimes, but quite [00:09:00] rarely, because we've got so, so many machines, normally one developers working on one thing at a time. And if two developers are working on it, then we, we make it known. So we can, we can always branch off of like a shared branch which contains some shared functionality we need at that time.
Baptiste Devessier: Okay.
Nick Worrall: Also I find like, because X States the files are like the machine files are very organized with like new lines. You rarely run into merge conflicts. Like that. So if someone's adding to an action or a state in the same place, then normally it's a case of accepting both the changes and it's gets quite easy.
So in order to iterate on these machines, it's becomes very good for motor conflicts and diffs. In general.
Baptiste Devessier: Yes, I agree. And do you use X8 4 or X8 5? I know it's a tough question.
Nick Worrall: Yeah, good question. So right now because we've got so many machines, we're in the path of migrating all of them from X8 version 4 to X8 version 5.
Which yeah, it's kind of [00:10:00] tricky and there's some tricks you have to do within NPM to get both versions installed at the same time. But yeah, gradually we're converting version 4 over to version 5. There's also a lot of new features we want to add, so that's kind of our, like, big tech debt that's gonna last for a bit longer, so we're finding, like, a healthy combination of people working on that conversion as well as adding new features and fixing bugs.
And all of that good stuff.
Baptiste Devessier: Are you still adding new features to Xtate 4 machines? Or do you migrate all these machines to the new version before adding features? How do you do?
Nick Worrall: Yeah, unfortunately, normally we have to add features to version 4, so we've got to have a good knowledge of version 4 and version 5.
A lot of when we go through the process of converting version 4 to version 5, we're also evaluating the machine to see how, how well it's running as, and we want to be able to, like, use new features such as the inputs for machines. We use that quite, [00:11:00] quite a lot rather than initializing the context all the time, as well as like emitting events and sending machines throughout the system.
We had a previous way we had, we got to do that with X8 version 4, which was a bit cumbersome. But now with version 5, we're able to do that a lot more smoothly. So the process is quite, quite long rather than just a file which can convert version 5 to version 4 to version 5.
Baptiste Devessier: Yes. You mentioned that you use the new system feature of X8 5.
What is your best use case for this feature?
Nick Worrall: Yeah, we're using it quite a bit. We've only converted maybe 10, 20 machines to version 5. But even so, we're finding within the machine and the action, you can send any event to any machine or actor with a system ID within the whole system. The way that we're currently trying to set it up is for every machine or every actor to belong to the same system.
So any part can talk to each [00:12:00] other. With like the webinars, everything's kind of we're treating everything with like quite, quite a bit of modularity because different use cases of webinars depending on if they're a live webinar, if they're a replay or an on-demand webinar. And your admin privileges, if you're a presenter, if you're a viewer, they will load different actors at the different times.
So we are having, so, so having like this option to add a system id to locate the, the actor you want. Is really nice and it allows for all this interactive communication, which we. Yeah. As I said, it was a bit cumbersome before with react context and refs as well.
Baptiste Devessier: Yes. I saw you collaborated with Stately on an article and you mentioned a lazy loading pattern with actors.
Could you, could you tell me more about this?
Nick Worrall: Yeah. Yeah. So in, in order for like the streaming app to like not load the whole bundle of everything at each time. So like the replays, we use a lot less than live webinars because we're just playing a video. So we've, yeah, modulized [00:13:00] everything, and then we also have it lazy loaded.
We had a pattern for this in version four, but now we've managed to make it within version five, where the actual thing doing the lazy loading is a machine, and an actor itself, which yeah what it kind of does as a brief overview is takes a path for a machine logic and loads it within, like, a promise actor, because that's also an actor.
Once it's done that, then it applies it to the, the system itself. And while it is loading, any events that you are sending over to that machine, with that system ID are kind of queued. And then they're all flushed when the machine actually loads as well as any event listeners and snapshot subscribe subscribers.
So it, it really feels like you get the, the power of knowing the machines there and it's gonna act in the same way once it's loaded. And you don't have to work on dependencies or anything nasty like that. So, yeah, yeah, we've, we've got that really.
Baptiste Devessier: This is a really interesting pattern.
I remember some time ago seeing on the stately discord discussions about [00:14:00] adding a mailbox feature that is having a state machine that could like queue messages. Until it's ready to, to process them as I understand, you have something similar waiting for the actor to load.
Nick Worrall: Yeah, yeah, generally we've the loading doesn't take too long at all.
So the actor has to know it's going to exist before you can like send a message to it otherwise. Well, in production mode, we don't want to fail, but within development modes, we probably want to show an error to say you've done something probably wrong because this actor does not exist. So check it exists before you send.
Something to it, but yeah, the similar to the mailbox feature, it's knows it's going to, if you send it, it knows it's going to go to that actor once it is present.
Baptiste Devessier: This is a some, I really like seeing teams taking states with it's all basic APIs and creating custom tools. I really love it. Maybe you, you [00:15:00] have more tools like this to, to show us today.
Nick Worrall: Yeah, exactly. Yeah. I mean, that shows like a good sign of a good tool, something with a good base that you can build on foundationally great like a whole plugin architecture, if you will. Yeah, I can, I can show you something else as well. We've built a tool for, kind of mapping machine states to react components so we can describe them in a more declarative way.
Okay. So we, we actually have a public repository here right now with like a bunch of X State tools that we have that I've only created, created a few days ago. Mainly for the purposes of this webinar. So hopefully we're gonna add like a bunch more things in here. But the one I want to showcase here right now is, the machine component. So the motivation is you've got like a like a state machine, say it's got states A, B, and C, and you want to show a different component when it's in state A, when it's in state B, so on. So normally you'd have, um, like a, a, a component like this where you may, maybe you interpret the, [00:16:00] the actor within this component, or maybe it's coming from props.
Or something. So you pull out its state value, and then you'll have a sequence of if else statements, or if you're within JSX, then you've got a sequence of ternaries, which also isn't so nice. But then like if you're in state A, you'll return another component. If you're in state B, you'll return something else, and so on.
So we have this helper that we have in this library called createMachineComponent. Which takes in a type of a machine which is when you do like type of the, the actual JavaScript machine. And then you get type safety on all the states that you have in there. So, and then you can return a component straight away from that.
So that can either be an anonymous one like this or a, a, a named one as well. So state A, you return the same thing up here, but you've got it in a way more declarative way as well. And here here's like a. A full full example of that. So yes, machines with state A, B, and C. Then you, you [00:17:00] create this component and then pass it some running actor where that actor is whose config depends on that state machine.
Baptiste Devessier: I think it would benefit really many people. I ended up. I think doing many, if else, if quite unreadable code. I think this API is great to, to simplify the code. Yes.
Nick Worrall: Yeah. Thanks very much. We're also, it's in early stages, so we've only used it in a few places, but we've already seen like feature requests for like layout components as well from colleagues to say like when, when you've got like a.
A parent state which has substates, then sometimes you'd want to like a layout component there which swaps over the children depending on the substate there. So it would be A, B in state A, B and A, C in state A, C. And also forwarding some props from, um, that are passed to that component. You'll be able to use them within your within your states.
And then we, we've got to work out parallel states as well, but we don't, [00:18:00] we don't really use those too much.
Baptiste Devessier: Okay. So yes, this is another question I wanted to ask. What kinds of features of XState do you use mostly?
Nick Worrall: Yeah, mainly actors are the, like the huge like big thing that we use. Not, we, we do use parallel states in maybe like 10 places.
We're not really using history states at all. Mainly the basic machines, but like invoking actors and spawning actors. We use quite We've got like really heavy use of them great and using that for like interactive communication spawning api runners to go make requests to the machines also spawning a lot of listeners.
For listening for events coming from other machines especially we're using phoenix, web sockets to Get events from the API when something's happened. So we've got our our own custom from callback actor we've built to listen for those events coming from phoenix so we can respond correctly within But the certain actor, [00:19:00] so the chat, when a new chat message comes through we can do, do what we like with it.
Baptiste Devessier: Okay. Is Xtate your only one state management solution on the front end? Or do you use another thing, like, I don't know, React Query Redux or anything else?
Nick Worrall: At the moment it's just X State and some like small use states new use effects. We were thinking about like using Redux for kind of like the global store, but I, I, I quite like experimenting with state machines.
They seem relatively new and visual. So. I'm glad we made that bet and we, we got something that we're, we're happy with.
Baptiste Devessier: Nice. And do you use final states? I think I like using them for, for instance, for the parallel states, when you have two things running parallel and each of them go in a final state, you can know when both of them are finished.
Do this kind of thing.
Nick Worrall: Yeah. Yeah. So the one place we do use like parallel states or final states is within, within like the [00:20:00] lazy actor like manager. So when you're loading like that promise at the same time, we also allow you to load a loader, like an API point to get data. So if we're. Talking about like the chat quest, chat module again, we, at the same time as loading the chat functionality, we also fetch all the chat messages so we can do that in, in parallel, which is nice because they're called parallel states for that reason.
And then once both of those have finished, that's when we spawn. The new chat actor with that data already inside of it. So we can, yeah, load them, load those two API requests in parallel. Nice,
Baptiste Devessier: that's awesome. Maybe another question about using XState in a, in a, in a team like, like yours? Do some people find Xtate really hard to to use, to understand?
And I don't know did some people want to ditch Xtate for another thing or did it cause some troubles in the, in the team organization?
Nick Worrall: Yeah like certainly at the, the start of the API, [00:21:00] the API for like version four was quite, quite a lot to kind of handle. But I think it was more the the mindset of Like building something with a like a global store.
That was the the tricky thing to build with When we started building the streaming app about three years ago we were with a team of like seven developers and we didn't have a like a lot of knowledge on building a reactor like application sourcing data. There's a lot of ways, to do things.
But now I I think that's generally with the community React community in general, it's like seen a lot of development in the last three years and finding the best practices and ways to kind of kind of source source data and best practices for using it. But now the like the seven developers that we've worked with, we've like kind of stuck together for those three years and now we've kind of got a really robust understanding of X state.
Now there's a few more things to learn with the version five API, which is solving like. [00:22:00] A, a lot of problems, which we, we found a bit cumbersome before. So yeah, in, in the initial phase there was a, like a lot of learning to do. So regularly we would have sessions to say this, this is a new pattern that we found within X State.
This is how you're using it. So just documenting everything internally was kind of the way to go as well as like doing a lot of pair programming with others. Now I feel like our knowledge is like a lot better.
Baptiste Devessier: Nice. And thank you for sharing this knowledge with the community, like doing this episode podcast today sharing the source code of your create machine component really interesting.
I think you mentioned that you specifically like the new setup function. Maybe we can talk a bit more about this.
Nick Worrall: Yeah, yeah. The setup functions I find really nice. It's kind of. Saying instead of inferring all your actions and guards from the state machine definition predefine them and then use them as you like what we found with a lot of like [00:23:00] our previous version for machines was we're repeating a lot of the same same guards to say is the webinar have a certain type does this user have a certain ability but now we have just like one one or two guards for saying if there's a webinar certain type and then you pass them the params Of the webinar you like.
So instead of having all these guards calling, is webinar a live webinar? Is webinar a replay? Those can use a start. The webinar can use a manage the chat. We just have these two, two guards like saying is webinar of type, and then you pass in those paras, which are the also new thing. And then we've got like a, a nice like literal of, webinar types that you, you have, but you can pass it. And also a nice literal of abilities that you can pass in there. So yeah, we're, we're finding this ourselves re not reusing as or not writing out as much boilerplate code for all, all of this stuff. So, yeah, I really, I really like it.
Baptiste Devessier: I can understand.
Yeah. I really like this new Params functionality. Being able to parameterize quads, [00:24:00] actions, et cetera. It's really powerful. Great. Thank you for your knowledge. Do you have another thing to talk in mind, another idea of a great subject people using Xtate might be enjoying?
Nick Worrall: Yeah, it's, it's kind of like if you're using it a lot, just kind of build patterns within it.
So I can quickly show you how we're kind of. Like debugging. So some of the actors we, we have so another
Baptiste Devessier: tool. Okay. Back
Nick Worrall: to, yeah. Back to this view. So this is kind of like the development version of the app. And we've got this little icon over here, which is kind of like our debug panel for like kind of showing a, a bit of stuff like the webinars, time, simulating some chat messages to stress test it.
But also here, this is my favorite part, this is the actor status. And this ties in with the, like, the lazy actor manager. So whenever an actor is spawned, then we will see it over here. And we can see its status, like, if it's running, if it's error ed, or something like that. [00:25:00] And we also have, like, a prettified version of its state.
So For, for example, the webinar state here is is is live, which is like the, the not started, the live and the, the ended state. And we we're also doing this thing to re refresh the broadcast status to check. We're still online. So you might see that change from IDL to to, to like fetching every once in a while.
There you go. And then we've also got this inspecting this thing I will need the. Console four. So if I start inspecting the the webinar state then any snapshots that are made to that so that webinar state module they will appear. So we've got state value and then like a bit of context over there, there's not too much context over there.
Maybe this broadcast status one is more interesting so you can see whether the streams online, how many seconds it started to go and how many viewers have been. Online overall in this in this webinar. This also adds it to like the URL query paras as well. So you can even start by [00:26:00] inspecting an actor as well.
If I was to re refresh this refresh this page yeah. So any, anytime there's a snapshot update, we, we will get that through here, which I, which I really like. So for example, if I was to end the webinar right now. We will get a snapshot update to say that the webinar is now ended.
Over here. So building tools like this is really fun and gradually as we get more things to version 5 we'll see this list expand all the way down, down the whole screen, which I'm looking forward to.
Baptiste Devessier: That's awesome. So, yes, thank you a lot, Nick, for all your knowledge sharing on this topic. It was a pleasure to talk with you about Xtate.
Nick Worrall: Thank you. Yeah, pleasure. I really enjoy, enjoying talking about X Days and hopefully we can open source a few more of the tools that we've we've made in this X Day tools repository. Maybe the lazy actor manager. Would be a really nice one to see how others can use that.
Baptiste Devessier: That would be awesome.
I will definitely share your, your repository with the people following my, my, [00:27:00] my content creation about XState. Definitely really interesting.
Nick Worrall: Yeah, thanks very much. I'm looking forward to collaborating again in the future.
Baptiste Devessier: Nice. Thank you, Nick. See you. for having me. Bye.
Creators and Guests
