I'm Hussein. I am a staff developer here at
shopify. I mostly focus on the front end. I've been using
react for like seven years closely. I mean, when it came out. Let's talk about CodeMirror. So what are we doing with CodeMirror? Today the agenda is we're going to talk about the library itself. We're going to talk about some basic setup. We're going to add our own themes and use the themes that they have. Add our own linting. So the ability to, you know, catch some errors. Adding a general autocomplete. Something more complex of an autocomplete in
javascript. And we're going to do more custom autocomplete. I will be using
javascript just because I think it's more accessible. Not everybody uses
typescript. I wanted to just make it more general. Also it saves a lot of time here and all the errors we might get. So why are we talking about this? CodeMirror itself is a very, very, very powerful library. It allows you to create your own editor out of the box and it has a lot of features and a lot of
documentation. How we landed on this problem was at
shopify we have a few places across our app that merchants use. Different across different code bases that other developers use in our docs where we want to show like a code editor. Whether you can edit it or not in different languages. Adding certain syntax. So across the app and
shopify has been around for a long time. I've only been there for a year. And we noticed that CodeMirror was the main one being used. And also it wasn't the most up-to-date version. So part of what I did was kind of had to learn CodeMirror and add a new feature where merchants are able to add their own code. Essentially add their own code and fire off events in those codes. So what that means is a merchant can say, after I make a sale, please send Facebook the message about my sale. Meaning that like tell them that I sold something, this particular product at this particular price with these parameters. So we fire off that event for you but you put in the code that you want to fire off because you want to send it to Facebook anywhere else. So we had to have like a coding environment and that's just one of the use cases that we had at that. So I think a lot of what we do here as developers, because you can create your own. You can create your own CodeMirror. You can create your own editor and that's like cooler, so to speak. But generally we find ourselves if there's something out there that's better, maybe it's not the best thing that you should do. And we all know that and we all have to make those difficult decisions about should we use this? Should we make our own? And something like this that already existed in the code base that other teams were using, it was a good idea to use this. But the problem is it wasn't up to date. We had to upgrade it. And I think that leads me to the point about why this is so important is because I found myself, you know, I've been developing for about 10 years. I found the most important, the thing I'm doing the most is not writing new cool stuff and cutting edge
innovation. Generally speaking, I'm giving libraries on the front end or back end, but let's just say front end and I have to what I call wrangle them. I have to make them work for what I want it to do. At the end of the day, it's nice when the library just works, but rarely is that the case because business means code and business makes code complicated. So what I've had to do with CodeMirror and what our team had to do was essentially make it work for our use case. And it was an environment where you see
documentation like this and you get very excited because it's very thorough. But
documentation, what I learned is very nice. But the problem is when it's very thorough, it doesn't mean it's very easy to find out to do what you want. So we had to do linting, we had to do autocomplete, we had to add our own, but it wasn't very apparent from the examples, but the
documentation was there. So let's get through here and let's start coding here. But I just thought that introduction would be important. So one thing to note here is that we're using
react CodeMirror. This just makes using CodeMirror a lot easier. You can make your own wrappers on what our teams do, but this library here is quite useful. It essentially just makes things into its own packages and you'll see that we have a lot of packages here and that's just the
architecture they decided to do to allow you and give you more flexibility. They give some basic examples of what you can do. They support multiple languages. So it's easy to use out of the box when you're using
react. So let's follow the instructions here. One thing that's cool about StackBlitz is that you don't actually need to install these libraries directly. So you should do
yarn add. So you'll see here if you're following along with StackBlitz, I'm going to take this code here with the basic setup and I'm just going to paste it in here. And I'm just going to change this to app.js if it works. If it doesn't work, we'll revert it back. So as you can see here, it's already asking me to, oh, and I have the 10D list here so I can't see a lot of what I'm doing. Okay, it's going to ask me to install these parameters. Pretty cool. I don't know if you noticed, but StackBlitz is actually pretty fast compared to a lot of the stuff here and a lot of the other kind of environments. I think code sandbox particularly is what I used. And what's really interesting about their
architecture is everything I think is written, correct me if I'm wrong, Kavi, is in
webassembly and just load it on your browser instead of going to the
cloud every time you update something and asking a server for things. So as far as I know, that's what they do and it's very, very fast if you use it. So I don't know if you noticed that or if you're a user. I just found out about this recently from a call. Yeah, there's an interesting difference between how they execute code on code sandbox versus in StackBlitz. I don't know the details of it, but I do know that StackBlitz is local, which is awesome. Yeah, so thanks for that, Kavi. So as you can see here, we have a basic setup of a code editor. And you see we didn't really need to do much here, but there's some important nuances. First one here is we can control height. Pretty easy thing here. You can make this 250 if you want. You'll see that it increased in size. You see here we have an initial kind of value. And my mouse is going crazy. And another thing that you can do here is you can see you have some things out of the box, like autocomplete. For example, for of loop, we have it right here. We could do an if statement. It's going to do an if block out of the box. There's no linting errors or anything like that out of the box. But you can see here with the basic setup, you can even do some collapsing, which is really nice. You have this what's called a line gutter or the gutter, which allows you to show the lines. And they have different colors for highlighting and everything like that. Also, let's see here, you can do like a try catch block if you want. And it's pretty nice out of the box. So what makes this possible is you're plugged into these language kind of plugins or packages. And
javascript allows you to essentially make this editor specifically for
javascript. And you call it as a function and it's inside the extensions. The extension is the most powerful thing in CodeMirror. And that's what I love about it is everything, every feature you want to add, you can do through extensions. Now, the problem with it I found is that the
documentation is extensive, but it's also confusing because a lot of times what they do is they'll use their own terminology in other objects and just say, oh, it provides this and facets. And what I found with that is it's a bit overwhelming and you got to dig into more to understand what's really going on. I don't know about you, but I like to follow examples. And that's how I try to do things. So a lot of it was trying to find things and do things online. And with the
javascript extension, you can also add, I think, TSX true in here. And I think it'll give you the ability to add things like divs, but I think they have to be inside some
javascript here. I can't remember here. Okay. Let's see. Is it in here? Okay. Doesn't seem to be working, but that's okay. That's how demos go. Anyways, so let's add some styling here. So we have the styling. We're just going to add some very basic styling and we're going to add just the little border around just to make it a little nicer. And just to show you that you have access to things out of the box here. So I think it expects it to be TSX. That's okay. I'll keep it TSX. Okay. So let's see here. Uh-oh. Well, this is new. Let me just refresh here and see what happens. Okay. All right. So now, you know, refresh to the rescue. We got our little border here. Everything works fine. So you can see before we didn't have that. It was just a matter of adding a couple of lines here. So that's something that you can do. You can get very sophisticated with it and I'll show you how to add themes in a moment. So let's go here and add multiple editors. So the next step here is I want to show you how you can have multiple editors in one screen. They'll all be responsible for their own state. So let's go ahead and do that. You can just copy and paste it, install missing plugins. I love this. And then you should be done. All right. So you can see here, now we have a
javascript editor. We have an
html editor and we have a
css editor. In terms of the
html inside of it, you'll get some autocomplete as well. Like you could do like section here and you can have like a div. Same thing here and maybe like a span inside of here. All right. There we go. So that's an example of what you can do here.
css is not as useful to autocomplete but it does give you some available tags if you want. Like we can add an H2 here like that. We can even add a div. So it does give you some basic abilities. I don't know if it's going to know the selectors or things like that but I just wanted to show you that you can use multiple languages. You can even use Python if you want. So I'll show you how easy it is if you want to do a Python editor. So we'll go into the
react code mirror. I'll look for Python. I'll copy this in. This is not in the instructions but I just wanted to show you this. Let's go ahead and add this language here. So import. Sorry, my keyboard is having some issues. Of course. All right. We're going to add Python. Replace the
css. Let's see what happens here. It allows you to install it. All right. So now this is Python. So you can see I have some autocomplete already. Maybe like let's do like a for loop and it's a Python for loop. The tabs are already there. So that's pretty cool. Like that's just out of the box. It took like two seconds to do that. So now what's interesting here is the on change here. You can see that the state is managed entirely by code mirror so you don't have to worry about concerning the state. They do provide some helpers within the within the on change or sorry the callback here is the view update. That's very powerful. Essentially view update gives you access to the view itself and you can manage all the state inside of it. And you'll see some examples here that might be a bit convoluted, might be a bit complex, but it makes use of this view update to get access to everything inside this document. Essentially the syntax tree is what we're going to look at later on. So now that we've built this, let's look at installing some themes. So one thing that we're going to do here is add some custom themes. And you can see here in the code mirror
react code mirror
documentation, they've gave you a list of themes here that already exist. There's probably more, but this is something cool depending on what you kind of like. And a lot of developers, this is our kind of like preferences. Some people like hate light modes if you want dark mode, things like that. So that gives you the option and it's pretty nice. So let's go ahead and do that. So let's import this code here or let's just copy over this code, copy and paste. Let's see what comes up. Install the missing packages. And you can see here that we have different themes here. We have Sublime, GitHub Dark, Ocadia. You can even have GitHub Light if you want. So we can do GitHub Light. So you can see here each one has their own kind of styles and colors, but the functionality still exists more or less. So it block things like that. Good to go. So hopefully you're following so far. I know these are just basic examples, but this is kind of something that's just out of the box for you. But now the question becomes what happens if you want to do your own custom theming? And this is something that they give you access to in a pretty nice way. So let's look at this part. Adding our own custom theme. So here create a file called custom theme.js. So how you do that is you go to the plus button here, custom theme.js, and just copy over this code. And we're going to copy and look at it, and then we're going to explain it here just to make things easier. So now that I've copied this over, please go ahead and add the new code right underneath. I have it for you here. So let's go back to the app.tsx, add that in, install the missing dependencies, and the ones that rely on it. And you can see here I have two examples of
javascript, one with a custom theme, and one with the theme out of the box. So you can see there's a few differences here, mostly in just basic syntax. So when I do an if block, let's say I do cons test equals four, we'll do the same here, but you'll see that it will look different. So it gives you some access. And one thing I'll show you here is maybe we can change the comment color. And how does this work? You can see in the custom themes, you have access to something called Leather, and it works really well with the
react Code Mirror. Leather, I think I'm pronouncing it correctly, is kind of a parser, a language parser written in
javascript that helps you kind of like either write your own parser for a language or understand your own parser for a language. So it kind of plugs in nicely. And maybe I'm not explaining it the best way, but essentially it allows you to get access to certain tags in a language, certain variables. So you can see here what we've done is we can specifically have access to the
javascript comments and have that tag, send it in as a style, and then give it its own color. So if I go here and just say give it some ugly color here, let's just say blue, you can see here that the comments have changed in color. So it gives you pretty minute access. And why that's useful is it depends on your organization. Maybe they want the colors to be a specific way. And these are the kind of things like for developers could be a nightmare for front-end developers when this stuff isn't given to you. Like if somebody gives you this stuff and it's not available out of the box, it could be pretty, not catastrophic, but it could take a lot of time in your time to kind of figure out and you might not do an elegant solution. So I think this very much gives you a very elegant solution to be able to customize your own theme. So enough about styles. Let's go into some really cool thing here with the history. So this is an example given out of the box, but I think it's really interesting to kind of use. So what we're doing here essentially is we're going to have our own history and we're going to save this in local storage. Saving local storage isn't something very unique, but having access to the history in local storage is what makes this pretty cool. So this is a recent example that they added. And what's interesting to this is that this didn't used to be in the
documentation, I believe, and now it's in there. So if you wanted to do this beforehand, maybe it was a little more complex. So one thing that I guess we could do as a
community is add more to the
documentation and maybe I should do that as well and to give people kind of out of the box ways to do things that might be helpful for them. So just going to copy this over. You can do the same. Go to app.tsx. We'll install the missing package commands and we'll see what we come up with here. All right. So what are we doing here? Now we're going to see that it actually saves what we have. So if I do, I don't know why I always start off with an if block, just do like a regular for loop. We go into here and we say const s equals four. So if I go here and add another if block, if else block, you know, I know this doesn't exist in scope, but let's do something like this. So if I refresh now, you can see that it's there because it's in local storage. And if I undo, my undo history is actually there even after I refresh. So that's pretty cool. So if I go like this, you know, oops, refresh. Now you see that is there and the history is there, which is pretty cool. Like I know when you're adding code, the history could be very important, especially in this context when you probably don't have source control, it could become very useful. So it's really cool how they're doing it. Essentially, you have the ability through the history field here to have access to the state and send it in as the initial state. And then as it updates, and this is what I mean by what view update can do for you, you have access to the state, which is the entire state tree here, and you convert it to a JSON string and then send it in, stringify it and add it to local storage. So that's kind of how it works. And that's, you know, very easy to do because you have access to the state so easily, and you can convert it into different kind of versions as you find fit. So I hope that was really cool to show. Let's go ahead and move on to the next stage. So now we're going to add our own linter. So linting here is very interesting. This example is something that took a lot of hours to do for us, but it's just a matter of you can see the basic example there, but you're trying to fit it to your use case. And that was something that I just wanted to point out there because they have a very interesting philosophy here. They're not going to give you, just like autocomplete, they're not going to give you something out of the box. They say linting is very specific. Use your own linter, but we'll give you the ability to plug into our code pretty easily through our extensions. So what we'll do here is we'll just copy this and make a new file called js-linter.js. Naming, right? Okay. So we'll copy that in. So now we have our linter here and it'll do the same thing and explain it later. I just want to get a working version first. So let's update our code. And let's go to the app.tsx and update that. Install our missing dependencies as always. All right. So now what we have is let's see here if we actually have any issues from the start here because it looks like it might have not worked. So we have a custom import here. Let's see. Here we go. It is working. Just, I think it's lagging behind a bit. So one thing here we could do const. Oh, my keyboard is having some issues. Sorry about that a little. We could do const test equals four. So that's fine. But now if we try to reassign it, it will complain. And it'll say attempting to override test, which is a constant variable. So this is something that's pretty cool. And how this is managed is through this linter that we wrote. So how does this work? You have to use your own linter. So in this case, as an example, we're using jshint, just as a linter that is a basic linter that's able to detect your errors. How they facilitate it for you is once you pass it through the extensions, you can have access to the code state through the view. And what we're doing is we're passing the code as text to the jshint parser or function. And then we're able to deduce our errors from here. And then we go through the errors. And what they expect us to do is give them a diagnostic object. Diagnostic object is simply where the errors were from into. In this case, we're just doing the entire line just for demonstration purposes. And then we can give the severity and the reason, which comes from jshint. And then we push it into this array and we give them this array. And that's how they're able to underline this and tell us that something is wrong. So that's essentially how you do it in a nutshell. So you can have, as long as you have your own linter, you can even kind of do this yourself. If you have specific errors that you want to introduce and say, maybe that'll be a little more complicated, but you can get something out of the box here that can help users and know that these are going to cause them errors in that particular language. So again, we've entered this as an extension with options, and I'll explain that in a second, with this lint gutter. All this lint gutter does, this comes out of the box from CodeMirror in one of its packages, from the lint package. And essentially it adds this here so that it could show you your error kind of more clearly. So let's talk about these options here. So one thing here is actually it's pretty strict. So if I go like this, it'll underline and say, you're missing a semicolon. Other thing is I don't think you could just call like just a variable by itself. It expects an expression. So maybe you don't want these things to be as specific. So in your actual linter, you can pass in, for example, the linting options that you have. And that's why I have this here. If you actually pass this on here, let's add these options to your linter here. You can see that now these don't give you any errors, but still, if you try to reassign it, it's going to give you an error. But it doesn't care about semicolons anymore. So this is something not only provided by CodeMirror, this is something provided by your linter, in this specific case, JSHint, to give you the ability to manage the complexity or the, I guess, the strictness of the errors that you're showing. So that's pretty cool to have as well. So with this, you can have something like this in any language that you want. These libraries come very helpful. I think ESLint you could use as well. This is as long as these packages play nice. And all you need them to do is give you the ability to give you an error, an error on the specific line, kind of like JSHint does. So that's in terms of linting. Let's now go into the next step about autocomplete. But before that, I just want to take a very brief pause because we went through a lot and see if there are any specific questions. Are people having issues with StackBlitz itself? How are you managing so far? Feel free to leave in the chat or the Discord. It's up to you. So Omar says, all good. That's good so far. Okay. We'll just wait another couple of seconds. In the meantime, you know, all this looks very easy, but I'm telling you, you know how these things go. It could be very, you know, it was very complex to kind of get to an understanding of this, an understanding of this, you know, while you're trying to do this like in production code. All right. Sebastian is good as well. All right. So there's also, it might be helpful to expand that console. Because if you're ever having any errors, like with the code here, then you can
debug and see what you're logging on the console, if that would help. Oh, you mean right there? Yeah. Yeah. Yeah. Yeah. Actually, I should have mentioned that. Thanks, Cubby. But yeah, let's go on to the next step now, which is the autocomplete. So you saw here, we have some autocomplete out of the box. Oops. So we have some autocomplete out of the box. It's pretty nice, but maybe you want to get a bit more complex with it. And this is where the kind of, you know, the really, I think it's a really cool part. And it's a bit complex, but also very, very powerful. So what we're going to do here is create a complete jsdoc.js file. And the naming, I know it's bad. Sorry about that in advance, but I just wanted to get something working here for us. So we added here, let's see, did it add it? Complete jsdoc.js. And inside of it, we're going to paste this right here, this code right here. And then we're going to plug it in into our extensions, just like we always do. So again, copy and paste it here. I hope that having all the code here was actually useful because I hate to just, you know, when tutorials just kind of give you the thing that you, the code that you should enter and then you don't know exactly where to put it. And then you spend a lot of time being like, where do I actually put this in my code? And so I was hoping to avoid that. I know it's a lot more code, but I feel like that's more explicit. Sometimes explicit is better. So let's go here. Probably have to install some new extensions. Let's see here. Now we've added the jsdoc completion. Let's see if it actually works. So what is a jsdoc completion? We add our comments here. And if we want to add, say, something like a constructor, a constructor, deprecated, whatever we want here. And it's all for demonstration purposes, not for accuracy. And I know it doesn't highlight the variable name if you're already here, kind of like we do it, but it's just, again, providing you some autocomplete that's pretty specific, because you see now that we're outside the comment block, or if we have regular comments, it's not going to show up. So how does CodeMirror make this possible? Okay. Oh, thank you for that, Covey. We're going to look at this example here. And what you'll see here that's different is something called a syntax tree. The syntax tree is provided by the language package. And what this allows you to do is parse the code, essentially, as a node that you can go through and be a little more specific with. So in this case, what we're doing is we're checking the node name before. So we get the node, we process it, and you can console.log this, and maybe we should here to see how this looks like. And as we type, oh, I think the object is too big. So it has to be in the browser console. Okay, that's not good, but we'll... Maybe you got logged to the browser. You check in the... Yeah, yeah. It's going to get logged, but what I'll do, I'll do a .name here. Nice. You can see here, it parses things like a variable name. It thinks it's a variable name, a for loop, a for statement. It thinks it's a line comment. So that gives you access to something very powerful, or you can actually look for the actual name of the variable if you want. And that's what's making this possible, is they're actually checking if this is a block comment. Let's see here, and I can't see, actually see, because of the camera. All right. So I don't know how to type it if it's a block comment. Oh yeah, there we go, because you're inside of it. Now, what we're doing here is being very explicit. We're saying if it's not a block comment, if this doesn't exist in the block comments, particularly the two stars, then don't do anything. And this happens every time you type. So it is pretty, I think, pretty... It could be pretty expensive in terms of writing this, but we've had some very big code, multi-lines, and it hasn't done, it hasn't stalled things down. But anyways, that's not the general use case that we're using it for. And it seems to be working pretty well out of the box. Now, in terms of what you're returning, that it expects is where the autocomplete starts, and then your options, and then also you can provide a regex. And this is an actual, just an
optimization, particularly just to make sure that as you're compiling this again and again, it doesn't do some extra work, as far as I understand. And then here, we're providing the odd types of auto return, the JS docs that we want to do. We can even add our own here. So when we come here and we say something like test, you can see that it's available now. So all this is being made possible by the syntax tree. And again, all we're doing is we're coming in and we're adding it as a JS doc extension, sorry, as an extension to CodeMirror through this
javascript language kind of line here. This is another thing with these lines. I couldn't get this to work initially. What happened was the way they tell you to do this in the docs is to use an override. And you might see there like an override in the docs. But what the override does is it's very hard, or what it takes away is the original autocomplete, like this very nice one. So it takes that away completely. So I had to kind of dig through some examples and actually quote sandbox examples, looking at different ones across the internet, and I finally found that this is the way you're supposed to do it. Maybe I'm just bad at reading the docs, but I didn't think that was very easy to find. So this kind of line took me quite a bit to find. But that makes it easy for you to add your own autocompletions. And you'll see here we'll add more with the addition of keeping the original one. Because if you do an override, like they tell you in the
documentation, you'll lose the original autocomplete. That's very useful. Okay. So let's now go and add a different kind of autocompletion. So this is going to be the whole global scope. And this one I like a lot. So what we're going to do here, again, make a new file. We've done this many times so far. And add our syntax tree here, our processor. And we'll change our code one more time. Not one more time, a couple more times here. Or actually, I didn't add that original one. What we'll do here is... Oh, okay. I don't think I updated something. Sorry about that, everyone. But what we'll do here is we'll see. We can just add this manually, actually. So I think I don't think I committed it. Let's see here. So we want to import. Let's see here. I think this will actually work. Just let us know if you're having any trouble with this. What I'll show you to do here is just to remove some
typescript stuff, which I think will make it work. Yeah. I think I removed that from the readme just like 10 minutes before this, but I don't think you refreshed it in time. Oh, okay. It should work. Yeah, it should be working. Yeah. It should be gone, those type ends. Oh, nice. Okay. So I just need to refresh my own screen, is that what you're saying? Yep. Wow. That's awesome. All right. So now what do we have? So now we have our original auto-completion. We also have our JS doc auto-completion. And now we, in addition to that, have our complete global object auto-completion. What you can see here is now the documents. I have a lot of stuff here. I have my event listener. I can add a click here and my function. I can do things like go into the window object and add some other functions that I want. And you see I have everything available. And I believe there's auto-completion on that on some of them. I'm not sure if that works entirely out of the box, but this is an example kind of given on their website. They actually removed it from their
documentation. I don't know why. So if you look at their
documentation on auto-complete for some reason here, and let's go to the examples. Where's the auto-completion? We see the main example here is the one that we showed with the JS doc. It used to be the one with the global object. I find this kind of useful for when you're using
javascript, but maybe they found this too complex or people complained about it. But it works exactly the same way, except that it does this little neat trick here where it looks for the variable name that you enter inside the window object. And that's how it knows that you can auto-complete within it. So that's just another one that is very useful, I think, and adds things more out of the box. But here's the last thing here. So what if you want to add your own custom auto-completion? All right. And that's the one I think, I don't think I added it here. All right. So I'll grab this from another CodeMirror instance that I have, because I've been practicing this, as you can probably imagine. Let's look at here. So what I'm going to do, and sorry if there's a bit of confusion here, is add our own custom auto-complete. So you don't have to follow along here. Maybe we can add it to here very quickly. Okay. So this should be it. So I'm just going to go and commit YOLO. And let's see here. Okay. Looks good. Let's take that here for a run. And what we'll do here is we'll create our own file here. Let's call it custom auto-complete, or custom complete.js. And we'll post it in here. And we'll add it just like we do everything, except I'll do it a bit manually here. But it should be easy. So we say custom complete. So we'll call this custom complete. Okay. We'll come here. We'll make a new variable. Call it custom completions. We'll add this here. See if it works out of the box. We'll install this missing package. And I think it'll ask you to install another one potentially. Yeah. And what this gives us here is I've added my own custom one. So I do test.sub. I know these names are bad. And then I have the ability to create my own auto-completion within that. And then my auto-completion actually completes it how I want. And it says your code here. So again, I'll do that again. And I'll say test.sub. I'll open up some brackets. I'll go like this. And actually the cursor ends up over here. But I've done it in ways where you can actually control where the cursor ends up. And I just didn't do that for that example. So again, I know the naming's a bit weird here, but we can change that to be whatever we want. But we can maybe say func method on it. Let's see if that changes it. But you know what? Actually, I don't want to change that because it'll have some side effects. So we'll keep it like this. So what am I doing here? And how are we accomplishing this? So now that you have the syntax tree available, you can be as custom with this as you want. So in this case, I'm checking for completions for anything with a .property in addition to doing just a general completion for just test itself. So one thing that I'm doing is I'm checking, let's see here, test itself. Actually, I didn't add that one. Sorry about that. But when I see the word test as a variable, I have the ability to add any kind of autocomplete that I want to it. So I can add here in case of it sub, I can add label another one, let's say. And when I come in here, I go test.another one or so. So I can make my own methods here if I want. But you see here, there's no autocompletion here. And what's happening here, this is another kind of layer of autocompletion that we can do is now I'm checking specifically for this. And maybe this is not the best way, but this is one way that you can do it is you can test specifically for the existence of a string and then from there provide your own autocompletions. And with it, you have the ability to add and apply. And with the apply, I'm just adding my own function syntax here and then providing the events that I want to show. So you can add this as a .sub or you can do .another one if you want. But as you can see, the sequence here matters. This needs to be kind of afterwards from this. And that's a little bit of an annoying thing. But it's part of the syntax tree and it's being read very fast. You can see here the completion here. I'm putting this in an if block here just to make sure that we have a .property. This is needed just for making sure that the autocomplete keeps working as you type in. Otherwise, if you don't add that property name, it will stop autocompleting after you write the first state. So that's why that exists. So far, what we've done is we've added a basic setup with
javascript, looked at
css,
html, added even some Python, looked at themes that exist out of the box, looked at our own custom themes, added our own linter with using JS hint, looked at adding two additional layers of autocomplete on the window object or the document object in addition to adding our own custom JS docs. And finally, looking at a more complex or customized version of autocomplete, which you might want to do. So as you can see, all this was made possible by CodeMirror. And I think building something like this from scratch could be even more complicated than following along with CodeMirror. But I think a lot of things that happen in our field is that it's always about trade-offs. Maybe here we spend a lot of time learning the exact way we're doing this with CodeMirror. But what we found is that we're able to share this across our own entire organization. Because we found out that we're not the only codebase using it. There's a lot of codebase using it. And in fact, we established a group where we help each other with different groups who are using CodeMirror. And just to say, how are you doing autocompletion? How are you doing this? How are you doing that? And helping us with making sure that we're following either
best practices or just having a different person who went in a different rabbit hole and helping us from what they have done. Maybe we can find out a bit about the people that are here. What are you working on? Does anybody want to kind of tell us what team they are? Where they're coming from? What they're working on? What you've thought so far? If you have any thoughts about this feedback, we can use that time right now to do that if you want. So Kavi, how long have you been at
shopify? What kind of front end have you been doing? I've been at
shopify for about a year and a half now. What kind of front end have I been doing? Mostly
react,
typescript stuff, although lately I've been reading more Ruby. But yeah, just getting familiar with
shopify's
typescript infrastructure is definitely like a whole journey on its own. So that's been a learning experience for me over the course of my time at
shopify for sure. And you've been so far on, you've been on automations. You've done now marketing insights, correct? Yeah. So essentially we have a marketing section for our merchants. And one thing that Kavi has been a part of, I think from the beginning was automations. So that is actually the ability for merchants to essentially add a path for how they want to send their emails. And it's through a user interface, and we're integrating with another app within
shopify. And you can essentially say, once somebody buys from my store, once somebody abandons my checkout, I have the ability to send them a sequence of emails based on actions. This was a kind of like a year project or so to kind of get fully out there and working properly. And it's generally now available. So that's the first part of your partner. Yeah, definitely. You can send a link to
shopify's marketing automations if that's interesting to anyone. And maybe we'll use that time in the panel if you have any specific questions about that. But Helen, can you tell us a bit about what you're doing at
shopify? Sure. So hi, everyone. I'm Helen. I've been in
shopify for four years, and I'm currently on the
hydrogen team. And what we do is build a framework that is best suited for
shopify commerce platform. So it is a framework that allows developers to build their store custom storefront really easily and really quickly. And, of course, to connect it with our oxygen so that it can be deployed very quickly. And yeah, we put a lot of like thoughts and efforts into thinking about how we can make all of those dev problems, not your problem, but our problem to deal with. I heard you have source control as part of
hydrogen. Is that true? Like merchants can have some kind of source control? Is that part of it or not? If you mean by source control, it's a direct connection to the GitHub repository. So essentially, when you create a project in the
shopify admin, you can connect to your, I believe, GitHub. And then there was another one, I think was the bucket. And I'm not too sure, but GitHub for sure will generate a project into your GitHub account, create a project for you, set up the web hook so that it's connected to our oxygen infrastructure automatically. And it's all done in like, I think it was like 30 seconds for you. And you can start your project, you can see the preview of your project, connect it to your store, and all of that ready for you. Okay, awesome. So just give a bit of background. Currently, when you set up your store, it's kind of like you choose a template and you have the ability to make some customizations on it. But with
hydrogen, you can make a completely custom storefront with your own code from scratch. Is that correct? Is that the best way to start it? Yeah. And we provide kind of like UI components that you can use. I think it's in
react or something similar that you can just kind of like use to build like as building blocks for it. At the moment, right now, we're using for
hydrogen version one, we're using the
react server component. So there was a lot of exploration into this, I would say, somewhat, well, it's new, but it's like two years new kind of thing concept that
react team is working on. And now it's like with
next.js. And so we were on that path. And as you all know, recently, we had the
remix acquisition. So now part, it's part of us. So V2 will be with
remix and
remix build. So that's kind of like where it's at right now. But yeah, overall, like our goal is like to provide something for developers that is so that they can very quickly to build their web storefront on the framework. So in V2, you're going to have the ability to just use
remix in addition to
server components or just
remix? At the moment, it's just
remix. We're still thinking about
react server component, how it can fit into
remix. Well, but yeah, that just details. Like, developers shouldn't actually have to worry about
react server component is an implementation kind of, or I should say framework detail. But like, if they have to, then it's like, not quite what where we want to be. So that separation of concerns between like, which code runs on the server versus like, which code runs in the client is something you guys want to like, make less relevant in
hydrogen? In
hydrogen, like I would say the goal will be more so in a sense that developers should be just worrying about building features for their custom storefront and not worry about a bug in
react or like
react server component. So I think that's where the line draws is like, developers shouldn't have to worry about
react server component. They should worry about how do I make
internationalization work? How do I add a card form kind of thing? And we want that to be just like a plop in, oh, you just like add this component and give some properties and then off you go. You're done. And it should never be complicated to build a custom storefront. That's awesome. So like, what I like about like, the source control specifically is like, that aspect is like, right now, if you make edits on your store, without
hydrogen, and if you make a mistake, like, basically, you have to have two versions of your store, like one staging and one production. Is that what people are generally doing before
hydrogen? Do you know? Do you know? For
hydrogen, that's actually more of the Oxygen infrastructures. So Oxygen, you are able to have multiple environments. We do have like previews for your storefront before you deploy to production. So that's one aspect. There's still quite a bit of like missing APIs. For example, like the draft
api, the drafts that you can have on the online store, that's not available in the storefront
api. So we can like, people can see draft products at the moment on
hydrogen. So that's like, one of the things that we're trying to like, fill the gap at the moment with the
api team. Got you, got you. That's really cool. I could say that definitely when I saw
hydrogen and Oxygen come out, I was like, wow, what am I working on versus what are these folks working on? Definitely a lot more complicated than what I'm doing. But that's awesome. I think, you know, with me, specifically like, you know, I've been only in the core team, started off with automations in one year, then got moved to the Pixels project, which inspired using CodeMirror here for people to add their own code and eventually moved into Marketing Insights, which is with Covey right now for the past month. So now we're going more deep into creating lots of charts and stuff like that. So maybe you can post in the chat there, Covey, something about like, maybe give them some like Polaris Viz. I think Polaris Viz is available publicly, correct? Yep, yep, definitely. And that's something I think we have a lot here, like Polaris is open source. Same with Polaris Viz and these are like UI libraries, the equivalent of the Material UI. So just want to drop that in there if you're not familiar with those kind of UI libraries. I mean, they're not as customized, they're not as like general as Material UI, I would say. But I think that it has a lot of cool things that you can use, especially if you're building something like a dashboard, especially with things like kind of like just getting bar graphs and stuff like that out of the box. And it's, you know, we're using it at
shopify, so we need it to work well. So if it's not working well for you, like we'll probably fix it, you know, because we need it to work well. Let's see here, I'll start off with myself. So I'm a staff developer here at
shopify. I've been at
shopify for about a year. And I'm currently on the marketing insights team. So what we help with is giving the
shopify merchant, any merchants the ability to kind of look through their analytics in regards to how they're spending their money on ads, and what kind of return it's bringing on for them. It's a fairly new project. And it's my third travel by team so far in the last year. And been really fun so far using a lot of
react and
typescript every day. And some Ruby on the back end, but I don't touch that so much these days. So that's a bit about me. Why don't we take it next to Covey? Thanks. I'm Covey. Been at
shopify about the same amount of time, but mostly all in marketing. I started out heavily in the front end, so
react and
typescript, and in the browser. But I recently moved further away towards Ruby. And yeah, I'm based in Victoria, BC. Yeah, that's about it for me, I think. Also on marketing insights with Hussein. Helen? Yeah, so my name is Helen. I have been in
shopify for four years now. I am currently working on the
hydrogen team, which is fully
react, but I'm pretty flexible. Sometimes I will have to go into Ruby stack or whatever else just to get things working. Could be anywhere as long as long I need to get stuff done. So I'm fairly flexible in that matter. Yeah, how I got into
react is like my previous company was building on it and I know nothing about
react. But then I know a lot about instrumenting analytics. And then there's a Helen Fix analytic on a single page app. It's like, what? And as you all know, analytics on a single page app is not the easiest thing to deal with. And yeah, that's how I got into
react. And been in the whole framework for quite some time. And now
hydrogen back to single page app now. And, and yeah, it's like full circle now. Yeah, that's what I've the going joke online is that we're going back to BHP. Right. So let's see. They do come full circle. I love it. Thank you, Helen. Let's go next with Tal. Hey, everyone. So yeah, my name is Tal. I've been with
shopify for eight months, more or less. I've been working with the email team, mainly doing front end
react. And what we're doing is basically allowing merchants, I guess, to better engage with the customers to increase conversions and, and revenue. Yeah, I think that's all pretty much. How did you get into
react? Oh, okay. So for me, I was my background was with like, Java and C sharp, the company where I was working for. I felt like I'm not, I'm not making any progress anymore. So I started like taking some online courses. I was looking for some open source projects to contribute to, which really helped me and gave me some confidence to actually find like a front end role. Yeah, then I just found a job prior to it. And after about one year, I left, I left there and joined
shopify. Nice little, little, little fact Tal and I worked together at that last company. And I was the, I was the engine manager there, Tal came in, what a talent, had to try to get him at
shopify. So we're not the same team, but we were under the same umbrella. So very happy to have him. Looks like he's doing great. It's been a great journey so far for sure. Awesome. Daniel. Hey, what's up? Yeah, I actually work with Adam. I am in the
hydrogen team. Yeah, like before that, I used to do the sign components, like UI components in another team in
shopify. I've been around three years doing, yeah, working in
shopify, a bit more doing
react. And I originally was doing Rails before, and I think nobody was doing any front end. And I remember in other previous companies that it was like a mess, the front end. So I just kind of like started grabbing that. And then I started to learn all what is this
react thing that some people at Facebook put out. And then that's how I started. But slowly I started to get interested into
frameworks. And that's why I joined this
hydrogen team, which is, I don't know, for those who are not familiar with that, it's a framework for building custom storefronts from
shopify. And recently we worked with the
remix team to build on top of that. So that's been really fun because I've gotten a lot of chance to work with those parts of the code base of
remix and also
hydrogen. And it's been fun. So yeah. Awesome. So it looks like we have quite a few folks from different backgrounds. Yeah, interesting, like
react myself, I got into it by accident. It was kind of like, I joined the same company as Tal like a few years before, and it just had been popular like at the end of 2015. For some reason, when I joined, my boss said, can you just build this in
react? And I said, probably. You know, like I was using
angular and Ember at the time. I don't know if any of you have used Ember.js, but it was fairly popular. And I think what happened was they upgraded to, they did an Ember 2.0 that was supposed to be a lot better, but it essentially broke Ember 1. So people got annoyed and just did an upgrade and had ended up kind of like phased out. Although yesterday I did see a job posting, somebody said, you know, don't need to know Ember, looking for Ember.js developer, some like ridiculous amount of money. And I'm like, wow, that's probably, that's very interesting that it's still around. But yeah, like, I guess everybody got into
react in different ways. So what I want to do here now is give the opportunity for the people here we have to ask any questions. You can drop it in the chat. Feel free to open up your mic. Tell us about yourself. If not, we'll continue on. And I will be essentially picking your brains on a few things. And one thing I wanted to know is you have a lot of contacts in
shopify about like, you know, three to four years. How has writing
react changed for you? Did you start writing
react? Like, when did you start? Were you there when we first started writing
react? How was that? If not, like, what stage did you come in? Like, was it only on web? Was it new repos? How was it? I can give it a try. Well, for me, is like,
react is how I got into it is, like I said, it's like, it was like, emergency, I need to fix something. And I have like, zero context of how
react is coded and everything. So I was pairing with another engineer that knows
react. And it's like, I need to do this. And just tell me where I need to go in the code base and kind of figure out from there. And as time kind of like, goes forward, and I learned about
react, and more just stumbling along the way of like, trying to figure out things here and there. And ultimately, in the end is like, it kind of got familiar, but I would say it's not familiar enough to understand what's going on until I need to like, build a brand new kind of like, component to figure out what's going on with
react. And I would say that process was like, okay, you know, learning process is like, get things done kind of situation. And compared to now, where like, there's so much more knowledge, especially at the time that was like, learning about the whole new
react 18,
react server component, we didn't just like, read the RFC and like, oh, okay, this is probably how it work. We went into
react code and say, what in the world is going on? How is it working? How is streaming working? How is the work schedulers working? And then they figure out every detail is like, okay, if we go to the client side, what in the world is it doing to grab down the client components and then keep a reference of it? Then in future, like if other components call the same components, that we use the same module that's already evaluated. It's just like, it's like, you go really deep into understanding, like a node
react developer have to do that. But for us, like, we need to understand the new protocol. So we did. And that process took long. Like, at first, it's like, if you think about it as a developer, oh, it's just a new programming language. It's just syntax thing. But no, this one's like, we had to go really deep. And I think even that took me like three months to understand that code base well enough, but not well enough. Wow. So you're saying you had to go into the
react code base to understand like
server components more? Yeah. Wow. And what would you say, like, what would you say, like, when you look into
react code base, what did you not anticipate that you saw where you're like, wow, we're like, oh, this is actually makes sense. So this is like, huh, a little bit of both. Like, how is reading that code different than reading code that, like, customers use at
shopify? You know what I mean? It's actually quite different. So like, if it's like code that you would like as a developer on any framework, it's pretty obvious. It's like, oh, you're just propping a component here. This is where you define a root for your router or anything like that. It's pretty obvious in terms of like more developer facing. But when you go into like the
react code base, it's if nothing is, it feels like nothing is connected, but everything is connected. So you get like this like scheduler function, which is called this like other function, which is the, that does the parsing. And the other one is like, it's recursively into like some other functions. It's just like, it's extremely hard to follow and end up like putting my console log everywhere to just follow the breadcrumb of like where I'm going. So it's recursively like in the tree in some crazy matrix situation. And then because it's like work scheduler, then you don't even know when, which one is like scheduled to be executed on the next one. So it just like, it's complex. And that took me a long time to like understand what's going on. And yeah, it's like, it's very different. Wow. So what would you recommend to somebody who wants to read the
react code base today? Recommend? Like where do they start? Yeah, where should they start? How can they make the best use of their time when reading it? You know, to avoid kind of like maybe the initial confusion or just it has to be, it's a part of it. Right. You mentioned some, you were like console logging some things to see the results, but just wondering your thoughts on that. Personally, like I feel like console log is the best because there are no comments in the repo. It's just, just pure code and just purely from the function names themselves. You can't really tell what exactly they're trying to do until you like put in some like console logs and figuring out where they are doing in like what process. And then you had to figure out what in the world the function is like trying to do. Yeah. I don't think like
react ever put out a primer that says, this is what we're doing in our code. If there was, it would have been a lot easier. Oh, no, that's a great insight, Helen. Kavi, you had to give your hand up. Yeah, I'm curious. So like, I guess when you're trying to explore the internals of the
react like package, does that mean when you're writing these console logs, are you writing it in the files in the node
modules folder? Like you're actually going in that code. Oh, I see. 100%. Because
react code is like itself, depending where you are, like trying to download their repo is like near impossible. As in like it's a lot of code and to understand where you need to be is even harder. So quite often we actually had to go and say like copy a piece of code and put it into our own project so that we can modify and we'll just like
npm like alias link or just like file link to that particular file so that it works. So that's what I wouldn't understand. Like if you add, if you add a console log in the
npm package thing, then how do you make it like recompile or how do you make it like adjust to those changes? Well, we pulled down the ES module one, so at least it's like readable. Right. And now we're not dealing with like compile code here. And like putting, and because like we referenced the file, not to the node module file, but like actual file as like part of like pretending that we're actually like creating a new package, which is like a
react copy. And then we just link to that. Oh, crazy. Yeah. It's confusing even to set that up for sure. Wow. That's super cool. I know Daniel, you had your hand raised please. Yeah, like I recently had experience with remakes. For example, we're trying to modify something and usually the repos, if you're lucky, they have some sort of playground included and they usually are also developing on it. So if you find how to set that up, then probably you have the thing easier to run. And as Ellen said, either console logs works or I recently discovered the BS code debugger where I just like running it the debugger and then just like go through it very slowly to try to figure out what they were trying to do there because sometimes there's so many edge cases that they're like trying to take care of that if I don't go slowly, I miss what they are trying to do. And yeah, as Ellen said, it's like there's, you know, you can, I think what
remix they do is they have the, they do like, let's say compile the code into a distributable and then they, I think they copy it into the node
modules of the playground that they create. So each time you do modification, it does it again. So then you have the latest version if you are modifying and want to test something. So I guess you could theoretically do the same for other, I don't know, projects that you test projects that you have, you can have the node module, the node
modules and then kind of link it directly. And then that way you could get the latest version. Yeah. So Daniel and Ellen, do you feel now like more confident in making open source contributions to
remix or
react now that you've like delved into the code? Like, like to somebody who kind of like, if you think, like when I think about it, I'm like, oh man, that's, that's daunting. Like me make a contribution to
react, like who am I? You know what I mean? But now since it's part of your job, like you went through it, does it feel less so or more so? Give and take, I would say. I mean, it, it really depends on the complexity of the stuff we're trying to, trying to fix. To me, I would say like, it's still daunting because like, in a sense of like, you don't know if it's a real bug or not, or you're just using it wrong. And then not. And then it's just like, not anticipated. And yeah, so I would say like, it still feels the same. It's still, it still feels kind of daunting to contribute to open source. Yeah. It feels like you have to, sorry to interrupt it. Go ahead, Ellen. No, no, no, it's okay. Go ahead. Yeah. It feels like sometimes as you say, that you have to talk with the people that are like, maintainers to figure out if it's a bug or not. And, and also to kind of agree before in an approach, because if you don't, then yeah, like, yeah, they probably have more context than you where you're going to put the code and what to do. And there's some features that definitely, they won't allow you to move it in a direction that they don't want. So it feels like, you know, that they don't want. So it feels like, you know, maintainers have a lot of like power over the code basis. So even though, you know, you might know how it works, you know, you might just like influence maybe their decisions or, you know, I guess, yeah, this is, it's not just like, I'm going to push the code and that's it. It's like, I kind of have to work through it a bit more than my code base. So that's funny. Yeah, like, I think like a couple of interesting things about that. Like, the one thing is like how you both described your kind of process of understanding. And one of, you know, Helen mentioned console.log, then you mentioned like the debugger. And I found that like an interesting workflow, because like, I know, when I started out, some people would say to me, oh, you don't know the debugger, like, what's wrong with you kind of thing, right. And that's kind of like the school way that I was kind of brought up. And then I read this book called Coders at Work. And then I saw some like, I think one of the main contributors to Linux, or the inventor Linux, like, that's exactly what he does. And he's just like, I just print state everything. And you're like, well, I guess it just works for him. So whatever makes you work faster, maybe sometimes you do need a debugger. But I guess if like, if that's your flow, and how you work, it's definitely a valid way. And it looks like you can get a lot done, you know what I mean? So yeah, just wanted to comment on that, because I thought that it's a particularly interesting way. So if you can put a course on diving into
react or
remix, imagine that, having that on Udemy. So I want to switch gears here a little bit to figure out a bit about what Tal had been doing on the email team. So the email app is a first party app. What have been some of your kind of like struggles with it working so far, or good and bad, and how are you finding working in a first party environment? Because you're not really in
shopify web, but you are in
shopify. Or like, you're not really in web, but you are in web and core, right? So how is it writing a first party app? Yeah, exactly. So yeah, that's definitely something I'm not used to be doing. Because first of all, as an app on
shopify admin, you no longer... I mean, the context is a bit different, right? Because your app is within iFrame. So I feel like this is the first thing that was challenging for me. Open
react devtools, I mean, it looks different. I think there is a way to do it, which I'm trying to figure out how to have it as part of your Chrome developer tools. But what we use right now is like an external
devtools window, which is a bit of a different experience. So I would say that was definitely one of the most challenging, or one of the challenges when I started working on it. Definitely different from what I did before. And then specifically for email, I think probably the hardest thing we're doing is the rich text editor. So basically you want to allow a user to be able to just add text, buttons, whatever they need, basically to create an email. Just like if you go on Google Doc and create a document, so very similar experience, they should be able to select the text and then modify it by changing fonts, colors, etc. So I would say this is the most complicated part of, at least for me, up until now. Yeah, and talking about open source, what we use is a library called Slate. And definitely, I mean, it's not a very straightforward one. We do have helpers, but still it's pretty challenging, at least for me so far. So you are writing everything in
typescript, correct? Like everything is pretty much the same thing. Yeah, that's right. Got you. And I'm curious, I'm not sure if you could share it more this publicly, but like Daniel and Helen, are you writing in
react or are you writing in another language? Definitely in
react with
hydrogen. It's all
react based. Got you, got you.
typescript?
typescript, yeah. I guess it's not always really 100%
react, but yeah, mostly. Okay, okay. Yeah, so I think we're all writing kind of
typescript and I'm just curious, your thoughts so far on it. I've been probably using it for two years, but I've been using it seriously for like a year. And yeah, definitely I can see, the way I used to write was I could just compare it to like a catboy. Just like, you write your test, but you just kind of write, and you're just like, you kind of hope for the best when you write with
typescript. In a way, you're writing tests, but there's a lot of if statements, there's a lot of things that I realized like, wow, this is catching a lot of things beforehand, but it took me a while to get used to and still getting used to the types. And essentially when I did the workshop today, I wanted to avoid that. So I just did
javascript and I think a lot of people maybe don't know it. So I started off with
javascript and a personal project, I probably will do
javascript because I just want to avoid the whole, because if you just end up using any, you end up like, why are you using
typescript? But I'm curious what you thought in that how has your experience been with
typescript so far? Me, fairly positive, but yeah, getting used to it. And this is open for anyone, of course. I would like to profess my love for
typescript. I've slowly gotten more obsessed with it and I'm still discovering new capabilities it has, especially for inferring types at runtime. There are just so many benefits I think. It's scary using an untyped language like
javascript in production. I think it's just a scary idea that
shopify used to run on that and all these different
frameworks. It's hard for me to imagine a time before
typescript where production code in a browser was safe. But yeah, I don't know. I'm super into
typescript, at least so far. Microsoft hasn't done anything that would, I don't know, put me off it, that type of thing. That's awesome. Any other thoughts? I think I share a similar opinion.
typescript would throw me off at times. But yeah, I think for the most part, when I first started using
typescript, I think it was hard. But I don't know. For me, I think it takes just getting used to it. Today, I like it much more versus when I first started. Yeah, I think that's it. Anybody else have something to share? I could share something. Yeah, please. I would say
typescript is a love and hate relationship. I love it if we know exactly, it's like this is what I'm expecting and this is the shape that we know that we should be expecting. But then I hate it in the sense of because we have to build it for developer facing and there are some points where we don't know what we're going to get, but we're expecting some certain stuff that's there. And then we're not too sure what we're going to return because that spec is also changing. Then how do you write a
typescript for that? And also like propagate through, it's just like very gnarly and it's difficult to write for that. But then we kind of have to do it mainly because we're dealing with developers that would benefit greatly if they know what they're going to get and what they should input in there. How should they input it so they can get what they wanted? All of that shape is just hard. And then quite often, because we had to deal with
typescript, it got to the point that this is too complex for
typescript. What do you mean? Yeah, go ahead, Daniel. That is the exact example that I wanted to talk about that it's great until
typescript is telling you that things are too complex. I love this specific error that says that your types are too complex. What should I do about this? It's just like, yeah, if the types are too complicated, that's when you really can get frustrated. But if everything is kind of simple made and understandable, then it's great. But as soon as maybe you start to introduce some really complicated types, it can get really frustrating. So I think that's the part where you're like, okay, I don't know if I'm doing it incorrectly or I don't know. I still think that it's worth it. When you get it working and then it's just like everything's great. It brings you some
security. But yeah, there's some frustrating moments sometimes where you just want to get done with the feature and not get
typescript complaining for hours. That's all. Yeah, I think I've been sheltered from that complexity in a lot of ways, because living in web where the
data you get back from our
api layer is all typed and all the packages we use in web are all typed. So you're very sheltered from, I guess, that additional complexity that would come from building stuff from scratch or just using stuff that exists outside of our nice little
ecosystem. So I think that sheltering has led me to appreciate it a lot more and to build with it in a lot in a more comfortable environment, for sure. Yeah, definitely. Especially a good build system that can help us run through additional
testing and things like that to shelter you further. I remember when we first started something like ESLint, and we did it in a way where it would break your actual code if you had an error. It wouldn't just show it in the route. It would just break it. It wouldn't recompile. That was common in some parts in
react. People would do that, and then now we do it. It's like the build fade is when it does the additional sheltering, and it helps you additionally there. But yeah, I feel like with
typescript, yeah, I definitely feel that love and hate relationship. And it's good. The stuff that Microsoft is coming up with, like VS Code,
typescript, some great stuff. I mean, I can't imagine. I remember I was going through different IDEs every day, and now I'm just like, well, I kind of really like this one. I don't want to change. Thank you everyone for joining. I didn't want to prolong it further. I can't think of anything particularly, but I just want to make sure that, you know, thank you for making the time to coming down here. Hopefully the workshop was good for those out there that enjoyed it. Thank you for watching. I'll see you next time.