Paul: Hi there, and welcome to PodRocket. I'm your host, Paul, and joining us today is Sander Moolin, who uses they/them pronouns. Sander is the creator of Lunchbox.js. This is a very interesting framework that... We're going to be talking about 3D stuff. It's going to be really cool, but very short. It's a Vue 3 + Three.js custom render. Is that what we could call it? Sander Moolin: Yeah, definitely. Yep. Paul: Awesome. So we're going to go over that and some other projects such as TroisJS and Vue 3 board game. I've never heard of Vue 3 board game and TroisJS. Is that the right way to say because it's T-R-O-I-S for anybody listening. Sander Moolin: I think it's "twa" I think- Paul: Twa? Sander Moolin: ... yeah, yeah, which is French. And that's going off of Vue recently, the folks behind Vue came out with Vie, which is also French. So Twa is kind of building off of French for three, I think it is, and the lead developer on that is based in France as well. Paul: Oh, okay. Okay. Gotcha. There's a French twist- Sander Moolin: Yeah. Paul: ... to these products coming out. Gotcha. Well, great. Right before the podcast, I was telling Sander, Three.js seems like this super cool, you're seeing things people are making Three.js, which is a 3D DOM render. Well, that's what I see it as. Is there- Sander Moolin: Well, the only thing I would change about that is that it's more of a 3D, it'll render to the canvas rather than to the DOM itself. Paul: To the DOM. Okay. Sander Moolin: Yeah. The actual end result you see is going to be rendered on a canvas element, which exists like any other normal element in the DOM that has some special properties, like being able to support some drawing intensive applications like Three.js. Paul: Gotcha. Okay. So the canvas just lends itself better to that type of functionality. Sander Moolin: Exactly. Just like an SVG might help you with scalable vector graphics. It's supposed to... Paul: Yeah. Three.js, amazing things. I've played games made of Three.js. I've gone to that GitHub visualizer and seen my commits, which everybody should check out if you haven't already. But the big point you were talking about is, I'm excited to talk about Lunchbox because it makes this palette and makes it approachable. It makes things make a little more sense. I'm going to hand it off to you, and I'd love if you'd just introduce the audience to, one, what Lunchbox is and how it interacts with the 3D capabilities and things that we love about Three.js, or would like to love if we were to get into it. Sander Moolin: Yeah, absolutely. Yeah. I have been developing with Three.js for a while. Absolutely love working with it. Can really recommend Bruno Simon, has a really excellent course based on learning Three.js for anyone who's interested in dipping their toes into the framework. Been working with it for a long time, and I've been working with Vue for a long time, and those tools together, I love individually, but for a long time there wasn't really any equivalent of react-three-fiber for Vue. The nice thing about react-three-fiber is that React developers can write code that looks like React, that has the same kind of reactivity and interactivity that React has, this kind of dynamic quality, but it's a lot more, it looks like HTML Markup. It looks like you're just writing regular self-contained components, just like you're used to. I loved that idea. Looked around for a long time for something like that for Vue and found that there wasn't anything, so I started digging into this some more. I started working on a couple games as well in Three.js and got to the point where I was like, I really wish I had something like this. Started looking again, and that's when I found Trois. Kevin Levron had started working on that and he had started to put together a rapper for Three.js where you could write a Vue component and it would handle a lot of the Three.js code for you. Just as an example, when you're working in Three.js, if you want to see a 3D cube, for example, you have to create a mesh, and then you have to create a geometry for that mesh, and then you have to create a material for that mesh. Once you have all those things put together, then you can add it to your scene. Then you tell your scene to render to this canvas. So there are a lot of steps you have to do in order to actually see something on your screen. But Kevin had set it up in such a way where it was really easy to just write a few lines of Vue code and see a result. And it's like, that's perfect. I love the look of that. The only issue I ran into with that was that I wanted some more customizability and that's where I came to, okay, react-three-fiber takes a really interesting approach, where it treats itself more as a very thin layer between React and Three.js, saying that we're going to write some code in React that's going to translate directly to Three.js, so we have to write fewer variables and declarations and stuff like that in JavaScript, but we end up with something that has the same end result. The whole point of jumping into Lunchbox was going for the same kind of feeling of, I want to create 3D scenes. I want them to be maintainable and easy to work with and reactive just like react-three-fiber scenes, and I want to do that in Vue. That's the big impetus behind all of this. Paul: That was a beautiful summary. We got taken from a journey. Sander Moolin: Yeah. We walked up the Brother Bear mountain right there. Paul: So it sounds like the react-three-fiber, it just did the same thing, but in the opposite direction. You went from less information to more information versus more information to less information. Is that a right way to think about it? Sander Moolin: Yeah. So I guess the way we were approaching react-three-fiber was like, I really love some of the customizability options we have here. We would love that in a very lightweight layer around Vue, 'cause we love using Vue. And when I say we, I'm working on a game with Studio [inaudible 00:06:37] Punk, which is based out of Malaysia, with my friend [inaudible 00:06:41] who is writing and developing a lot of the material for the game that we're working on, and this is all in Lunchbox.js. Paul: I have a quick question. When you say material, these are the meshes and the bodies, so this guy's an artist. He's creating a design. What type of application or interface does he come from, doing that? Is he jumping into code Matrix-style and just producing graphics? Or is he going just Maya or Blender, taking inspirations and still files and stuff like that? Sander Moolin: More into the Maya, Blender world. He, in particular, does a lot of 2D stuff, where right now, the closest analogy for the game we're working on is kind of a paper Mario thing where it's 2D-ish sprites moving around in a 3D environment. So we have some of that dynamic lighting. We have everything you would expect from a 3D game and that you can do in Three.js that you can't do in other frameworks or just in regular HTML, but any artist is going to be able to produce just a GLB file, which is the 3D model itself or a texture that you might use like a PNG or a JPEG or something like that that you could just drop into the scene. Paul: You're talking about, okay, it's a 2D-esq sort of game thing we're doing, but it has some flavors of 3D. Is this what we would call 2.5 Age of Empires? Sander Moolin: Definitely. That kind of feel. Yeah, absolutely. Paul: That's such a good game. Those graphics are like, yeah, it's the best happy point I feel like a lot of times. As a non-game developer, it doesn't seem as hard to develop that versus a 3D scene because to make the 3D scene good, oh my gosh, there's just so much. Sander Moolin: Yeah, and that's part of the thing we're running into is Three.js is really, really good. It doesn't compete with something with a Unity or an Unreal. Those engines are just built from the ground up. We're working in C++. We're working in very low level languages that are built to handle things like lighting and physics and all of these really high end details. Three.js is really good at some of these kind of things, but we're playing to its strengths right now, which is a lot more, you can have some relatively small, realistic scenes, just as long as you keep it a very focused-realism. So your lighting has to be pretty intentional and your shadows and that kind of thing have to be like... There's all sorts of ways to optimize it so you can get the kind of performance you would expect, but you do have to think about optimization a lot more right out of the box than you would have to do with Unity or Unreal. That kind of ties into the whole, it's really fun making stylized 3D things. The example that everyone goes back to is Legend of Zelda, Wind Waker aged really well because it was so heavily stylized and has its own character, has its own art direction kind of feel. If you can do it like that or Jet Set Radio Future or one of those kind of older games that really leaned into their art direction, and push that in a Three.js context, you're very good to go. Announcer: Enjoying the podcast? Consider hitting that follow button for more great episodes. Paul: Some of those games, that's why we remember them. There was some games I feel like there's two things. That's just like, if they check the boxes that are very hard to check, Space Pinball- Sander Moolin: Yeah, Paul: ... it's an undeniably good, that reaction is what everybody has when you bring up Space Pinball because it's just like, oh my gosh! Sander Moolin: Yeah, yeah. Oh, I love that. Yeah. Paul: So with Lunchbox, you're taking all this stuff. You're putting in Vue. You're doing Vue because that was where you're coming from. That's like your family, right? Sander Moolin: Yep. Exactly. Paul: But you also have used the react-fiber thing? Sander Moolin: Mmm hmm (affirmative). Paul: Okay. Are you looking to get to the same point of operability that that's at? Or do you think that Vue has some strengths that React doesn't have that you're looking to exploit? Sander Moolin: Yeah, that's a really good question. So right now, kind of parody with react-three-fiber is like pie in this sky kind of goal. That's an incredible project that has a huge number of contributors. It's a very mature project, so something like that is far off in the future. But the nice thing about Lunchbox, the nice thing about Vue is the way everything is written now, even if I were to stop development on Lunchbox entirely, you could keep using it with Vue 3 and with new versions of Three.js. I've been working on Lunchbox for about a year-ish. In that time, Vue Three.js has come out with several new versions, because they're coming out with new versions all the time. The nice thing about that is that I don't really notice the upgrades. You can just install Three.js to install Lunchbox and it'll work right out of the box because the goal here is longevity, in the same way that react-three-fiber has where it's like, we're not so dependent on Lunchbox itself. We're treating it as a translator between Vue and Three and letting Vue and Three make the decisions themselves. I have a development manifesto or something on the documentation side, just talking about it being a good idea to treat Lunchbox as a very thin layer between Vue and Three.js and to let those two frameworks make the decisions, because those are the ones with more muscle behind them, with bigger user base. Being able to do things like support plugins, right out of the box, being able to do things like work with new versions of Three.js, all that kind of stuff is really important to me, so I built that in from the start. Paul: I think that talks to what people try to emphasize, which is a lot of times the most beautiful or best solution is the smallest, then the lightest one, because you allow the shoulders of the giants to still do their job. Right? Sander Moolin: Exactly. Exactly. It's that airplane analogy, where you write as much code as you need to get it working. Where if you're building an airplane, you want to have as much weight as you need to build an airplane, but no more because you don't want to be adding any extra weight or any extra burden that you have to maintain in the long run. So something like that is like let's get the minimum amount of code that we need. Yeah. I read that somewhere and I was like, "Oh, that makes sense." Yeah, exactly, exactly. The less you have to maintain the easier it's going to be in the long run. Because I've been on too many projects where it's like, oh, you get very excited, you have blue sky, open fields, everything's wonderful, and then you have to take a six month break and then you come back to it, and you're like, oh my God, where do I even begin the work that I was doing before? So something like this is designed to be as long-term as possible. Hands-off and long-term as possible. Paul: On, well, if you're rooting yourself in that way and people are coming to the community, it sounds like you're setting yourself up for success in the project. For success. So that's great. Sander Moolin: Oh, I hope so. Yeah. Yeah. Paul: So you were talking a little bit about, okay, we're talking about this layer. It's going to be a light layer between these that very intelligently is going to sort out and translate. One thing in the notes that I have that we're going to talk about is, how we're matching declarative styles and imperative styles of programming through your Lunchbox layer. So before we hop into that, what's declarative and what's imperative and what's the 20 second difference between them? Sander Moolin: So for me, I'm not classically trained in computer science or something like that. So whenever I think of the difference between the two, declarative, I always come back to, we're writing HTML elements, we're writing something like CSS or HTML that is going to exist all at once and react to the environment of the code around it. Imperative, I think of as, we're starting at point A and we're going to end at point B. We're going to go through those. It's going to be a JavaScript kind of thing where we start at the top of the file and then we might do some loops. We might do some branching statements and stuff like that, but at the end of the day it's a linear process. Paul: I think that was a great analogy because ultimately Three.js, that's the imperative side of things. It's code, it's running through, it's a scripting. Then we have [inaudible 00:15:36], DOM, [inaudible 00:15:37] and declaratively. Right? You're joining these two things together. What do you think is the main advantage of having this? Is it speed? Is it the organization? Because a lot of frameworks that comes out sometimes it's guys who are like, I made this so that my team of people can just pump stuff out faster. That's the reason. Sander Moolin: So, Lunchbox, yeah, that's a great question. To answer both of them at once, Lunchbox is handling a lot of the modularization of the code and a lot of the long term maintainability is what I've found with it. So if I want to have a scene where I have a bunch of cubes, that you get one cube rendered for each item in your array, you can add or remove items from the array. I can make a custom component, just like I would in Vue, a self-contained .Vue file. I can iterate over that with V4. I can conditionally render it with VF, just like I would a dot element, and that means that all of my code related to that cube is contained in a separate file and just referenced as if it were any other custom dot element. The nice thing there is that means I can change the color of it. I can make the color a prop that I can pass to it. I can change the behavior of it if it's supposed to grow or shrink or rotate or something like that. Paul: You're defining this API. Sander Moolin: Right. Exactly- Paul: Right. Sander Moolin: ... exactly. Paul: Okay. Sander Moolin: Yep. Yeah. Yeah. The biggest thing I've found with the advantage of declarative versus imperative is that I've tried working in pure JavaScript, pure TypeScript for writing bigger projects like games, and eventually it gets to a point where it's like you have to be very cognizant of how you're organizing it from the start or else you're going to set yourself up for bigger problems that snowball down the road. Switching that over to a declarative style, writing single file Vue components, writing... I talk a lot about how writing Vue components in TSX is one of my favorite workflows, just because everything is typed. If you're going to refactor a variable name, you can just do it right there, and you don't have to worry about searching through your whole project. You can just F+2 and rename it right there. And all that kind of thing is, the easier you make it to write something once, forget about it until you need it again, come back to it, change it, whatever you need, however you need to do, and then forget about it again until you need it again, the easier that is, the less work you're making for yourself in the long run. And the more maintainable project is. Emily: It's Emily again, producer for PodRocket, and I want to talk to you. Yeah, you, the person who's listening but won't stop talking about your new favorite front end framework to your friends, even though they don't want to hear about it anymore. Well, I do want to hear about it, because you are really important to us as a listener. What do you think of PodRocket? What do you like best? What do you absolutely hate? What's the one thing in the entire world that you want to hear about? Edge computing? Weird little component libraries? How to become a productive developer when your WiFi's out? I don't know, and that's the point. If you get in contact with us, you can rant about how we haven't had your favorite DEV advocate on, or tell us we're doing great. Whatever. And if you do, we'll give you a $25 gift card. That's pretty sweet, right? So reach out to us. Links are in the description. $25 gift card. Paul: Yeah, it's plugable, right? Any time I have to revisit a component, it's just like, oh God, I need to be alone and I need coffee because this is going to be brain crunch. Sander Moolin: Right. Exactly. Exactly. Yep. Yep. Yeah, but the nice thing about a Vue single file component that I really like is, you can divide up a lot of the functionality between like, this is your end result in the template code, and this is your interactability, this is your animation, that kind of thing, in your JavaScript or TypeScript, so a lot of that just feels like it segments itself really well, which is really satisfying to work with. Paul: Could we talk about animation? 'Cause for me animations, I use libraries. That's where my expertise stops. So now we're talking about taking animations that natively exist in one framework and porting them to another. Yeah, let's dive into this. How did you tackle animations? How are you thinking about them? Sander Moolin: I usually think about animations in either a Tween-based framework, where it's like we're starting at point A going to point B, we're going to move through a set of key frames and interpolate between those key frames. Or I'm thinking about it as, I like to do procedural animations a lot too, where you get a pulsing cube by setting its scale, to be the sign of the current timestamp. So you get a sign wave and the cube will grow and shrink like you would expect it to. I really like doing shader art and stuff like that, so that kind of purely math-based thing is really, really fun. That's a big part of the reason why I made that custom OnBeforeRender, OnAfterRender in Lunchbox.js, was that it just came back to I want a way I can reliably call a render function before and after the scene actually renders, so we're manually rendering. We have a custom render function in Lunchbox.js, which is something that's a little further outside of that paradigm of being as hands-off as possible. I thought that was a good trade off to make, just in the sense of this way we get some more control over when the scene is rendered, what happens before and after that actual render, all that kind of thing. Just to say Three.js has a lot of OnBeforeRender and that kind of thing, functions, built in. But for this, I wanted a little bit more control where it's like, I want to keep on doing my procedural animations in a way that I know that I can come back to and just use as if it were a hook or something like that and react when it's just OnBeforeRender, passive [inaudible 00:22:24] function, and it's doing exactly what you would expect it to. Paul: What's something that I'd want to render onBeforeRender? Sander Moolin: You might want to do, let's say we're coming back to that example of a rotating cube or something like that. You could say OnBeforeRender you're going to increase the rotation amount by 0.001 or something like that, and then you'll see the cube rotating in space, just so that you can have control over how fast it's rotating over the axis, where it's rotating, something like that. Paul: So the reason why you would want to rotate OnBeforeRender versus after render... I'm missing this link right here. Could we iron that over one more time? Sander Moolin: Definitely, yeah. So in most cases, in 99% of the cases I've come across, before render is just a convenience thing. Just like I choose to make the change before the scene render because it's neater in my head where it's like, oh, I want to change something and then render the scene, as opposed to render the scene and then change something. Where it starts to come in useful is where you start thinking about different layers in the Three.js context, where you think about turning objects on and off, where you think about being able to change a material for the duration of the render, and then change it back afterwards. There's situations where something like that happens, where you want something to be different that you're not necessarily seeing in the render. I've run into things like that, where it makes sense. I don't have a really good example off the top of my head. Paul: But this is one of those things where this extra life cycle hook allows the wrangling of Three.js to be just more powerful- Sander Moolin: Exactly. Paul: ... okay. Gotcha. So you're like, trust me, you're going to use Three.js. You're going to want this. You'll get it. Sander Moolin: Yeah, exactly. Paul: All right. We can roll with that. So where are you going with Lunchbox? What's the next set of features you're looking at? Or where are your eyes sitting next? Sander Moolin: Yeah, so couple places. Right now, I would love to support DOM element rendering right out of the box in Lunchbox. Right now, to mix Three.js with the DOM in Lunchbox, you actually have to have two separate Vue apps on your page, which is something that's very doable in Vue 3, very easy to work with, or relatively easy to work with. You can make them share reactive variables and that kind of thing. I've gotten them to work with the same instance of a plugin, for example Vuex or boardgame.io, can come back to using the same plugin. So they're both referencing the same source of truth. But, I would really like not to have the overhead of two Vue apps on every single game I'm working on or every site I'm working on because I would love to just be able to write a single one and keep that maintainability easier. Building in a DOM render out of the box, I'm doing some work with a guy named Karine, I think his name is, or Karin, who is a Dutch developer working at a biomedical place where they want to have a few instances of Lunchbox on the same page, which currently is impossible because I'm just shifted with some global variables to make it easier to write. But we're shifting that over to some scoped variables so that you can have multiple renders on a single page or multiple Lunchbox apps on a single page rather. Paul: That's such a big under undertaking it sounds like. Sander Moolin: It is. It's really interesting. Yeah. And one of the really cool things about it is, it taps a lot into Vue 3's new features. The custom render feature is something that is brand new to Vue 3. This wasn't possible in Vue 2. I remember going back to Vue 2 and trying to do this kind of thing and they didn't have a custom render then. That's a new thing in Vue 3. Then also mechanisms like provide and inject in Vue 3, where you can have app level passing information between the grandparents and grandchildren, as opposed to just the parent-child component communication that we're used to. All this kind of thing is- Paul: That's nice. Sander Moolin: Yeah. No, it's pretty fantastic. Yeah. It's really fun to work with. Paul: 'Cause it's just increases your bug surface area so quickly when you can't do that. Sander Moolin: Yes, exactly. Exactly. When you have to pass props down through several layers of children or something like that, just turns into a headache. Paul: It actually does. Because also depending on the component, the name of the prop's going to be different. Data up here is not data down here. It's going to be part person or right. Yeah. Sander Moolin: Yep, yep, yep. Yeah, exactly. Yeah. So the fewer places you have to declare something, the fewer places you have to, I like that bug surface area analogy, that makes sense is, the less surface area there is for bugs, the happier you're going to be in the long run Paul: This custom render function from Vue, is it just for powering up Lunchbox? Are you excited about it just for the Lunchbox framework or is there utility being used for this new way to interact with the Vue core that you would urge people using Lunchbox today to look at? Sander Moolin: That's a really good question. I would definitely urge people to check it out. I feel like this is really, as far as I'm aware, a pretty underutilized part of Vue 3, where the custom render side of things is just such a powerful... the whole exciting thing behind something like React Native is you can write React code and then see it natively render on iOS, on Android. How cool is that? Something like that is possible with Vue now, just needs a lot of work. It's not like, oh, just go ahead and make it. It's more like this capability is here, and I definitely think it's worth a look. It is one area where I see not too many resources are available right now. Something I want to do is write an introduction to some basic renderer terminology and Vue custom render terminology and workflow and stuff like that. There is an existing one by Lachlan Miller, who is a developer who wrote, I think he did a tutorial on how to make a custom PDF renderer with Vue. So, L-A-C-H-L-A-N Miller, M-I-L-L-E-R. Definitely worth a look for his tutorial. That's and the Vue DOM render itself are the most comprehensive examples I've found of how to create and maintain a custom render. But that's definitely worth more of the look by the community. Paul: Thank you for spelling it out, because it's always difficult sometimes to know how to spell these names. So that's really great. Now, since we're on the topic, if people want to get into a, Three.js, B, Lunchbox, or, I was going to say C, this area Vue where we're starting to talk about some of the core rendering and the life cycle things, but more on Lunchbox 'cause that's what we're talking about today, where should people go? Sander Moolin: For all of them, I think, those are really great questions to ask because all of them are so interconnected with each other. The really fun thing about Vue and all of these frameworks is, when you start to speak the language of one, it's so much easier to learn the language of the other, and then your knowledge and capabilities just kind of grow, which is just a really fun feeling, just a really nice experience all around. So for Three.js, I think I mentioned Bruno Simon's Three.js Journey. That's a really good course. That one costs money. There are some that are available for free online, but that one is a very in-depth course. I was able to take that one through work and had a really good experience with it. Then for learning Lunchbox, I think it was LogRocket that put out a really good tutorial, an example of how to create a globe scene with your own custom textures and your own custom displacement mapping and stuff like that, which was really, really cool to see. Yeah. LogRocket had a really good tutorial along that. Then I think they direct you to the Lunchbox documentation site as well. So you can just go to lunchboxjs.com and we have a link to the source code, the GitHub repo, the documentation site, which has some more of the theory, but LogRocket has a bit more of the tutorial of this is how you jump in and start building with Lunchbox.js. Then as far as the Vue 3 custom render stuff, I think I link to it on the Lunchbox.js documentation site, but somewhere in the internal development section. I have a link to Lachlan Miller's tutorial, and I have a link to Vue's core DOM renderer, which are both excellent places to start looking. It does take a little bit of manual looking around there, so that's why I'm looking to create that tutorial of this is how to get introduced to the world of custom renderers, which is a really, really interesting world and a really cool problem that Vue 3 has solved. Paul: Yeah, like you said, I just don't feel like I've seen much out there. You found a good area to really contribute, because it feels good when you find something that not a lot of stuff out there exists, and you're like, I'm going to do it and people are going to read it. Sander Moolin: Exactly. Yeah. That's the exciting thing about Lunchbox was, this was the tool that I wanted when I was working on my game two or three years ago, by this point, when I was working on my games. Paul: Well, keep writing, keep having this desire to write documentation, because the easier you make the transfer of your mental model into my mental model, then it's easier for everybody else to- Sander Moolin: Yeah. Paul: Yeah. It's great. Your eyes are set on doing things like that, and hopefully people will start to get attuned to what's coming out and what they can do with this. There's a lot of hardy Vue users out there. They keep coming on our podcast, so really wish the best for Lunchbox and everything you got going on. Sander Moolin: Thank you. I really appreciate that. Thanks. Paul: Heck yeah. Well, thank you for your time, Sander, for joining. This was a really fun one, talking more about the graphical and creative sides of what our awesome, modern frameworks are allowing us to do now. So, Sander, they're on Twitter. Do you have a Twitter handle? Sander Moolin: Yep. Sander Moolin. S-A-N-D-E-R-M-O-O-L-I-N. Then also Lunchbox.js has a bunch of official Lunchbox examples. Paul: Well, thanks again, Sander, and hopefully we'll have you again on, some time in the future, to see how things are going. Sander Moolin: That would be lovely. Thank you so much for having me. I really appreciate it. Emily: Hey, this is Emily. One of the producers for PodRocket. I'm so glad you're enjoying this episode. You probably hear this from lots of other podcasts, but we really do appreciate our listeners. Without you, there would be no podcasts. And because of that, it would really help if you could follow us on Apple podcasts so we can continue to bring you conversations with great Devs like Evan You and Rich Harris. In return, we'll send you some awesome PodRocket stickers. So check out the show notes on this episode and follow the link to claim your stickers as a small thanks for following us on Apple Podcasts.