 How about now? Can you hear me everybody in the back? Raise your hand if you can't hear me. It's a weird question, right? So my name is Josh Pollock. I'm the lead developer for Cadera Forms. And I bring that up to mention that what we're going to talk about is kind of the more complex version of what Brian just showed. I'm going to start out, you know, something very similar to what Brian was three or four days ago and we synced up on this. And then we're going to slowly modernize it using modern tools. And the reason for this is that what Brian just showed is a good way to learn. And if you're doing a quick block like the one that he showed that creates some static HTML or has one or two settings or is replacing a short code, then that's great. But it's not really going to scale if you're doing large complex plugins. And that's kind of my world is doing big complex plugins like a form builder or custom things for specific sites. And we're going to start to get into a little bit of an opinionated look at what a complex block plugin looks like using a little bit of React, using JSX, using esnext syntax. And when I say a little opinionated, a lot of this is based off of a plugin called GCF that is by Riyadh. I will not attempt to pronounce his last name. Who's one of the core Gunenberg developers in a really this GCF plugin. It's in the WordPress plugin repo. It's on GitHub. It's a really good example of how to write a complex WordPress plugin with Gunenberg. And so a lot of this red pack and other conventions are like Zach and I figured out based on Riyadh's stuff. So there are slides. This slide deck which has very little in it. It's kind of an outline. That's a shortened link for it. And then this GitHub repo is the example code. And I kind of, as I went, made commits that said each step. So one of the things that you can do is if you check it out with Git, you can go back and check out the first commit and see something super basic. And I'm basically going to walk through this process with you today. And again, we are starting to talk about modern tooling. So when you pull that plugin down, if you just activate it, you'll get an error. Because the actual JavaScript file that it's trying to load doesn't exist. That's because we're using NPM to build out a plugin JavaScript file. Because some people here who might be more experienced with JavaScript might have been looking at what Brian was doing. You're going, hold on, you're running JavaScript and JavaScript? This is 2018. Like at least he was using JavaScript to write HTML. But do we have any CSS folks who are like, hey, what about SaaS? Like he was cutting and pasting CSS into two places. In 2018, now, it's a good educational experience. But anybody who does this, it has multiple blocks. That's the kind of problem that SaaS solves at CSS. So we'll show just a little bit of how to build, use CSS in your blocks. How to use other React components in your blocks. And this resolve involves a little bit of modern tooling. It's a little bit more work to get set up. In a more complex plugin, it's worth it. In a simple plugin, probably not. So do you need webpack? No. You can build your block that wpcli command. That means absolutely nothing else. You can ship that tomorrow. You might want to add minification. But webpack lets you use newer syntaxes, With JavaScript that might not be supported. For instance, if you want to use ECMAScript 2018, which i don't think is approved, But there's a babble preset for it, we can compile it back to browser-safe JavaScript. So if you want to use SaaS, you want to use esnext, you want to use jsx. These sorts of things, your reasons to use webpack and take on That extra complication become worth it. Every bit of software complexity better be worth the trade-off. What is jsx? Jsx is a simple templating language that is used in a lot in the react world. It's not required. When brian was showing how to use that create element function, Jsx is basically a different way of doing the same thing. Under the hood, react figures out how to use that create element function. So it's just a little bit of a more expressive way of writing it. Some people hate it. Some people love it. We'll take a look at it, and you can decide for yourself. So we're going to show how to use webpack and jsx together. I'll kind of skip over scaffolding tools because right now you've got Wpcli, which is pretty basic, but there's a lot of work going on To make it more complex, what it can do. And then create gunenblock. And i've also used create react app And just kind of done a little bit of work to it to make it work In wordpress. Just like i've done with viewcli To create a webpack configuration for plugins. It's not that much different. So block attributes, we're going to cover very briefly before i go in. We kind of talked about them as fields or settings. But this is where wordpress starts to get into declarative fields. And we'll look at that in a second with block attribute types as we Start to make this more complex is that we can say this is an Attribute that has to be a string. It has to be an integer. It has to be an array. It has to be an object. We can say if it's required. We can say if it's not required. We can say what its default value is. We can say whether or not it's stored as meta data instead of Post content. So this is something that's a little Bit more declarative than we've done before in wordpress. But it does make it a little bit of a better developer experience In my opinion. And i want to mention that once We get into that, i can show you how to change from storing Post content to post meta with one line of code. But we will have to talk about how the wordpress rest api plays into that. So let's jump into some example code here before we move on. And it's the wrong application. I have, i just installed this GitHub app because i think it's kind of nice. If you look here, this is a laser mode. Yeah. This is kind of the commit history of As i was building this. So this initial commit is i Kind of pasted some stuff that brian was using as his start Point. It's a little bit different because He's put more work into it in the last week. And then we added some extra stuff and then we started Rewriting it with modern. Figured out how to do the CSS. Figured out how to do bootstrap as My alert message. You know, fixed a mistake. And then started using components to make our code more modular. And by making it more modular, it becomes reusable. We can start to have complex discussions about how we're going to reuse These same react components on the front end. So let's, can i roll back to this? Okay. So this should jump me back to a pretty Empty plug-in. I want to go over the fact that We have a webpack configuration here that is not terribly Different from a standard webpack configuration. The one key, two key things that i wanted to point out here Is these are my entry points. So the idea behind webpack is that you're able in your javascript Land, at least, to say i need this, i need this, and it Figures out the most efficient way of loading javascript. So i used to do theme development when i started and i was Constantly breaking things up into smaller modules and then Manually queuing them based on which feature. I was breaking all the roles in terms of having tons of Functionality in my theme. It's like 2015, leave me alone. But i was doing all these weird and queued scripts And only loaded the javascript and css for each feature. Now webpack can figure that stuff out on the fly. But by default, webpack only creates one bundle, one, you Know, one file that we load. And that's a problem because I'm going to have a lot of components for editing that i Really don't want on the front end ever. So i'm going to add two entry points. I'm going to add one called, well, okay, it doesn't Really matter. We gave it this old name space. But it's blocks and then front end. And you'll notice if i open Up scripts here, i'm going to have blocks and front end. So that means everything in blocks creates one bundle for The admin. This is all, so i understand That this is hard to see. This is all on github if you Want to see it on your own screen. Zach, can you maybe show them how to do that? I don't think that it's going to zoom, to be honest. If somebody has a better way of solving this problem, please Come up and solve it because i don't know how to make it bigger. I don't really know max very well. Does command plus work? No, okay. That's what i'm doing. Does anybody else know how To solve this problem? Then you just hold control and zoom in. My keys are real, not mac. They're pc, so it's There in the backwards. I'm sorry? Oh, we put it over here. I don't know how to use it. Because it's that weird full screen mode. I'm not a fan of mac interfaces. So i switched back to mac against my will recently. And i have some gripes with the finder. Yeah, i don't know what that is. And i heard we used spotlights. The first mac that i used was an lc2. I think my dad got it. So i've been using forever, but I bought it a few years ago. For whatever long boring reason, i bought zack's old computer. As you can see, it's a mac. You bought an old mac? Yeah. I didn't want the touch bar. I didn't want the out of date processor. And it's cheaper to buy it used. And i wanted a big-eyed screen. When an old mac is like, oh, i need to buy a new one that's got this or that. It's got a fast processor. It's got 16 gigabytes. 15 inch? No, 15 inch. It's the same speed for $1,000 less when you buy it used. Yeah. It's 10 years old. Yeah. I mean, i was using a desktop and boot to machine before. Can... So you do have your keys switched? Yeah. I have them corrected. Oh, okay. So then if you do command, and you just... You can zoom in my... Okay, does that work in phpstorm? Yeah, wherever that window went. What's that wooshy mode? Oh, there you go. Okay, so now just do command, and you can zoom in. Oh, okay. Thank you. Round of applause. So here's the thing. I'm really good at web development and reading science fiction novels. And i'm bad at everything else. So i don't know anything. It's like, how does a computer work? I don't know. Outside of WordPress. So what i was saying is, we have blocks, front end. These are our entry points. And if we open up this directory here, it's going to generate for us Blocks slash build slash index. And that's what we actually enqueue to load in the admin. And then this front end file, which right now doesn't really do anything. We'll get to it later. It has a build index right here. So that's going to get... we can load that in the front end. So we have two javascript files. The front end bundle can be a little bit lighter weight, because we don't need all of our kind of back end stuff. If we go in here to this alert block.js, this is basically... This is like where Brian was before he cleaned it up for the presentation. This is like what he sent me he was going to use. And you can see this is very similar to what he has. And if anybody says, like, Josh, there's no reason to use es6 and babble and stuff for this, you'd be correct. We'll get there. So I wanted to point out that this is all the same stuff. We're just using wp.blocks.rich text. All I've really done is changed it to a constant, because I don't know es6 and now we use constants. And then from a structure point of view, you'll notice that this doesn't actually register a block. It's just exporting an object literal. That is my block settings. And then I have my actual entry point is going to import alert block name and alert block. Yes. So now I have register block type here, and I'm using its name and I'm using that object. And then I'm collecting them all and I'm dispatching an action. We're not going to get too much into wp.hooks, but wp.hooks is a javascript event system that has a very similar syntax to the WordPress php event system that we call hooks. So we have this event system that we've been using since, I think, b2. I don't know when it was added to WordPress. That allows you to add a filter in your plugin, apply filters, and then somebody else has a plugin that adds a filter. This is a thing we've done in php.lan for at least a decade. This wp.hooks do action means that I have this array of all blocks. Somebody else, some plugin developer, some add-on developer, wants to use that configuration for whatever reason later on, and only run whatever code they're going to run after the blocks are registered. Well, they can use this action. They can use wb.hooks.add action to go and do that. In the handbook section on extensibility, it has good documentation on this, and this wp.hooks package is on npm, so that actually has even more documentation there, and it's readme, and you can bundle it with other software you're working on. So that's kind of it. This is very much exactly where we left off. Even the props.focus didn't get changed yet. And again, this is not a...let me zoom in here on my save. This is the same stuff that he was doing. This is not a good use for webpack in ESX. So let's start modernizing this code. I'm going to jump back to GitHub real quick. Oh, man. I'm using my app. What was it? Command? No, because it's not the standard keys. No, but the plus minus doesn't work here. Okay. Yeah, the standard... Oh, there we go. It's down here. Okay, so if we go here, and let me just copy... This hash...I'll see if this is caldera forms now. I don't like this editor. This app works. I just need to get to the commit hash. Okay, so now we're going to see a very similar... And I'm going to do the save block live. This is the exact same thing that we were seeing last time that Brian showed us here. Let me zoom in. Maybe. I have no hand-eye coordination. This is why I do computers for a living. So this looks weird if you've never written, React or done jsx before. It looks very similar to HTML in terms of... Look at this. Div, semicolon. That's HTML. Class name. Well, because class is a reserved keyword, we can't use class. So we have to use class name. It transfers that later back to class. Don't worry. And then you see how we have pulled out the brackets here? That allows us to use a variable. What's my variable here? Attributes.message. This is a little bit different. If I zoom up here, you'll notice that in my edit callback, I'm using an es6 deconstruction where I'm breaking down that props into these individual parts of that object. So like Brian showed, props.isSelected. Or props.attributes.message. Well, that gets old because there's a lot of this stuff. So I'd have to start every edit callback with, you know, attributes equals props.attributes isSelected equals props.isSelected. That's just boring. It's repetitive work. Instead, I can use esNext deconstruction. Somebody correct me if that's the wrong use of the word deconstruction to break these out so I just have attributes. This is functionally identical to props.attributes from the last example. But it means that I can have attributes.message here. It means I can have class name here. Right? These are the... And I can pass isSelected here. Also, with JSX, these are the same. This is functionally identical to writing value equals quotes in then a hard-coded, you know, message. And I actually don't have to do this here where I'm doing the curly brackets and the quotes. I actually, like Zach called me out on that yesterday. I was like, oh, I forgot that's not required. But the reason why I do it is that maybe later, That's variable. And so it's easier to swap, Just pull out the inside then, you know, get rid of the double quotes and stuff. So this is very much like html with JavaScript mixed in. The joke is that, like, this is if you love javascript In your html and angular is the opposite way around. Angular is html with javascript mixed in. This is like javascript with html mixed in. But everything we need here is very similar. This on change message, remember brian created function update message? Same thing. We're using an arrow function. Just because it's, you know, yes, six. And arrow functions, if you've never used them, they look a little bit nicer. But the real value is a real, like, value to switching into this way Is that it doesn't create a new scope. So inside, if you use the function decoration, inside of the function, This is a different this. Whereas inside here, it's not a new scope. So this is the same this as above it. And that changes what you can do in terms of that in constant. So it's just a little bit of a more useful syntax. But remember last time brian had props.set attributes? And use that to write, I want to update the attribute message using value? Same thing. Just a little bit more modern looking. Gives us a little bit more flexibility as we grow. Especially as we start, like, i think in my finished example, I have, like, five of these. That's getting boring. I'd start to extract them into different functions. Or i'd come up with a function that, you know, factory pattern That dynamically generated these functions. And that's where this kind of syntax gets easier. So what i want to do now is i want to kind of live code Updating the save callback. This is the next commit in the history. But just to show you how this relationship works between this L functions, create element function that we've been using the whole day. And how this jsx works to create the same thing. And it's just important conceptually to remember that under The hood, jsx is creating these. So jsx is, like, an easier way sometimes. I like it. I use it a lot with React and with view, but you don't have to do this. So i'm going to get rid of this. By the way, if you're using php Storm and it's, like, your syntaxes are weird, you have to tell it It's a jsx file, and then it'll figure it out. Web storm, php storm, i assume visual code studio, they all Know about jsx, but sometimes you have to tell it it's jsx. So, like, my screen isn't throwing up weird errors, So that's totally not valid javascript, because it knows it's jsx. So the first thing i'm going to do, i'm kind of just going to Come down, because it's just too much weird count and paste. I'm going to go class name equals, let's do that deconstruction here. This is going to be attributes, comma class name. So now class name equals class name. Close off my div. Close it down here. Same rules as hdml, right? You have to close your element. And then the inside is just going to be attributes.message. So we'll use brackets here. What did i do wrong here? Oh, i didn't change. I don't need the semicolon. There we go. Thank you php storm. I don't know how to write code without you. So now, i think that's a little bit more expressive. This is a little bit of extra work to get jsx compilation working, To get your id set up for it. But this is so much simpler to Meet, personally. It's a matter of preference, right? As i said, we're going to get into some opinionated things here. If this is useful to you, use it. If you don't want to use jsx, don't use jsx. But i happen to think this is just easier to write, especially as things get more complicated. And so what i'm going to do here, is i'm going to open up the terminal. And i'm just going to drop this in here. npm run dev. I'm going to npm update just to make sure i have everything. This is just going to update my dependencies. I'm just worried because i keep jumping Between branches that i could just have the wrong stuff in node modules. They're jumping between revisions. Can i see the bottom of my screen, please? Delete node modules, reinstall. There we go. Okay, so build it. npm run build in this scenario Builds for production. So when you, web packs kind of Built around the idea that you're going to do a lot of stuff that isn't as efficient When you're developing, that you're going to want to kind of undo For production. So we have two build steps here. So npm run dev in this setup will do two things. One, it'll build everything in an easier to debug but less Efficient manner. And also it'll start this file Watcher. So that way, if i close out my terminal Here for a second, you can see it's doing this watch. So as soon as i change, say, this, it save, it's going to Happen really quick down there if you saw that. It's just going to go in and make a change. And if you have a more sophisticated setup, you can Actually have it refresh your screen or do what's called hot module Replacement where it just grabs out the module that you just Changed and replaces that. Really neat stuff you can do with webpack. But this is, again, one attribute. It's the same one that brian had. And the one thing that i'm doing Here is that you'll see my selector. That's the class name. And i'm writing it dynamically. And this is just a file that i've imported that i only have One class but i can add more and more. Because we've had this Conversation a few times about how does it work in my theme, How does it work in my front end. I honestly don't know Because i would be happiest just writing json apis and Like frameworks for other people to create front end code. But i know as a developer that what's important for Designers and for seo is consistent html with the right Classes and the right order of elements. And i want that to be Clean. I don't want a bunch of extra stuff there. And i want to make sure that it's always the same class so That way the css doesn't always applies as i change. So one of the things that makes that easier for me because I'm bad at writing the same thing twice is just having this Thing that i import into every file that gives me my class So that allows me to here put this on that element but also In my save callback if we expand this out you see that i'm Inserting it here. So that way i know that that's Being consistent and if i need to change it i can change it At one place. Again it's a strategy for complex Plugins. We're sort of starting a complex plugin Here and you can figure out how to go bigger from there. Questions before we move on. There's a hand in the back if Somebody can bring in the microphone i don't know where it is. I got it. Could you make the logo bigger please. Any other questions? Any other questions are we going to move on? Oh sorry. There it is. But it's again it's html like. This looks weird if you've never done this. Give it a day. You'll love it. Because it's much more expressive. Let's move on. What was my next step here if i look at my commit log? Let's zoom out. Let's actually look at this On the front end real quick. Because i want to make the point That like i just want to make sure this isn't going to Load. This is just my front end Thank you. Let's go over to wordpress. Let's zoom out here. You can tell this is a test site. Most of my posts have no content title. This is my alert Block. And i can just say alert. Right? And you can say wow josh you've Reverse engineered the paragraph block. But it has less functionality. Well hold on. Let's start talking about what we can do here with this. For example i'm going to here in my alert block you'll see i Have this cut out import. This is my scss file. So now when i do this if i go into my editor.scss That's not going to be the correct class name because That's whatever i cut and pasted this out of. But my correct class name is going to be somewhere up here. I missed it. This is i guess why we need Css and js. Here it is. That's what i'm looking for. So if i drop this in here if i do this here then i can Do like background equals red. I'm real good at css folks. And this was probably inside of a div inside of that. It doesn't really matter. My point is as long as it compiles Back to css this should vote. And i'm not going to get too Sophisticated into scss. My point is to have an example Code for you all that shows how to build. Work with scss. So we're going to remove this. We're going to add another one. And now, right? So now i have this super basic alert. But that doesn't look very good, right? And again, i'd be happy you're just doing back end stuff. So whenever i need something to look good, what do i do? I use bootstrap because it looks good. And everybody already uses it. So what i've done here is when i set this up, It was one of the earlier steps. I included react bootstrap. React bootstrap is a set of, it's an open source library. It's something that i found a few months ago and started using. That basically gives you all of the bootstrap components, the Grids, the alerts, the popovers as simple react components. And remember what we keep saying that WordPress is This WordPress api for create element for components is An abstraction over react. So what does it take to Use a react component library? Nothing. Just install it and use it for the most part. Sometimes, like for this one, i had to have react dom Installed so i installed it. But let's give this a whirl right here. If we go in now, if i import alert from react bootstrap And then we look here at react bootstrap slash component Slash grid so i can figure out how it works real quick. Yeah. Here we go. So let's try this right here. Let's go in down here. And what i'm going to do, first, I'm going to make this conditional here. This is the syntax for a conditional. So if is selected is true, everything inside of these Brackets here are going to show up. And then we can add another One of those called with the reverse. And then let's drop in that alert. So the idea here is When you're viewing it, you see the paragraph editor, that Rich text editor. And then when it's not there, right, We want to just see the message. The way that it's going to Look in the front end. Yeah. Well, nodes aren't really a library. Nodes of dependency as a Task runner for npm. To compile this, you would need Webpack installed and webpack into a run npm install on the Plugin. Yeah. Yeah. We had a question in the back, but this question to repeat Was what do you actually need to compile this? We have a question in the back, but wait for brian, please. Are you doing an import of an scss file within a jsx File up above and the top of this file? Well, inside of a javascript file, yeah. What is it that's allowing you to import scss in a javascript Context? The webpack sassloader. The webpack sassloader figures out what it is and knows where to put it. So because it's an scss file, it knows to compile it to That css file. And because everything else is javascript, It knows to compile it to that javascript file. So webpack is associating the style sheet with the javascript And if the javascript is included, then the style is getting included. Well, so all webpack is doing is building index.js and Style.cs. Then i use wp and qscripts inside of If you look in that block.php. So out of webpack, you got your jsx, which is an html Javascript composite, and then webpack is bringing the css Into that before it goes to wp and q. Yes. So it's generating build Slash index.js and build slash style.css. And those are actually what i'm enqueuing. So all these files that i'm showing now, like chrome dev Tools is smart enough to know they're there, so it looks Like they're loaded because of the min map, but they're Not really loaded because they're written in, like, ECMAScript whatever the preset is for. And so they're not browser safe. And also we're doing things Like jsx could never load in the browser. So yeah, all webpack does is create those two files. And then this here, i made actually more verbose than it Had to be because as brian showed, you can just pass The, you know, you can register your scripts and then Pass the handles in. Because i wanted to make this Super clear. I made this slightly, you know, i Want to do this many steps, but it helps show the fact that All we're doing is these two files. And again, they don't have To be compiled with webpack. And we couldn't make more. It's just a way that, again, when i start adding, like, Ten blocks, you know, ten blocks or sharing components As we're about to get to, it just becomes unscalable And otherwise. Are there other questions? Or can we move on? So the next thing that i wanted to show When you go back to php star and we click here. So right now, what i have showing is this little component Here. That's just, you know, it's just Using that react bootstrap component. And now that's a problem Because my save callback is saving something totally different. So one way to do that would be to cut and paste this down to Here. Right? We can just done. Now we have the same thing for an end back end. In terms of this is going to actually render out that html And save it. As that, you know, whatever the Ending css that, or html that bootstrapped it with the Right classes and so that way bootstrap styles are right. This is going to save that to the post content. But we've not just violated the do not repeat yourself role. We've created technical debt where, well, what happens when i Want to make warning a setting, right? Like later on, if you look at the final version, i've created A select control that changes what type of bootstrap as Like info, notice, warning, these sorts of things. Right? And i don't want a hard code warning. That's not too useful. So that becomes an attribute later. Well, that's a pain in the butt, because now i have to change Two things. Also, how does it work on the Front end? This is why we invented functions. Right? And so what is a component in the context of a React word press javascript app? Because remember, it's Functionally no different at this point. When we say it's a component, it is a function that creates Something, creates this view here. So, literally, what i'm going to do to start is i'm going to Go to my components directory here, which is empty. I'm going to create a new directory, call it alert. That way i can group all of these alert things together. So if this becomes more complicated, and i have other Blocks that have different components to point from. I can put them here. And i'm just going to say alert Display. So this is a standard file. I'm going to import, i'm going to cheat and look on github. I have this built. I don't recall. Because you can see here i have about three of them here. Whoever is in the back talking, do you mind stepping Outside? It's just really distracting. So, again, using my, when we zoom in, i'm able to do that Same import here for the alert from react bootstrap. Import class names again because i want to, no matter where i Am, have that same class name. And then i want to have my Component from wordpress element. And this will become More important. I just want it in scope for now. And then this is basically the same thing as we had in The edit block before. But now we're using, we're Passing in props. It's a react convention to call This props. Could have been called arguments. Could have been called, you know, andrew, taylor. It doesn't really matter. But by convention we call it Props in this case. When we start to get into using Classes, that becomes more important. But you can see that This is, there's nothing fancy about this. This is just a function that wrapped some jsx. And this could be using the l, create element function if we Want it. And at this point i've just Made the decision to wrap a p tag inside because that's Going to be a little bit cleaner. It's a paragraph of text. It should be in a p tag with a consistent class. And then this inside. And the reason why i want to do That is that way i can actually change my Attributes here. Let's see how i did that. Sorry. Get back here. I ended up changing this to I took out what kind of element it's looking for. So just find any element really that has that class. This gives me a little bit more flexibility for message. And i'm going to set a default. So that way it doesn't come out empty. My default alert message to tell people about is high run. But to get a little bit deeper into these attributes, as i said, This is your opportunity to be declarative about your fields. When i say this is an array, that means that wordpress will Refuse to treat it as anything else. Now because i'm using that rich text thing, It figures out how to put it into an array and out. But if for some reason somebody else tries to do something weird And put an object in there, it's just going to throw an error. It's not going to let us save it wrong. And if somebody has been doing wordpress development for a long time And writing functions that are like, if this argument that should have been An array is a string, let's figure out why it's a string, Protect against that, see if we can turn it back into an array Based on what we interpret the user. It just gets weird. Because we don't have in Super old versions of php that for some reason we're still encouraged to use This kind of type tracking. And it's not something that we've You know, it's simple or not to have. The rest of this is basically the same now. I'm going to replace this alert. Remember i just made a new version of this here. So i'm going to import this up here at the top. Import. I think it was alert display. Php storm kind of figures out the rest for me. But if you're new to webpack, unless you're using shortcuts You're going to have to use full file pass. There are other ways of doing it with lazy loading and things like that. This is the simple way to do it. Now, what i'm going to do is i'm going to replace this here With my component, which is self-closing. So i actually don't need that. This is going to be alert display. And it's going to have some properties to it. I need at the very least, i need message equals attributes dot message. It had an optional parameter for type, but we don't have an attribute for that yet. So we're just going to leave that out. Because it has a hard code of value. And i'm going to put it there. So now, this is my component. It's used in two places. But remember that jsx is a fancy way of writing a function. It's kind of an optimized way of writing a function that generates html. But it's still a function. It's no different than if i just returned an object literal or a string. It's just a sophisticated way of doing this. And that means that underneath, this is using that library for the alert. If later on i realize, i want to switch to tailwind css. Instead of react bootstrap. My block and my front end, when i start to use the same component, are all using this one thing. So all i have to do is change one function. Again, this is why we invented functions. It's the fancy version of kind of paste. It's more scalable. So two things. One. This is the class name. So that's like adding class equals whatever. But we can't use class because it's job script. So this is an optional property here that i'm using here. And then i should have done this for it as well. So that way i have a fallback. And then you could say to me, but josh, now you're repeating yourself. You should do that above. The point is that if i want to persist this without making it a Meta field, you're about one slide ahead of me, but it's fine. One of the things, before i can add a control for type of alert, right now it only creates warnings. What if i want info? What if i want danger? So i'm going to need an attribute that represents type. So one of the ways that i can do that is i can make it a Meta attribute and just have it store in the database. The other way is i can use just kind of let it be mystery Meet and have it serialized. And then the other one is that i can put it. I can tell it, hey, p tags with whatever that class is have an HTML attribute called type and that is the alert type. So that's three ways to do exactly the same thing. The advantage to this way is that now in the front end, let's say i wanted to just use bootstrap jQuery in the Front end, i can just pull that off with jQuery. Or i can use document.get element by attribute or Read attribute. So it's a little weird because Now i'm using data attributes. But it's available in the Front end whereas if it was in the serialized saving that's In that comment, you don't see that on the front. Or if it was in meta data now i need a rest api call or PHP render callback which is actually something that we're To show soon. How am i doing on time? We have to like 445 so at some point we're going to get to The end of my example code and then we're going to take Request and if i have to hand it off to greg or zack or Brian, that's fine. So let's go ahead and add two more Attributes here. The first thing we're going to do is We're going to add a control that will let us select between Three types of alerts. This hard coded warning That could be info, that could be data. So the first thing i want to do, as i said, Requestion was about two seconds ahead but that's fine. It was a great segue. This is an irritating workflow. Let's go in here. So here we're going to add this Alert type. Again, to represent the what type of Alert. And i've said it's an attribute. That means it's an html attribute. The example in the handbook Shows how it figures out from the saved galleries, how it Figures out what images are in there. How does it do it? It's the html attribute called source. It looks for IMG tags. It finds the source element and that's the URL of the image. It's able to pull those off. So in this type, i'm saying that there is an html element. Remember, she pointed that out. That it was there. Then i had that type attribute. So i could rip it off the DOM. Somebody's going to say, josh, that's insane. Why are you using the DOM as your single source of truth? Fine. So let's change my source to meta. Now it's a meta key. Which meta key? Greg, please correct me if i'm doing this wrong. Is key equals and then this will just be Alert block type. I'm just making that up. If we want getPostMeta, Once i do one more thing, it's going to populate this block. It's going to call getPostMeta and then alert block type. I'm just saying to people who are caught up. So the one thing that isn't, when i say that's what we need So that way it's going to persist to meta storage and back. Let's talk about the physics of that. That will make what i've missed out. The word for us is the database layer. This was the security question that came up earlier. Is that now i used to create a meta box with register meta box. And then i had to put the data into that. I had to write my own form fields and then use php to Escape the old save value if it was there. From getPostMeta and then on the save callback i had to Use updatePostMeta. Last api can handle most of this automatically for us. The one problem is it doesn't know dynamically about this. So i looked up in the docs and it looked like the type needs to be string. Source needs to be meta. And meta needs to be whatever you want to use. If i spelled source correct? That helps. Oh no type sorry type. So now the one thing that we're going to need. You also need to replace key with meta. Yeah i need to show. Like the name source meta and the key is meta. So it's like double meta. Okay but then how do i change the name of the... The other way around like the key is... The word key is meta. Seriously? Yes. Okay that's not how i recall it but i trust you. You have the internet and you wrote this. Well part of it. So the next thing that i'm going to need to do is tell the Rest api hey this field exists. The word key is meta. You swap the word key with the word meta. Yep throw alert block back down into meta and meta into source. Is this source yet value meta? Is anybody confused? I'm not confused. I just want to point that out. I just want to make sure nobody else is confused. So this is the same way i write code normally. I just do my own googling. One day when i'm rich i'll hire my own Googler. So now that we've remembered how to do this. What we're going to need to do is go over here and tell the rest api hey there's a field that we can use. We need this meta key. By default meta data doesn't show up in the rest api. It's an opt in thing which makes sense because what Meta keys go with what and what's public what's private. That's opt in for a good reason. That was a good design decision. So we can come in here and we can add action. Rest api in it. We should really do that in general. And then register meta. Object type is post. I think the next one is key. So that's going to be this. And then we're going to give it an array. And we're going to say show in rest equals true. I would also probably add a validation call back here To make sure it's one of those three. Register meta allows you to add a sanitization call back And a validation call back. I would just use a validation call back here to make sure it Was one of my three options if i was, you know. Had time to keep going. But now we have this ability here. I don't have react dom installed. That's why it's not running. Install. Save dev. Save dev react dom. Just to fix that error. No, npm install. Okay, npm is probably still running here. Yep, so now you see it was giving me errors because it Couldn't resolve this required dependency. I installed it and webpack kind of recovers all on its own. So now theoretically if we go back to the editor, we Refresh. Let's just remove this and start over. You see it gave us that new default. We can do this. And you can see that the saved html, we must not be getting Bootstrap loaded. Or no, it was overriding because I still have the csss. But you'll see here that what's actually saving and post Content is the css that you would use if you were just Doing bootstrap manually. Right? If you were writing a static html site using bootstrap And you needed to add a warning, that's how you would do it In html. So that means that as long as you're using a theme that Has bootstrap loaded, or your plug in loads bootstrap in The front end, that's it. Problem solved. The question about themes? Well, do you have custom styles for alerts? Do you have bootstrap loaded? End of story. Now, we might want to, in a more complex app, we Might want to actually reuse that same component in the Front end. At this point, what's the value of replacing static html with JavaScript that does the same thing? Nothing. But as our app gets more complicated, we might want to Use a more complex structure. So what I want to do now is we still have warning. Right? I said it as, you know, it's an attribute that exists, But we don't really have any way to save it. Right? We don't have any way to change it, so it's just falling back To its default. So let's add a control for that. Let me find my get hash for that. I have this done already. It's a little confusing. You know, I'm going to have to do this. Oh, I got to pull. Sorry. Okay. So now, if we, I know. I know. Let me go on. Give me one second. You know, our version control, and we find, that's where we Were. And give me one second. This will turn over to where we were. So now, I've gone back in here. Let me zoom in again. In my attributes. I've gone back to the old way here of doing this. Okay? Where we have a work type as just that html attribute. And I've added a second change handler. And if I was doing meta, this would be exactly the same. It just doesn't really matter. But now, I've added this toolbar here. Let's change this to a div, because that's not really Offering much work. Now I have this toolbar component. This is one of those components that brian was showing you. You can pull it. Okay? So this is import toolbar from word press components. Just like we can import, say, a text control. And then I went ahead and just put this. I skipped that step of, like, writing it in the editor. And then abstracting it out to a component. I just went ahead and did that. And if we look at the top here, I mentioned that we're Extending word press component instead of react. If you look in react's documentation, when you see a Component created with a class, you'll see the import React. And then they do export class, if it's an export. You know, a large select type extends react.component. Or though, you know, they're shorthanded. When you read react's docs or any type of react tutorial. You can do that if you had imported react. That's totally valid. But you want to use the same version of react as word press. Just like you want to use the same version of jQuery. And so, as a result, we're just going to use, you know, Import component from word press element. And we're going to treat that. But everything inside of here, if you know react or you want to Go to the react's documentation, which is really, really good. Everything else inside of this is, there's no difference Between react and word press. I like teaching this because it's like surprising you know React now. What we're doing here, we're just bringing in, this is Actually more verbose than it needs to be, but we're having Constructor brings in our props, and then we always have to Pass it to parent. This will get a little bit more complex as we go. Starting with a pretty simple class based component. This has this constant options. Again, this render function is what creates the html output. You know, this could have been a class property, but Just for simplicity. These are our options that we want to have, right? And again, we should have the text domain. It's just that was changing. But you know, we have warning, danger, notice. And then we have a label, right? So we have the actual value, and then we have the human Readable label. And at the top, I'm importing select control. So there's a select control, there's a text control, there's A checkbox control. Just lets you have the thing that word press does. So that way you don't have to write your own checkboxes. You don't have to deal with making sure that the labels Are correct. Goonberg under the hood and make sure that you have a label Attribute with an id relationship to the actual input. That's essential for assistive devices. It kind of creates that under the hood for you. It's just like the security question of if you do it the Right way, word press will handle all of your accessibility Concerns. Not all of them, most of them for you if you don't do Anything nonstandard. And that just makes it easier to write good code. That's one of the things that i like about goonberg is that if We zoom in on this, on here, that's how i created my select Control. It's pretty simple. You'll notice i just wrote label here. And i'm going to let word press figure out how to create a Label attribute with the right for and then a select control With the right options i passed here and the right Relationship and if aria element tags are needed it should Be able to figure that out if in the future there's a new Version of the aria specification that this doesn't match. I would expect word press core to update this component to Match aria 3.0 or whatever. And then you'll notice here, so this is just taking these Options, this array. Pretty magical. This on change is this dot props dot on change. So that means that this component has a property that it Expects to be passed in called on change. And that is the function that is called by react whenever this Select component changes. You'll notice this is not in the class. Because i wanted this class to not have any strong Long relationship to what state management is for this Application. Now how i'm going to use it is i'm going to pass in that Change handler that i wrote in my edit block. That's just going to be the prop. And so it's going to use word presses set attributes. But this opens up the possibility that in the Future i might be using say redux for state management Because this is component ended up getting repurposed into a Wp admin screen that isn't using gunenberg or a front end that Has no gunenberg. And it has to have its own state management system. That from the perspective of this component, that's Invisible. It just doesn't matter where data comes from. The type is props dot type. That's the value. And what happens when it changes, it calls this Function. So if we look back in our edit callback here, I'm saying on change. I'm passing that prop. I'm passing the type here. Attributes dot alert type. And then I'm passing this change function. So that'll update word press. This we've seen before. It's exactly the same as change message. It's just changing a different property, different attribute. But we're able to pass a reference to this function Down into this property, into this component. So that way it's reusable. Does it really? There's nothing about that component that's strongly tied To gunenberg. We can use it in other places now. If we had put set attributes in there, then it could only be Used with gunenberg. And that means it's not easy to unit test. And it's not easy to reuse elsewhere. You have a question? Any questions? Okay. So if I were to build this out now, You're going to see that this doesn't look good. Let's refresh this. Let's start over. So when I click out, it's going to go back to looking. Right, so there's my bootstrap. That looks great. It's inline. It updates in real time. But my edit interface is terrible. Right? Why did I just drop that toolbar there? Let's just make sure that works. Right? So that's cool. Problem solved in terms of functionality. But putting a control right there, now it's like jumping Around like if I had a paragraph block under this. Is that a paragraph block? Right? So now like when I jump into the editor, That block kind of jumps around. Nothing about that is good. But the reason why I didn't use a toolbar like this, Which I could do, right? I could reuse this component. Is that the, well, but I wanted the wizzy wake stuff. So now I have a problem. I can't really put this here because it looks bad. I can't, I don't want to just keep adding stuff over here. Because that's going to get out of hand. What I really want is to put stuff over here. You see where additional css cost is? I want to put my type over there. Because it's a sort, you know, it's an advanced control That's kind of a set in and forget it. But also I want to, one of the things I want to do Is make it so this can be a dynamic block. It can pull data from the rest api. So that means I'm going to need to switch for, you know, What if it's static or dynamic? I'm going to need to know what post to pull from the rest api. If I, this is bad. But if I have three more of those, this is a user interface Nightmare. So let's back up a little bit. Let's redo this. Let's go in here. And let's replace this with inspector control. So I'm going to have to import. Is that, can you real time correct me if I'm wrong here? Is that correct? I think inspector controls can move to blocks. Oh, okay. Can you look real quick? You mind? That should be correct. Okay, cool. Now what I'm going to do is I'm going to change this toolbar Here, which looked kind of silly. To inspector controls, key equals inspector. That's correct. You actually look in my final code if you want to check me. Remember we did this. And now I have it here. And theoretically, if I reload. See, it jumped it back to a paragraph block. I think this is a really cool feature that if the thing Kind of jumps out, you know, your block is bad. It becomes a paragraph block, not like a naked short code. That just makes your site look busted. I think that's a good progression for wordpress. So let's create this new one. I'm getting hungry for dinner. Right? So now we have the same thing, but this interface, Yeah, I've got a little bit too much padding here. But I'm not getting that huge jump of having that thing. And if you notice over here, I still have that control. And I like that a lot that all I had to do, So this is the paragraph block, has all this stuff over here. I can do exactly the same thing that gives me the same type Of interface that's consistent. Again, I'm not an interface designer, but I know enough About interface design that what I need to do is Make things the same. Right? Let somebody else decide what the standard is. Let somebody make those little tweaks for my specific plugin. I want things to be consistent. That's what I'm interested in. I want consistent html, I want consistent controls. Let other people deal with that. So for my block, I'm able to do this over here. Now, and I guess notice doesn't really have CSS That shows up on my screen, but danger here. So this is a way better interface now. And I just want to highlight that there's nothing too fancy About this. This inspector controls component, you just wrap Stuff in there. And WordPress knows where to put it. We can dig under the hood or pick Greg's brain on how That actually works, but for me, that's what I know. I know that it goes in there and it looks right. And I think that's really cool. As somebody who spent a lot of time figuring out Like the css of like an html structure to reproduce Like the post blocks in the old post editor, so on like a Plug-in screen, so it's consistent and you have the same sort of Flow. I spent a lot of time on that in the past. Reason that same classes and keeping it up to date when css Changes. We had one of our plugins, we had that issue where we Tried to reuse a core class, reverse engineering how core Worked, and core made a change that made sense, but All of a sudden the edit button in our plugin, all of our Users where I could disappear, and I was like, no, it's 99,000 Pixels to the left of the screen. Which is a distinction the end user doesn't really care about. So we had to make a change. I love this as a plugin developer that I'm just going to use Inspector controls, and it's going to go where those go. And it's going to look the way they look. And me as the person who should never touch the css, Should never make a design decision, just doesn't matter. WordPress will take care of that concern. So the next thing that I wanted to show is that this is Still a static block. Zack talked about this, Greg talked about this, Brian Talked about this. It's a weird concept. A static block just creates static html. So what's a dynamic block? It's going to save data that can be used to construct The html at render. And when we say render, whenever the post is read From the database, and then, yeah, your cache system Might come in and make it. So it doesn't only happens once. Just like in the current WordPress, you have a cache Plug and you have a cdn. So we only have to call post content and render your Short codes out once. And then it's just there in the cache. But one of the things that we could do, and i think is in The last code example here, is let's make this another WordPress post control the title. Control that alert message. Because what if we wanted to have this as, like, say, a Sales message, right? All of the posts that are about a product, you want to Put this, you know, you have this new product out that, You know, makes WordPress 10x faster, right? And you're doing a special launch deal. 50% off with this discount code. Well, hold on. Now later on, you might want to change that. You know, fall sale 20% off. You can have one post that just controls that. Or, you know, maybe this is a block that, you know, puts Real-time information out. You know, you do it on ajax loop or use a web socket so You can update. It's great to have it instead of being saved in Static to be created dynamically. So let me jump out to... I think this is basically as far as we got. Cool. So, this is actually going to compile. This is only slightly more complicated. All I've done is I've added text control. You did a pretty good job of clearing out the room. Some of the stuff is a little more complicated than Everybody needs. I get that. This is where I'll be at the end. So you'll notice that I'm just starting to pull in Lots of controls here. I just want to illustrate that. If you go to the Gutenberg on GitHub, there's the Components directory. There's the blocks directory. Click through there. A lot of them have a read me file that shows you how to Use it. If not, pull requests, you know, to add that once You figure it out. It helps everybody in the community. But I pulled in text control. And then I added it here. And what I did is I said label remote post id. This is the idea of that post that we're going to pull in. You can get more fancy in like show latest posts or, You know, have them addressed by the title, not by the id. But this is a kind of simple concept. And because of that, I did specify that this is the type Number. Right? Because I only want post id's in there. And that's just going to, you know, input type. Standard. And then on change. Again, just a new function that looks pretty similar. To all the other ones, it's just changing a different attribute. Which i did add up here. You'll notice that i didn't really do anything. Here. I just said it's an integer. That means it's going to be serialized. So let's look at this for a second. If i go here. I'll just delete you. No. Remove. Move. Add a new one. What i have over here. Let me zoom out again. Now i have the type. I also have this remote post id. And what i'm going to do is i'm going to type 665. Because i happen to know that to be a post. That has the title remote message from post. I just happened to have created a post with 665 last night While i was setting this up. That's the title of. Just trust me. So what it did is it switched from the hard coded Message to the post title. How did it do that? Workpress rest api. Let's take a look at how that happened. You'll see this right here went from being alert display To alert display with api data. What's going on there? So this is the same file that we were in a little bit ago. This is our old component. Alert display. I don't want to change it. Because it's still super useful to me. I just wanted another way of using it. So i'm basically creating this component at the bottom around it. Okay? Because the responsibility of this component is to set up that Component with api data. So this component's responsibility is to create html that Looks like an alert. This component's responsibility is to use api data to set up That component. So in the render function, almost identical to what we were Using in the gunenberg block. The only thing that's changed is that at this point, ignore Everything about this for a second, is that this, the Message is this.state.message. Okay? Why is that? When we go to our constructor, remember before i just said It was just constructor props, super props. And i said that's really kind of not necessary. It's overkill. In fact, the default eslint for react will throw a warning on That. Like it's an extraneous constructor. But what i'm doing here is creating this.state. It's just an object literal. Message equals props.message. It's a ternary. So props.message is passed. It's that if not empty string. That's why when we saw this render, it started with the Default value. And then it updated with this rest api request when it was Done. So wordpress has events, right? These, you know, at do action, wp head, right? So we can add action to our execute code whenever we get To the wp head event. And javascript has events in terms of, like, with jQuery. We can say jQuery.onChange. Whenever that text input changes that we just bound to, Well, react, everything has events, right? This is not specific to wordpress. React components have life cycle events. One of them is called component did mount. That runs after the component mounted. It has a evil twin component did on mount, which runs Whenever the component is removed from the DOM. So whenever this component mounts, i'm going to call this Method this.getRemoteMessage. And i've just abstracted this in here. But i'm only going to do it if this.props.postid is set. Because i can't make an api request to nothing. To no post, not set, right? This just doesn't do anything if there isn't a postid. It just uses this static saved message here. Because this.state.message defaults to props.message. But then we change it here. And this is a api client that is built into wordpress. And it's important to note that this wp api request is designed To be used with the current site. And what's important about that is this is basically jquery.ajax. If you read the source it's wrapping jquery.ajax. But it's setting up the nonce for the api request. So that way when i make the api request it's made as the current user. So that way i can update, if i have permission to update the post Or read the post then i'm actually able to do it. But this you can almost read as jquery.ajax. It's exactly the same thing under the hood. This is just kind of a utility where i have to set up the nonce And the headers and all that stuff. It just figures that out for me. But one of the things that the first time we tried to build this Zach and i ran into was like i tried to plug in a remote url. It wasn't the right nonce and it was just i would have to use wp. Dot api, thank you. If i wanted to do a remote post. But all i'm doing here is you can see i have that 665 hard coded. Let's change that to this prop. Because it's es6 we can use ticks. So now it can pull from any post. And as i said, i kind of cheated by just having a number input With the text. You know where i knew that 665, like i'm giving a demo, i cheated. But remember when we created this select type. And i hard coded an array of options. I could have made a wordpress rest api request for 10 posts. Or i could have added a search there. In fact, there's a component that does this for you. It's like url lookup or something. I forgot what it is. It's in the components directory that doesn't auto complete. We start typing the name of posts. And it brings them back from the rest api auto complete wise. So that would be a slicker way to do it. Or maybe this was like choose from one of five preset posts. So let's say you were doing this. You worked at a university. And it was like, i wanted my alert to be student events. Or i wanted to be alumni events. Or i wanted to be general notices. And so the label would say that, but the value would just be The post id. Maybe i have a custom post type called site-wide notices. Or something like that. And again, because these components are pretty decoupled here, I could use a different, right? Like i don't have to use the wordpress rest api. This could be pulling from any site. If later on it's like, hey, we want to pull this from a Different type of application. I want to pull this from an rss feed of local news. Really kind of doesn't matter as long as i end up setting State a message. Here. Andrew has a question. I guess i don't know. Zach's coming on the mic. So right now with post id, you're entering it on every block. And then it pulls in. So if you use these blocks ten times across ten different posts, You could have different post id's. If you want to update that, how would you go about handling Transitioning that from a per block setting to like a global setting? Well, so if it were a global setting, then i would probably Put it into options, right? Because post meta doesn't really work as a global. Post meta isn't global. Options are kind of global settings. So what i would do is i would put a little like setting. I would create a settings component on a wp admin screen. And then i would like embed it in that sidebar, but it Would have its own save method that made its own api request To a custom end point that then updated the settings, However, that worked. Global settings. But if i was using one of the weaknesses, i think of using The, how this works is it just kind of serializes it. Is that i can't like bulk update them. Whereas if i had used a meta value, a meta key, well, That's a sequel query, right? If i want to bulk update all of them. The other option is with reusable blocks, i could Create this two or three times and just repurpose those Throughout the site and then changing. Brian showed this earlier where he had the static version that He was, or greyer had this in his footer that created it on The five one. So that would be the other solution. Is that i could create three of these beforehand and then Make them into reusable blocks. And then potentially hide this from the insert. So the only way to use it was the reusable blocks. That would be one solution. The other is just use post meta because you can write a sequel query. There are a couple of questions back here. At least one. Is this api request only happening in the Gutenberg Back end or does this happen on the front end when it's Displayed as well. So, again, this is still just saving html. It looks like a block. Right now. Okay. The next step is to figure out how it works in the front end. Unless anybody has any questions, let's move on to that. Because this, we keep coming back to this. How does it get to the front end? What does it do with themes? And a lot of times the answer is nothing really. It's just html. But that's kind of limiting because, for example, what if There isn't a post id set? Maybe you have a global fallback setting. Right? Where it's like if the block doesn't have a post id saved, We go to the global site setting for post id. Or maybe we want to use getPost real quick to Make sure whether that post exists. Because the rest apis is going to throw an ugly 404 error. You know? So that's where we have to make this decision of do we want to Try and be isomorphic where we reuse the same components in The front end? Right? And that's why it was good that i was saving that type as An attribute. Because i can either use jquery or react or just vanilla JavaScript to rip that off the DOM and do it. That's also kind of silly. So let's look at how to use a php render callback. Because this just isn't complicated enough that i want to Mess with any of that. Right? At some point, it doesn't really scale to rewrite, you know, Your view layer in php. But for something this simple, you know, and also i want to Get to that point of showing a php render callback. Zach, do you have a question? Or are you just looking for new people? Okay, cool. So let's look at a php render callback for your block. And this is super similar to a short code callback. If you've ever done add short code, and then it's the name Of the short code, and then it's a function that gets past The attributes of your short code, and then you do something With php to create your html. That's like the tldr of short codes, right? Let's do something very similar here. I don't know if it's going to be... I already created it. But let's... two things. One, i am now using register block type instead of in addition To the javascript function. Why? Because i want these attributes to be known on the server Side. In this syntax here, this is php syntax, but it's Exactly the same rules and concepts as when we did it in In javascript. Literally, i cut and pasted my object literal from javascript Planned in, and updated how i changed colon's Daryl operators and put single quotes on this side. But it's the same thing. It's just an array of arrays. But it's all the same rules. Type, source, right? Nothing. No new concepts. It's just using the way that php creates arrays. But what this allows me to do here is have a render callback. Now, this render callback is just a php function. I used a closure because... i don't know. I got bored of writing php52-compatible code. But it gets past the array of attributes. What's in there? Message or type and post ID. This is pretty cool because we never really had this before in WordPress. Short codes sort of have it. There's no requirement for you to declare what attributes Your short codes have, but there's a lot of advantage to doing Because you can then filter them and validate them. But here, i have to. And as a result, you'll notice i'm not really doing any Checking here to make sure this is a string. You know, that this is a string. I'm just making sure. You know, i should have validated it. And then this is just a very basic php, you know, inside Of double quotes. That consistent class, this consistent class, right? With the type there. And then message. Again, this doesn't really scale. As my application gets more complex, right? The question that i'm still sort of answering is, should i Have, like, mounted this on the front end with react? Maybe. If i need more application-like features, Like the ability for people to communicate back, right? What if i have an alert and then people, if they are Affected, can, you know, have a little form where they Submit a response or, you know, updates? Well, that's the kind of reason i want to use react. I wanted to, like, work with some sort of live updating Library that can either pull my api or can, you know, Use a web socket to get real-time updates. That's another great reason to use react. To create a bootstrap alert, i'm not loading that on My front end. Right? This is just not at the size where this problem is a Problem. And also, i, like, for academic reasons Wanted to point out that this is really cool for If you already had a shortcode, right? If you have add shortcode and then a callback That's, like, wrapping a function, right? Some people tend to use their shortcode callbacks Do everything to create html. Right? That's violating the single responsibility principle and Reducing your reuse. If you have a function for it, All your, for your shortcode, or if your add shortcode is Just setting up your attributes and then passing that to An existing function, you can do exactly the same thing Inside of your render callback. And just leave your Shortcode alone, and that means that your plug-in when Loaded without doon and burq, say a classic editor, Wordpress 4.9 or below without goon and burq installed, It's just a shortcode. People want to use that Functionality, right? This is my life with my plug-in. Right? We have shortcodes. Now we have a block. I need both things to work identically. So they're using, there's wrappers around the same function. The other thing that's good about this is that i can do A capabilities check. So if i was creating a block For restricted content, i don't want that to happen. In javascript, there's no way to secure that. Right? If it was set to one user, paying members, here, Well, i can just do current user can or some other call. So there's a lot of situations where this gives us a lot of Benefit for dynamic content. And also, if i wanted to build In a rest api request here, i could. If i wanted to take that post id attribute here, right? If isn't new, if zero is greater, it's less than Absent, adder, post id, it's really just is new. Right? i don't know. That would probably be good enough Because we know it's going to be an integer. But it just could be empty. So let's say if it isn't empty. And yes, that won't allow us to use post id zero, but who cares. If this is done, we'll do arrest, we'll do use getPost. Right? And if not, we'll just move this up here. Right? And so now we can do message equals getPost Adder, post id. Right? Because why make a rest api request? We're already in php. I'm not getPost, getPost. Right? And that's like the least exciting line of code, but I don't even really need get. I could just use getTitle. I don't know. I haven't made a theme in forever. I forget these shorthands. Other questions. This is kind of the end of my example code, and it is Currently 352. So we have about 45 minutes. So i think one of the two things we can do, or three Things we can do is sort of like if you have general questions About gunenberg, we're all still here. If there's specific things You'd like to see how to do, we can kind of live code them. Or if we just kind of want to go and eat dinner. Is there a sense of the room, zack, brian? Questions? Family event. It's true. There's only some of the things Attributes i can do. So this you can add even more And more attributes. Yeah, you can just keep adding Attributes and they're filterable to an extent. I mean, if you look in the database, the question was that You can just keep adding attributes. Yeah, that's kind of the Ideas that i can just keep adding them on here. And as long as i have the old ones, you know, i don't Modify the old ones, that's going to get weird for Backwards compatibility reasons. I don't want to. Once i ship this, you're going to be very careful about Changing those. I mean, there are filters that run On the prop that lets you change your block props. So you can kind of use those like if this one's set, Like change it to that. That's hokey. I would rather just like once this is there, just kind of Like a short code attribute. You need a new feature. You can add another one. But leave this alone. But i can just add a fourth one, a fifth one, a sixth one. Or new capabilities. I know people will, i mean, they add to the repository and all that. Oh, sorry. I know in linux, i mean, there's so many Contributors. Yeah. Now will there be something like this Where they contribute to the code and... Well, if i were writing this as a release plugin, i would I would actually not put this here. I would bring that in from In an array that came from its own function. And i would put a filter on that. Namely because, right, like I build in an add-on ecosystem so i put filters everywhere. That's why in my example, i showed how it was registering a JavaScript. I put that action there. I have no use for that action. I just know that You know, wordpress developers needs filters in actions. So if i were doing this for release, i would totally put That there for a couple reasons. One, so add-on plugins can add Data. You can add new attributes. Also, because maybe i want to make it so certain users can't Change post-id, right? Or for some users, they're limited In what capabilities they have. And then the other reason is Just because i might need to reuse it. So putting it in its own function. For example, i might, If i'm going to have to register meta and get really in Depth, at some point, like manually calling register Meta, i register rest field for every one of these attributes Gets squirrely, right? That doesn't really scale. So having a function that creates these, and then i can Get the name from them. If they were a meta key, right? I'd have that in there already. So i could write a loop Through that and kind of generate the registration on the fly. This is just a little bit simpler for purposes. But, you know, i would totally write a function that generated That array. Also, i could unit test whether Or not that was correct. Other questions. Right over here. Just wait for the mic, please. It's just for the live stream people. Yes, so i have just a more general question. Obviously, the wordpress community is more heavily Focused on using react. I was just curious why the Community chose react over angular or, say, view.js. Okay, so i'm going to hand this one into grade, but i will Point out that as somebody who started on his view, right? Sort of new react, and i had to get super into it for this. I'm still a view fan, and because i have a lot of Investment in there, i'm just going to use wordpress's State management to dynamically update view's data In module and mount that app right in my block. If it pre-exists. I have a couple of examples that i Can show you. It kind of gets into the redux Abstraction, which we aren't going to get to today. Where you can use wordpress's redux to dynamically update the State of a view app. Or you could do the same with Backbone. It's been explained to me why this is a Giant pane in angular, but there's no reason why you Couldn't do vanilla javascript in there, or you Couldn't mount to view app or backbone app. And i've done it with view. But grade can actually answer The react question a lot better. Why? So the prototype was built with react. Because of the developers who were involved, they had a lot Of experience with react. They knew mostly from calypso, Which is wordpress.com interface. And based on that, it was easier to start, but also the Most important part that was needed from react is Virtual DOM, which is basically in view, in angular, and in Ember. So the thing is that as you can See the surface of the react is also very small, so what You have seen in the last hour or two is mostly, i would Say, over 50% of api, so it's not that much to learn. It's overwhelming at the beginning, but then you Just need to adjust to this thing. There was this issue with patent closed last year. It was like around September, so even Matt announced That we are backing off from the react and rewrite this, but Facebook changes the approach. Now it's MIIT license, which Is compliant with whatever wordpress uses, which is fine. And so there was exploration to use view and also to use Preact, and react was pretty easy because there is some Way of doing, they provide drop-in replacement for React. But in the end, since react State as valid for usage, there was no need to Replace it also. It turned out that there are no Issues to react and perfectly find whatever we need. So it's like there's no reason to remove it now, because we Want to focus on the product itself, not all the libraries That are behind. And also as zack Mentioned before, i also mentioned that we have this Abstraction layer, which is sort of built to prevent the Situations like with jQuery or backbone that they are no Longer maintained, which probably in case of react won't Happen, but if they change the apis in a way that's not Compatible, we don't want to break all the plug-ins, but Just continue updating and we'll take our Solved decision if you want to still use react or use Something else or even build ourselves. Because virtual DOM is so present nowadays that i would Expect that in some way in the future it might even become Like a new api inside the browser. Thank you. Do we have any questions, requests? I have not been playing guitar much in the last few years. I wasn't very good to begin with, so let's give it. Do you want to come up here and do that with me? This is an interesting discussion. In the beginning i pointed out that i had loaded this Front-end file. This is a separate bundle, so that Means that i don't have to. I'm going to import my I'm going to import the same component that i used And i'm going to import render and create element from wordpress But all that other stuff that i needed to build the admin, the Editor, those controls, they're not included in this bundle. This bundle is a lot lighter weight because i don't need any of that stuff. But this is where it gets a little weird of like what if i Did want to have, my ideal would be that goodenberg puts Out html that's good enough for your light mode, good enough For your no j s mode. It's human readable and machine Readable without javascript. But we then use javascript to Replace it with an interactive app. So this is a pattern that we Were playing with. Yeah, i didn't have the mic. Where it's like, well, i know what this consistent class is, so That means i can rip them all, i can get them all off the Dom, right? i mean, this is a conversation With jack and ive been having for like three months. The interesting thing is think about the gallery block. When you save the gallery block, it's a bunch of hard coded html, right? And you get that on the front end and you want It to be a gallery that you click on and it pops up with a Model, right? That's a pretty common thing. So because everything in your cool react base world in a Block is just saving html that's thrown into the content, You can't do anything in the editor that would cause Functionality to happen on the front end. Does that make sense? So if you're all you could do in the Block context is save hard coded html. So if you want to then click on an image in the gallery and Have it pop up, the easiest solution would be to load a Completely different javascript file on the front end, use j Query, and then go in and find those elements and rewrite It differently. But ideally, we'd want to Be able to build a react component that handled all this Functionality, but once you save that component down in html, It loses all of its functionality ability. So the path became how do we get everything that's available in Editor now and before they consciously made it available to Be used on the front end in this context, like how can we Hack it to get it working? So... So the idea is that document.get element by Class name gets us sort of an array. It's in a way like object. It is actually a DOM element Collection, but it works like an array. And it's going to get us all of the elements that have that Class. Again, this is why i keep Using this object so that way i have always the same one. Is this on top of the blocks you already created? This would be in addition that way you're putting the Functionality on the front end. So in this point, it's like before i kept saying, why would I use react to create a static html element that i could Just save to the content and it just looks right and css can Handle the rest. And also i can always... For example, let's say that i set up that gallery. If i use the right html structure for a bootstrap gallery, Maybe i just do jquery.bootstrap. Whatever sets off the gallery. But if i want to get something More complex, i want to create that little mini app that lets Me change the message on the front end, if i'm an editor, Let's me say, oh, hey, i have more information than i Want to share. That kind of thing, we're going to need To turn that saved html into a react app in the same Place. But we want to do the good Thing about having the static html saved to the DOM. Is if javascript isn't a thing, it's just the static html. We're going to progressively enhance it with javascript and css. So one of the weird things at this point is that can you Pull up in like a php file where you're enqueuing this Into the front end? Yeah, because i'm not, actually. Look at that. Okay, so see where it's enqueue script and then we have i18 blocks and element. Normally in javascript, we would assume that if we make Things a dependent, that it will load them, correct? Like you make jQuery dependent. But that doesn't work with this. So you have to go through a separate step. And I'm not sure why. Maybe Greg could help us out. But you have to actually re-register all of these Libraries in this function right here. So above the enqueue script, we would also have to do what is It wp register script or something like that. Yeah, while you're using q, but then the other thing i should Have done is use this variable here, right? Because this is this array and i'm looping through them and Enqueuing them. But what i really should have Done there was wp register script. Yeah. Yeah, so this would be correct. So now i'm registering these. Well, the thing is, is that core already registered them? That's why i had enqueue. I don't really understand the Problem here, but it's totally necessary. Right. Right, the reason why we're doing This is because we tried it without it, it didn't work. But the basic hack to this, and just keep this in mind, Because at some point, hold on before you take it away, Let me give them bad practices to do. At some point, you're probably going to want to be like, Hey, why can't i use react to build everything? So if you go through this step of making sure that it's Registered on the front end, which seems like a duplication, But we do have to do, then you have access to the same stuff. So you could actually take a component that's loaded in the block And also load it on the front end. Unless you're using some crazy higher order functions, Or like the redux flow doesn't work with this model, But core react and building components that click And have event behaviors, we've been able to get working Once you register. The easier option, by the way, is just import react. And then it's built into your webpack bundle. I just wanted to say that probably there are more Dependencies that are needed because blocks might depend on Newtiles and so on. So we would have to look into the plugins, Gutenberg plugins code and just copy the function that is There. And there are lots of Dependency inside. To block for blocks, to work properly, sometimes media For wp-alarm, and you also don't have react here, Which also needs to be... Yeah, you need wp.Component, right? Yeah. But the thing is that when it's built, React is treated as external dependency, So you need to put it in yourself. And there are streams and stuff like this. It gets very complicated. It's like 100 lines of code. So, yeah. But anyway, this is something that will be merged Inside the core soon. So you will have that available. It's only loaded inside the Gutenberg just to save The bandwidth, yeah. And save the bandwidth for Netflix. Yeah. I mean, in the short term, how to Probably solve this is not used WordPress dependencies. It's kind of a question that doesn't have an answer yet. But in the short term, what i would just do is import React. It's cheating. But, like, it's not done. Like, when we get to the point where this is all kind of Magical, then i won't need to do import react. If i needed to ship this this week, i just import react. I wouldn't use any WordPress stuff here. I just let webpack build it out. I love that because the more people who do this, the more Likely there's going to be multiple versions of react loaded. We're slowing down page loads. We're going for no reason. WordPress should be providing it. We're just not 100% there. Gutenberg's really far along. I'm cracking this. When did this start? When was the first beta? Yeah. No, i mean, the first time that It was like, this is a beta. So i've been following this pretty much from the beginning. It was like, this might be too minimal. And now it's kind of getting to the point where it's adding These levels of complexity. And we're kind of at the point Where this is like this and coming up with better syntax For templates, the multi-column stuff that everybody Really needs is experimental right now. But it's pretty neat what it can do. The nested blocks that just came out three, four weeks ago. This is the kind of stuff where i think a lot of people are Like, where's my nested blocks? Where's my multi-columns? That kind of stuff starting to come together. The redux abstraction for communicating between blocks Got revamped for the good recently. This is starting to come together, but it's the last Sort of pieces of, you can correct me if i'm wrong, but I think as a plugin developer, sort of looking at this like Okay, this is my life now. These are those last kind of Pieces that i'm like, well, how do i do a nested block Programmatically? How do i do this front-end stuff? I don't know, we'll figure out over the next month or two. I think just the thing to remember is that all of this Works within the editor. So once you get outside of that Editor, if you're on your plugin settings page, it's Going to be a different game. If you're trying to work in The customizer, right, and the goal of Gutenberg is to Slowly expand this whole abstraction layer through all Of wordpress so that you get it in the customizer, you Get it in the back-end, you can use it on your theme, and We'll eventually get there more and more, right? Like the direction is going? Yeah, there's also plugin which is already in the Repository, which what it does, it just takes advantage of The existence of, they are called now shared blocks, which Are stored inside the database, so they are exposed inside widgets. So you can just pull up from the list and use the same Thing that you have already inside your editor, which is pretty Handy, and this is like the direction how it can evolve Because if plugin developers are able to do that, how nicely It can evolve once it will be a focus for the next phase. So, theoretically, this should create an element using this Temp, this. We're going to kind of Change the code here, for the reasons we discussed, this Would work. Imaginary code. We changed the wordpress Model, code is imaginary. I have that power, obviously. So we're just using l again, i've called it create element, This is the same l that brian was showing us. Just to create an element that has this in it, that's Correct syntax, should i wrap it in a div? I'm going to use it. So then, the theory is that render, i imported up here, From wp element, that's react DOM. So i should be able to render, and the order of operations Is the element to order on, to load on. That should be block DOM element, and then the content is Going to be that element that i just created. So the theory here, and as i said, this kind of needs a little Bit of work, and i figured it out, i'll come up with an open Source package to do this, is that it grabs the DOM element, Because that has position on the document. That's super important. That's not backwards. Other way around. What react DOM does is it takes an element, and it Replaces an html element when used in this context, and Replaces it with a react app that generates a live Updating using the special secret source of react. So our theory here is that we should be able to grab the Existing element which has position. We don't want to move things around on the page. And replace it with an element that's created with react, Said now it can live update the way that react does. So for this example, this is all just a waste of time, right? Like our php callback was enough, or our static block was Enough. But as soon as we start to get into those type of app-like Features, then this is of huge value, because i can put That same react app on the front app. I'd have to remove that php render callback that i Registered a little bit ago to make this work. But this thing here, now what do i do if i want to make this interactive? I'd have to either set it up so it worked somehow Magically with react, or i could use jquery.on On a text input to make an api request. But i already wrote all that for the back end. So why can't i just use these same components? And if i want to make it front-end editable, i can just Drop in those different components that i wrote for editing the Message, or for changing the type. Yeah, it really doesn't become useful until you have like Super rich interactions where they're either feeding data back Into the block, or that block has so much, it almost Becomes like a single page app in and of itself in terms Of interactivity. So, again, this was my goal for today for this was To show people who are going to end up building complex plugins. Substructure for building a complex plugin. Having it all in that one file that way brian showed is Great to get started and it's great for simple block plugins. It doesn't scale. This gives us, if i want to add another block, i'm just Going to add, you know, if i have like a reply block, you Know, because we want to make this into that interactive thing, I'm just going to add a reply block and then import it Into editor, or index.js. Maybe i have to break it up into different css files. Maybe down here in my components, i start having Scss files so that way they're only bundled in. I could have alert display.scss, or alert.scss. Then it only gets bundled in, that's css. Webpack has this magical system where it only loads what it Really needs. So it could figure out which css it needs based on which Components, because i might add, you know, alert reply or i Might write notice as a separate thing from alert. Maybe i create message and alert as a type of message. As this grows, i'm going to have more components, more blocks, More stuff in the front end. This is a very flexible structure that i just add one more File and set up my imports and i don't have to change anything. Pull up your webpack for a second. Pull up your webpack config. My webpack config, you wrote it. I stole it from core. So just point to the css loader stuff. So css line 16 where it starts going through this configuration For extracting css and then scroll up a little bit to the css Extract plugin. Somebody was asking about how do you know what the css is in The block and stuff. So this text plugin for webpack will allow webpack to track Any css file that is named as .style and automatically pull It out into its own file so that basically all the individual Little block things will all be compiled down to one block css. So you might have your editor stuff i'll be pulling out into One that's just loaded in the back end or you might have in this Case it's all being loaded to the front end. So just to dig deeper into some of this. That variable we were looking at is this right here. He asked me to show you where this exact config was Defined here. This is just an object that doesn't do anything on its own. It then gets injected down here and is used whenever a file Passes the test of having the extension of scss or css. That's what's going on there. There are two types of files that will pass this test. Css and scss. And in that case we use that object that figures out whether Or not it needs to use the sass loader or the post css loader. Now the other one if you notice was looking for .js. So this is the physical mechanics of how it knows what to do with Scss versus jsx or javascript. So .js will also pass for jsx. And it uses the babel loader. What is the babel loader? It is the webpack of integration with babel. Babel is the tool that converts jsx or newer syntaxes for javascript. I don't know what's the one they're working on now, 18? So whatever the next x is, you're able to use just by Setting up babel. So if you want to use the latest Functions of javascript or now with web assembly, you can write C++ and have it compile to javascript with webpack. Pull up the c++ block example. First person who writes a block using css compiled with Web assembly wins a prize to be determined. But yeah, all of this is fairly complicated. And the cool thing about webpack is you can define your Standard. So i am a ujs fan. Vue encourages you to use a .vue file. Which isn't a standard thing that any browser could ever load. Webpack, they have a special loader for view files that Converts them into plain javascript. I think ten minutes remaining is plenty of time to pull up a State example. There's still brain cells that Haven't been melted yet. Do you want to pull up your Stabs me in the back. So the one thing they didn't talk about was redux. The fact that you can manage to do it. I'm pushing forward. Come on. I didn't get the refill. Pretty please. Okay, so we'll save that for another day. Does anybody have other questions about any of this? I use WordPress with beaver builder. And sometimes I use short codes. Short codes on ultimate. And I notice that sometimes those short codes don't always Work with beaver builder. Now, I forget, I guess if this Gets into the core, I guess all the, those frameworks, I mean they should all be working with this. But if we're doing more customization in our own Attributes, could there be a situation where Sometimes the attributes that we add, you know, The customize may not work with the newer, like beaver Builder or divi or whatever. So i can't speak for all of the page builders. Beaver builders made it very clear that they're excited about This. I've talked to a few of them, but I've also, they wrote a really good blog post on their site About, yes, this will change what they do with beaver Builder. But they think that long Term by integrating with core blocks, it'll make a better Page builder. And i think that some page Builders are likely just kind of to do their own thing. It'd be an alternative and some are likely to integrate with core. And as we start to get to multi-column and nested and Repeatable and group, like, there's all these different Proposals for how you can have modules that are shared Between and like reasonable blocks are already a thing. I think, you know, i'm somebody who uses a page builder Because i have no sense of design. But i'm not using it for Anything super complicated. I would suspect that for Somebody like me, because i'm not doing design heavy sites, I just kind of need things to look the standard way. That Gutenberg will be enough. But it's unclear how, When, where that new demarcation will be. It's pretty low bar right now where you're like, i don't Know html or css or don't really want to write it. Post editor doesn't do a lot for you. You need to use a Page builder. I think that bar is going to get Higher because it does stuff. Multi-columns. I have a short code plugin that nested short codes for boot Strap stuff that i installed. It's a pain in the butt. So much rather a multi-column block. But i installed that plugin because it was the way without Doing anything fancy in the post editor to have multi-columns Or tabs or whatever. I'd rather use a block for that. And some of the things i'm using page builders for is Consistency and color pallets. Elementor has a color pallet Feature. Everything defaults to your preset Slight color pallet. That's beautiful. Because i don't. Somebody else figured that out. I think those kind of things may or may not still require Page builder. But at the end of the day, Some of those page builders have their own ecosystem. They have very custom things that probably don't belong To the core but are super useful. So i don't think it replaces A page builder. I think it could make page builders A lot better. With beaver builder, for example, for the foreseeable Future, they'll have a block that says open in beaver Builder. Just like now how you have Like you do one or the other. They're slowly looking at How they can make beaver builder modules as blocks. But for almost all of the page builders, they're still Going to kick you out of Gutenberg, open you up in a New tab and give you the page builder environment. And i haven't talked to a single one that is like, Which is what, bold grid? Do you want a bold grid? They're one of the ones that actually keep you in the Content editor. And even that one is still Going to need to rely on the classic editor going Forward because it's just, it has, not everything has Been ported over to block. So most of them, Even when 5.0 rolls out, you'll see no changes With beaver builder. It'll keep popping you up In a new tab and work the same way. I think one of the problems in the ecosystem is the fact that There aren't these standards. And so everybody kind of has been Building their own thing on top of, to deal with the post Editor problem. And how much do we need all those Specific custom versions because some people like one Page builder, some people like the other and know it And learned it and invested in it. And how much Gutenberg makes those better, how much Gutenberg reduces Who knows? Whatever works for you is a good guideline. When 5.0 comes out, people will be able to go back to the Traditional editor and i've forgotten the answer. Yeah. So the question is, this is a great Question, once wordpress 5.0 comes out or Gutenberg is installed, can you go back to the classic Editor? Classic editor is the proper name for what is Currently the default. In the Gutenberg right now, There is edit post. In the post list, there's edit post And then there's edit with classical editor. There is a plugin in the repo that allows you to globally Disable it. But the other thing to keep in Mind is that post types have to opt into it. So core is now going to opt in for post and pages. But if you have an existing post type that you've kind of Used a cf4 to like build out all of your stuff and it Works, why redo it? But in the future, you might Want to start from scratch at Gutenberg. But like you have Something that works? Just don't load Gutenberg on that Post type. Yeah. Yeah. So there's a lot of Benefit going to Gutenberg, but it's not a Requirement and there's a lot of wordpress out there That's built, where it's not really, there is no, A lot of post types don't have a post editor. They're just a bunch of custom, you know, fields, be it a cf or Be it hard coded meta boxes. And maybe there's a benefit to Using Gutenberg components to compose those meta boxes in The future. But it's like, it's not post Contact, really. It's a bunch of fields that get assembled And the themes already built out that way for the site. Maybe that's good to let it be. The other one is that By default meta boxes should work. There's going to be edge cases. A lot of work. I'm really impressed by the amount of work that's gone into Making them. It's a really nightmare of a Problem. jtrip and i had this conversation about Two or three years ago out here after the word javascript Track was like, how do you make it so it dynamic we can Use the rest api to save? Yeah, but the save post took for All the meta boxes is a nightmare of a thing. I don't even want to think about it. It's been basically solved that the yos meta boxes Kind of shows up down there. It's not always going to Work. Most of the time it should work. You can in your register meta box now, and this is in the Handbook for meta boxes, how this actually works, you can Specify that this meta box is not gunenberg compatible. That will cause if it's present on the screen to revert Back to the classic editor. And you can also register a Pre-existing meta box. You can label it as for Backwards compatibility. So that way if your plug-in, which Works fine with gunenberg, has a legacy meta box, which you Still want to leave there because they might install it in 4.9, And then it's used on some post type where some other plug-in is Causing the problem, it will fall back to using your Meta box. So that's kind of like these Like five different ways that it can be disabled. It really kind of depends on the context because some post Types don't need it. Some post types have existing Functionality, but for the most part you should be able to plug It in and it will work. Is there a question over there? One thing that beaver builder is saying too is they envision Using beaver builder for pages but turn on gunenberg for Posts so you could still design some content and it Definitely doesn't have to be all or nothing just like you Were saying with a custom post type you might have it on Or have it off but something else on. If your site has some custom post type that just kind of works That's no reason not to use gunenberg for post and pages. Or if for some reason your pages kind of don't need this Leave it on for post, leave it off for custom post types. I see it almost would be like unifying for all of them. Yes, i think that's what's exciting is that themes can Kind of just be css. So what would be really cool for Themes to be is hey when you install my theme you're going To get a totally different look to the gallery block. It's the core gallery block but my theme has this special Presentation level. That's css maybe javascript. Or maybe my let's say woocommerce adds a bunch of Blocks. We can assume that. At some point woocommerce is going to have an update. It's a process that it started really with. When you're starting with a phone with you. You're dealing with so many with such a smaller area That the layout becomes irrelevant. So that the way your brand is going to be these Elements that i just collected in that term texture. Yeah, but think about also what a woocommerce compatible theme is today. It's a theme that has really good css for the Or javascript for the short codes that woocommerce ships with. Right, so that way if i or you know the default layouts Of a woocommerce product page of a woocommerce product gallery. Just spend the elbows deep in. Yeah, we're trying to. Yeah, but you all checked out the Gutenberg theme. Have you seen it? It's a good start point, but that's what i think or like Let's say that you know a framework like genesis or whatever Might potentially have a set of special blocks. Genesis blocks, just like their genesis widgets now. Right, in child themes to genesis, part of what's good about it Is that they have this really nice presentation of a genesis standard widget. Well what if genesis had a standard set of genesis blocks In my genesis child theme was the css to do that kind of stuff. Right, in that kind of changes. Okay, i'm looking forward to it. I like genesis, i don't think we're really themes, but i do like genesis. But i think that'll kind of be the secret sauce. Ah, css grid. Css grid is going to be very helpful for all of this. If you can do multi-column, if you can lay out your Multi-column blocks, which again is experimental, but if you Look at it, it's very neat. If you can lay those out with css grid, so all they're doing The static html with css grid, and then your theme is doing Whatever cool stuff with css grid, i think that's going to be a Really nice pattern. Yeah, it's been fun the last couple of months. Yeah, i mean, so i shouldn't be trusted with css. But i follow this, and i'm excited as a developer building Stuff with gunenberg, creating consistent html that's easy to Work with. That's my focus. And i think that if plug-in and core developers can stay there, In theme developers can do stuff, knowing that it's safe to Assume this is always going to be the same structure and The same classes, i think that will have a better word Press that's easier to create sites that look good with Minimal work. Right? Like, there are a lot of word press sites out there, And i'm like, there's a little bit more design skill That goes into this. And, you know, i think that this Will allow themes to help. We're just using bootstrap as it is. People kept saying, oh, yeah, bootstrap sites look all the Same. I'm like, you've got no bootstrap, And you don't rewrite it? Yeah, it does all look the same. So anyway, that's about it. All this code is on github. And we're going to put all of our slides there, too, so People can kind of, like, repurpose them for other word Camps if they want. But also, these are all kind of Good starter places for, you know, if you want to build Plug-ins. But we're going to be around The rest of the weekend, brian and zack and greg. So if anybody has goodenberg questions, there's matt Cromwell giving a non-developery talk, i think tomorrow On it. He's a good person to talk to. Kevin hoffman has been following a lot. There are a lot of people who really know goodenberg here. So i think this is kind of a discussion that can go on The whole weekend. But thank you, everybody, To the end. I was kind of intending to drive people out, Figuring that i would go to a complex for a lot of people.