 Hey there folks, Rob here. Welcome back to the show. In the last episode I was showing off Polymer starter kit to one of our new Polymer CLI generators. Today, I thought it would be really cool to demonstrate how you can actually build your own generator for Polymer CLI. So follow me over here to my laptop and where we want to start is over here on the Yeoman website. A Polymer CLI generator under the hood is really just a Yeoman generator. And if you haven't heard of Yeoman before, it's a little utility for scaffolding out projects for you. So it'll stamp out your files. It'll do a little bit of variable substitution and renaming for you. And it's generally a very useful tool for just kind of like getting up and running with a nice boilerplate. So the first thing we're going to do is we're going to go over to our terminal and we're going to run npm. I'll bump this up a little bit so you can see it. npm install-g. So we're going to globally install Yo. Which is the command for Yeoman. And this thing called generator-generator. And that's actually a Yeoman generator that will generate Yeoman generators for you. So you can run that command. It'll take a second to install and then I'm going to go over to my desktop and I'm going to make a new directory and every Polymer CLI generator needs to start with the prefix generator-polymer-init. And then you can give it whatever name you want for your own generator. So I'm going to call this template seed. So it's a bit of a long name there, but that prefix is really important because that prefix gets picked up by Polymer CLI after you've installed the generator and and that's how it actually can tell you, hey, this is the thing that we want to init. So I'm going to make that directory I'm going to cd into generator-polymer-init template seed. Now I'm going to run Yo. And it'll give me a few options for things that I can generate. I've got a few other generators already installed, but the one I want is this one. That's just called generator. So I'll do that and it's going to ask me some questions. I'm just going to fly through here and just take all the defaults, right? Skip all that stuff and it'll take a second. It's going to stamp out a bunch of files for me. And it's also going to npm install all of the dependencies to make Yeoman run. So wait a moment for that to do its thing. npm install takes a very long time. All right. So we're done. We've installed all of our dependencies. And I'm going to open this up in my code editor. So over here in our code editor, I will I'm going to embiggen things a little bit so you can see it created a number of files for me. Package JSON, read me, bunch of stuff. The one that I really care about is this generators directory inside of here. It's got an app directory. It's got a templates directory, which right now contains this one file called dummy file.text. And then it's got this index.js file. So let's open that up. We'll look at the index.js file. There's a lot of JavaScript here, but most of this is stuff that you don't really need to worry too much about. Basically, there is a little section here at the top in this prompting function where it will sort of speak to the user in their terminal, ask them questions about the project that they are setting up. This is a good place for you to create variables that you can then use elsewhere in your templates. So for instance, right now, it's just got this default example prompt here. It's a confirm style prompt. So yes or no prompt. And it's going to ask you, you know, would you like to enable this option? Just sort of like made something up. In our case, what I want to do in our generator is I want to have like a kind of a default element that the user uses as sort of like the root of their application. So we'll change this to an input prompt. We're going to change the name of the variable to element name. The question is going to be, what would you like your root element to be called? And we're going to give it a default value of my dash element. So now we've got this element name property that's just available to us throughout the rest of our template. Now there's also this writing section. This is where it's going to copy all the files from this templates directory onto the user's computer. So in this case, you can see that it's copying that dummy text file from the template path and it's dumping it to the destination path, which is basically whichever directory the user is currently in. So what I want to do now is actually instead of just using this one dummy file, I want to have a few real project files. And I'm going to go over to Polymer Starter Kit and just steal a few things from here. So we know we want to Bower JSON. So I will open this file up. I'm going to grab its contents. And because this is like a pretty simplified generator, I'm just going to really slim this down. So I'll say the name of my project is just going to be, you know, my dash project. You know, authors are whoever. The dependencies, I'll just say right now that the only dependency is Polymer itself. Maybe this is like a really tiny generator to get people up and running really fast. So this is like the world's smallest Bower JSON file that we could have. So we've got that. Now let's also create an index HTML file. I always want to have one of those. Again, we'll go over to Polymer Starter Kit and maybe just steal the one that is over here. So we'll say, all right, give me the index file. Okay, dump that in here. I can actually remove some of these things that I don't care about as much. So I'm not, for instance, going to, maybe I'm not going to import a bunch of elements or anything like that. So let's see, we'll get rid of these critical styles. Maybe you don't care about those. The element name, we're actually going to ask for that name from the user. So instead of just having a hard-coded element name right here, we're going to use some of Yeoman's templating syntax. So it actually uses the sort of, the syntax kind of looks like this, where if you want to expand a variable, you say bracket percent sign equals, and then variable name, you know, whatever that is. And then you say percent sign, and then you close the bracket, right? So this is how you do variable expansion in Yeoman. What I'm going to do is dump that into this tag here. So I'll say, all right, I want this to be that element name that I'm going to prompt the user for, and then we're just going to close it and also say, hey, that should also be the element name. And we want to steal this and also use it for our import up here. So source directory, we're going to have whatever element name they want in there. Let's see, what else do we have here? We've got this little bit of JavaScript that is going to lazy load the Web Components polyfills, that's good. Normally we would be, you know, if you want to build a progress web app, you might ship a service worker to keep things really simple. I'm actually going to remove this little chunk right here. So we won't worry about service workers right now. We're just going to have like a super bare bones polymer app. Otherwise, I think we can leave pretty much everything in this file. We can get rid of this dummy file, don't need that. Get rid of that. The last thing we want to do is we want to create a source directory. And inside of here, I'm going to create a file and I'm going to call it underscore element.html, okay? And the reason why I'm doing this is because remember, the element name is something that the user is going to pass into us as one of their prompts. And so we don't want to hard code a file name for that element. Instead, we're going to also take that file name and generate it based on the prompt that the user, the answer that the user provides to the prompt. So the contents of this element are going to be super simple. We're actually just going to grab some boilerplate code here and dump that in. And what we're doing is we're importing our components. We've got our element name, element name for the is property, element name for the value down here. So this is just sort of like a really, really basic polymer element. It doesn't really do anything. It just sort of like says the value of one property inside of an H2. The cool thing that we're going to do though is we're going to go back to that index.js file. Remember, this is the one where we prompt the user for the element name and we have this little writing block here. And I'm going to replace that writing function with a custom one that I created earlier. And I'll walk you through what's happening here. So inside of this writing function, we are taking the element name, which we got from our prompts. This is stored inside of this props variable here. So we're creating a reference to that. And then we're saying that we want to copy our template files over to the user's machine. We're using a regular expression here though to say, hey, anything that starts with an underscore, like that element HTML file that we just created, hold off, don't copy that just yet. Instead, just copy everything that doesn't have an underscore over to the user's computer. That's stuff that we're not going to worry about templating or anything like that. And then we're going to specifically tell it to copy that element HTML file from the template path and then to the destination, we're going to use an ES template literal string to actually generate that file name based on the element name property that the user passed in. So I think we've got pretty much everything we have or everything we need to test our generator. The next thing that we want to do is actually kind of like hook it up. Normally what you do is you would publish this generator to npm, a user would globally install it and then they could start using it using Polymer CLI. But before you do that, you probably want to test that the thing actually works, right? And so to do this, we can use a handy little npm command called npm link. So when I run this command, it's actually going to create a symbolic link on my system for this generator. It's as if I globally installed it, but really it's just linking to this directory on my file. So this is really, really useful anytime you're testing any npm library that you're working on. You can kind of pretend like you've got it installed on your computer, make local changes, and it will just update automatically. So now it's as if we globally installed it. So I can go over to my desktop now and bump this up a little bit. I'll make a new directory. I'll call it polyfoo, something like that. Just cd in here. And now I'm going to run polymer init. And we should now have this option down here for this template seed thing. Because remember it's taking that prefix, generator, polymer init. It's chopping that part off and it's just using the last part of our module name, which is template seed. Run this puppy. It's going to ask us some questions. Hey, what would you like your root element to be called? By default, it says my element. I'm going to call it instead like my widget or something like that. Then it's going to copy that file over. It's going to run bower install and install polymer for us and our weapon opponents polyfills. So as that's running, see it looks like it's finished. Now we could open up this project and we can see over in our code editor that we have our index HTML file. We bump this up a little bit so you can see it. You can see that it is pulling in our my widget element. We've got my widget down here in index HTML. We've got my widget in the source directory. So the last thing really is just to run Polymer serve. We're going to cross our fingers and we're going to go over to localhost 8080 and we should see right there, boom. Hello, my widget, just as we were expecting it. That about covers it for today. I would encourage all of you, if you want to go start creating your own generators, put them up on GitHub, put them up on NPM, ping me, let me know when you create them. I definitely want to share them out to the world and get as many people building these cool CLI templates as possible. If you have any questions for me, as always, you can leave them down in the comments or ping me on a social network of your choosing at hashtag as Polymer. As always, thank you so much for watching. I'll see you next time.