 I think I'm going to go ahead and get started because we've got a lot of cool information to talk about and a very small amount of time in which to talk about it. So I'm going to show off some code samples and a bunch of different things. You're going to be compelled to write them down or ask me what was on there. Don't worry. My slides are already online and you can have all of them and the link is at the end. Normally give it out at the beginning and I realize I spoil all surprises by doing that, so just sit tight. We're going to write this together. I'm going to talk about how I made wpbingo.com using the rest api and view js and tailwinds css and a whole bunch of other stuff. Have many of you been playing wpbingo so far? Show of hands? No. Well, you can follow along and demo it. You can go to wpbingo.com right now and it should load up super quick even if the wifi dumps out. And we'll talk about how that works. And this came about because I kind of like to create little disruptions in events. I actually really like to create disruption. And before we get into all of that, though, I want to talk about what this talk is not. This is not how to make production scale ready view js app start to finish. I'm not going to show off like code samples that you're going to want to use in your next implementation. And we're not talking about lots of best practices. We're talking about building fun things and growing our knowledge and how to get from here to being able to make something like this in a production ready environment and charge lots of money for it, ideally. So this all came about from a simple idea. My wife and I like to visit disney world and we also like to people watch. And so we started just tracking the patterns and trends that we would see as we're watching people in this giant theme park. And I created a list in Evernote, just a bolded list of all these weird things we see like a pack mule stroller where someone has a stroller but no children. A stroller is just loaded with luggage and they're just carting it around the theme park. A tantrum from a toddler who's just had it like they're done. The day is spent and other funny things like this. We started making Evernote note and I thought wouldn't this be more fun to play with friends rather than just the two of us just referencing this Evernote note. And what would happen is we'd just be walking through the parking like bingo bingo as we'd see these funny things. And I was looking for an experience something that I could experiment with some new technologies. And I figured a bingo board is a really great way to figure out some new javascript tech play around some css things that I've been looking at. Plus once I've made it it's highly adaptable. So it's not just going to be theme park bingo. I can turn it into word camp bingo. And I did precisely that at word camp us. In fact that's where this photo came from. This was Matt's state of the word address. And people were playing bingo during the state of the word. And we started offering up money to the first person to audibly shout out that they got a bingo would take the whole pot. It didn't take too long. It was a lot of fun. So I needed to learn some stuff and I wanted to practice some things. So I wanted to learn a new javascript framework. In this case I wanted to learn how view js worked. And I wanted to experiment with local storage because I hadn't done anything with it yet. I knew that it existed but everything that I'd done previously was with cookies or with server side storage. And I wasn't playing with any of the cool browser tech that's been out for almost close to a decade now probably. And I wanted to try some utility-based css. Which is where tailwind css comes in. We'll look at that in a minute. And then I wanted to customize the wp rest api. Because I'd been doing some stuff with the rest api but I hadn't really done anything totally outside of wordpress. So I'd been using the rest api to help with type ahead searches and suggested search results. And lazy loading content, infinite scrolling, those kinds of things. So I'm just getting wordpress data in javascript in a slightly different way than creating my own custom admin ajax. So I wanted to do something unique with the rest api. And this was a perfect playground to do that in. And so I made wpbingo.com and if you haven't pulled it up on your phone it looks a lot like this. When you load it up it generates a random board for you. I think there are something like 70 possible squares that it can pull from. It pulls 24, puts a free square right in the middle. And then anytime you get five in a row in any direction you get a bingo. And you can choose to start a new game and when you do it generates a brand new board. And if you end up with a bogus board that you just can't win you can just hit the start and over button at the bottom. And it will wipe it and pull down a new one. And then as I mentioned I wanted to play with local storage. So it uses local storage to store all of the squares and the current found state of the squares on your device. So that when your wi-fi craps out or you don't have a signal as you're going from room to room you can still keep playing. Without it showing you the, sorry you don't have an internet connection screen. It was also really handy to prevent with the stupid auto reload feature that safari does. I don't know if the rest of you have been frustrated by this. But I'll be somewhere where I don't have a cell signal and I have a page that I was looking at just previously. And I open up that page on my phone and it goes hang on let me try to fresh the new information. You don't have an internet connection. Now you can't even see the information that you did pull up. Good luck finding the phone number for that building that you're standing outside of right now. Hypothetically speaking. So I wanted to build something. We saw what I built. So how did I get there? Well, I started with some exploration. And to answer the burning question that I'm sure some of you have. Why did I pick Vue.js instead of react? That's the common. Why Vue.js? Why not react? Why react? Why not Vue? Why not backbone or angular or any other framework to jure? Well, as I said, I wanted to practice something new. I'd already spent some time learning angular. I had played around with react. For those I made a license plate game because when my wife and I travel to Disney, we like to drive there because we have a family of four and it would be very cost prohibitive to fly. And so to pass the time while you're driving on a 24-hour road trip, you try to find every single license plate in the United States. And so I made just a fancy little itty-bitty javascript utility to track all the license plates we were finding. And that's how I learned how to play with angular and how I learned how to play with react. And now I wanted to do something similar to learn how to play with Vue.js. So I could see if it was something I wanted to use in production work. But two reasons that you might want to consider using it. It has zero external dependencies. So you can just include the Vue.js file and start writing code for Vue without having to compile anything. Unlike react where you have to use Battle or Webpack and pre-compile everything or transpile everything so it can work backwards and be available in every browser. The other reason, it's only 30 kilobytes after you've minified and gzipped the file, which is really small. I don't know the last time you looked at how big even just jQuery is, but react creates a massive file. So that itty-bitty utility playing around license plate game that I mentioned was not too huge. I think it was maybe 80k when I first wrote it in Angular. And then when I tried all the new cool stuff that I could do with react, once it compiled it back, it was something like 400k. We had to include all of react and all of react router and all of the shims to use all of the new features that don't exist in any of the browsers yet. It was a huge file. This is 30k. So that's pretty cool. Not to knock react, by the way. I've used react-react as cool and it's probably the go-to solution for most production stuff. But I also really like Vue because it's got a very simple syntax. And it works the way that I would expect and predict. It has a lot of opinions. So things are done for you. Whereas react is providing you lots of utility so that you can write things however you want. Vue is saying, I've already made these things. Go ahead and use them. Which is the same way that Angular is made if you've ever played with that. So it's a very... I find Vue to be somewhere between react, which is you have to build all of your own stuff. And jQuery, where it's all done for you and you just have to figure out what already exists and how do I use it. So it's on jQuery in the terms of I can just plug it in and start playing around and kind of knock around and figure things out. But it's like react in that it's got all this fantastic reactivity to it. And we'll check that out right now. So... Oh, good. It is big. This is a very basic Vue instance. And in here, we have a div that I've given the idea of app and a class of container just because I'm loading up Vue.js. And then I am setting my app variable to be a new Vue instance. I'm telling Vue that we're using this app element for outputting all of our stuff. And we can put all of the custom data that we want to work with here inside of this data property and all of the custom functions and methods that we want to use here in this methods property. And then you just expand out from here and you can do all kinds of neat things. One thing that I really love is that you get the reactivity for free automatically. So if you use vModel on an input, you tell it this is the piece of data that I want to track, which is I've named message. And now if that message changes in javascript, the input is automatically updated. If the input changes, the javascript is automatically updated. All for you. You don't have to do anything else. You just say vModel equals message. You type message inside of data here and vue takes care of the rest. And then you can have elements that are conditionally rendered. So you use vif. And so this container will only output if we have a product ID, for instance. And we have v4. So you can write four loops in your html. So four product in products. So for every single one of these, we want to output a table row. And we want to include the id, the name, and the stock quantity as table cells. And it will just iterate over every single one of those. I don't have to write any javascript for this. I just tell it this is the array of all of my products. This is what I'm going to call it. And here I'm popping out the values that I want to use. And it uses mustache syntax. So curly braces. You put two on one side, two on the other side. Pop your variable in. If you write javascript, you're probably familiar with this because that's how a lot of things work. And then we've got a couple more fun things. So you can bind your data to specific attributes. So here I want the href attribute of this anchor tag to be whatever my link value is. And instead of having to write v-bind semicolon, you could just write semicolon href. And it will automatically infer the rest. So it's got this nice little shorthand syntax to it. And that shows up in a few places. So if we want to bind a click event, and then we call the save product, anytime someone clicks this, we can do that. And we can shorten this further by just using the ampersand. So we can say at click. And so anytime somebody clicks this button, we call save product. Now, a quick aside inside of our aside about accessibility. This would be a bad pattern, expecting a click event, because not everybody is using a pointing device and clicking on buttons. Better would be to have a form, and inside that form have a submit. And then you can listen to the submit event that happens. And that happens whether somebody clicks on the button or presses enter or uses some other assistive tech. But I couldn't fit all of that on the slide without boring you. So in this case, when somebody clicks on this thing, we call the save product method, and then it takes care of things from there. We can also automatically say whenever somebody clicks on this, call prevent default. So we say onclick.prevent, and that way we don't have to add prevent default inside of our JavaScript every time we want to stop clicks from propagating throughout. And then finally, this also works with shorthand, so we can say at click.prevent, and that's all the same thing, but a little shorter. So there's our brief scary code segue aside. Let's talk about css real quick. There are lots of different things. Oops, I forgot to change the color on these. A lot of different methodologies for working with css. We've got object-oriented css. We've got b-e-m, which stands for block element modifier. There's scalable and modular architecture for css, which is smacks. And then there's atomic css, which is what I'm going to talk about here today. Each of these are pretty awesome and useful, and as you can see, I've got links in here. And as I mentioned, my slides will be linked so you can read all of these in great detail. But these are essentially slightly different methods for writing css in production. How can we best write our style sheets so that we can take advantage of the cascade and we're not repeating ourselves, but the class names we're using are expressive so that we can understand what's going on. Should we write semantical css where we're calling things a sidebar, or should we write object-oriented where we've got things grouped by a bunch of different properties? Atomic css, don't know what we're getting to here, is suggesting that rather than writing semantic css, we've got a sidebar and we've got a menu and we've got an article and then we write styles to support those things. Instead, we have styles that represent specific portions of our design. So we have styles for representing our margins and our padding and our different typography and our colors, and we just add all of these classes together to compose an element. So it might be a sidebar, but all of these smaller utility classes are actually what's determining how that sidebar appears. Rather than writing inside of our sidebar that we need to have padding of 1m and margin of 1m and font size of this and color of that, we give those classes and we don't have to repeat all of those declarations. And so we end up with a stylesheet that's really, really tiny. There are pros and cons to this and we'll look at them in better detail in a minute, but the atomic css approach, the framework that I used is called tailwind css. I saw a bunch of people tweeting about this a few months ago and I wanted to check it out and see what it was all about. And it's a utility-first css framework is how they described it. So if you're familiar with bootstrap, bootstrap is very much a template-driven stylesheet. It gives you predefined classes for button or form or menu, and then it loads in all of the styles that it needs. Tailwind has none of that, and instead they have lots of utility classes. So if we want to make sure that something has a particular margin or padding, for instance, they've got all of these classes based around the shorthands here. So if we wanted to say something with a margin and we wanted to affect the top, right, bottom, left, etc., and then how much we want it, we can put all of that into the class name. So for example, mx-auto means margin, horizontal, auto. So it'd be saying margin-left-auto and margin-right-auto. And you just add mx-auto as a class name in whatever your element is and you get auto-margin on the left and right. My-4 would be like saying margin-top, one-rem, margin-bottom, one-rem. And then p-4 would be like saying padding, one-rem, and it adds padding all the way around. So it's really slick. You only got a couple of characters here and you add it to your element and you can tell from looking at the element how it's going to be styled without having to go to your style sheet, which on paper sounds awesome. We'll come back to that. What it allows is for you to make something really awesome, like this little alert box, without writing a single bit of custom css. But what you end up with is this very verbose list of classes. But here we see we have a background of white, margin-auto on the left and right, a max width of small, which is defined a large shadow, we want large rounded corners, and we want the overflow to be hidden. And then inside of that, we've got a small item, or rather, when the screen is small, it flexes when the screen is small, the item center, otherwise we've got a padding on the left and right of 6, which I think is one and a half rem. And so they've got it all documented, so you know what each of these short hands are and you can start to guess what they are because they all follow a predictable pattern and you can write your style sheets very quickly, because you're only writing very few utility classes or you're picking up a library like this one where they're already written for you and you just start to use them. And so you have a style sheet that's laced with this, but you never have to write another bit of custom css after This because everything can just adapt from here. Obviously the trade-offs, right, we have to write way more in our Classes, but if you use this with a build tool, like sass, Well, now you can still have a sidebar class, and your Sidebar class can extend or implement all of these, right? And so now we only have to have a class of sidebar here, And then all of these get automatically injected when your Sass compiles back out to css, so you're still not having to Write a bunch of css, you've got all these composable bits to it. And the arguments here are when you have to add a new item To the page, you have to modify the html, and once you've Modified the html, you have to go and modify your css to Declare how you want this new html to look, right? And then you get a change order from the client or scope Creep, as it is sometimes known if you're not getting Change orders, and they say we'd actually like this button to be Over to the right, and it needs to have an icon in it, okay? Well, now you add the icon, and now you add the styles to Support the icon, and you change this other thing, and then Something else about the project changes, right, and you Have to add a little bit more html, and you have to change Your css, and so no matter what, you have to change These things in both places, you have to change the html And the css, and so the benefit of having something like This is you can completely change the arrangement of this Component, we can add another thumbnail, we could get rid of The thumbnail, we could add a second button, and we don't have To go back to our css to say, okay, well, now i want it to Look this way, we can just change what classes are being Applied to the element here in our html, and we don't Have to change one thing, which is really cool, and if You have to write this stuff anyway, right, now we're just Writing it as class names in our html, so this gives us The flexibility of having inline css without the awful Terrible non-maintainability of having inline css, so We have our css tucked away in our style sheet, but we can be Very declarative here in all of the things that we want this Container to do. It's personal preference what you Want to do, i thought this was pretty neat, and we'll see What it can do when we get here into the prototyping stage. I don't know that i would use it for a full blown website Necessarily, but it's got my brain thinking. So to recap, here's what i wanted to accomplish. I wanted to learn a new javascript framework, i wanted To experiment with local storage, i wanted to explore this Atomic css concept, and i wanted to customize the rest api. So i really enjoyed view syntax. I already mentioned that. We got to see some of view syntax in those examples early on. It was just, it felt really natural to write my javascript Inside a view, and if you pull up wpbingo.com in your browser On your desktop and your view source, you can see all of My javascript in there. Warts and all. I didn't bother to clean it up for this, because this was just A sample project that i wanted to do, so i wanted to show off What it's like to just write a sample project where the Stakes aren't too high. So inside of view, we have to Prep our data. I showed off that data attribute In the beginning, and so this is where i stuffed all of the Things that i needed to track. So for my bingo game, i Need to track the start time, i need to track the victory Time for when you won, so that i can then calculate the elapsed Time and say, hey, congratulations. It only took you 0 Minutes and 46 seconds to get that bingo. I wanted to know what the winning set is, so i can show all Of those cells inside of the modal. We have to check is the Modal visible or not. Should we show the keynote Link or not? Spoiler alert, that keynote link is going To show up at about 4.30 for today's keynote. Keep that under your hats. Oh, you already knew that. And then we had to track the game board, so all the cells That you're working with, and then the keys for the possible Winning combinations, which we'll come back to in a minute. So the markup for this is pretty easy. I've just got a div, and that's wrapping the whole thing, And inside of that div, i have a lot of other divs, 25 Of them to be precise. So for every cell in the Game board, we are outputting this div with a label inside of It, and inside of that label, we've got a span for the text, And then the checkbox input, which is hidden, and when Somebody checks this, so when it changes, we track that Change, and the value for it is the found value for this Particular cell, which is just binary. One if you found it, Zero if you didn't, just like a checkbox, two are False. And then that controls a few Other things, which we'll see in a minute. Adding custom methods, i redacted this because that's like the Entire file, so i have lots of small functions because i believe That a function should do one thing, it should do it well, And it should do it only. So if you have to use the Word and to describe what your function is doing, it is Doing too much. So i have lots of itty-bitty Little utility functions in here, even though we're only Used by one other function, and all of those functions just Get stuffed inside of the methods property of my view app. So they're all encapsulated and self-enclosed inside of you. They're not in the global namespace. I don't have to worry About colliding with the view app that you wrote and Everything breaking. One of the cool things about View, which makes it more like react, but this does Require external dependencies and build tools, is that You can make lots of smaller components. So i could have had one component that is a game board rather Than writing it as a div here, and then i could have another Component that is a bingo square, and so my game board could Load the bingo square, and each of them could be responsible For their own separate things, which is even better. I did not write it that way. I mashed it all together Because it was faster to write and experiment and learn. And then tapping into local storage is super easy. I don't know if everybody was way ahead of me on this, but it Is probably the easiest thing that you can do in javascript. Almost as easy as working with a cookie, except much easier Than that. So to put something in local Storage, all you need to call is local storage dot set item. That's it. You give that item a unique key, And then you pump in the value of whatever your item is, And now it's stored in the browser's local storage until you Clear it, or they clear it, or it expires at some other point. And so i have to store just two things in local storage for this Game to work in offline mode. One is the game board, so all Of the squares that you're being shown and whether or not They've been found, and then your start time, because i Need to know that so i can calculate the elapsed time When you're done. Everything else can be rendered Dynamically, and we only have to make one server request To populate the game board on page load, and after that it Can work from local storage the entire rest of the time that You're using it. Getting the data back out of Local storage is really tricky, though. Instead of calling set item, you have to call get item. So that's how they get you. And only have to give it as The key. So you use set item, And you give it a key, and here's what the thing is, And then you call get item, and you give it the key, And it gives you the stuff back. You'll notice here that i'm Calling json.stringify before i stuff it into the local Storage, because it's just storing text. So you can't just stick a json object in there, because What you'll get back is a text string that says object, Object, which is so helpful in javascript. So i have to convert it to a string to put it in local Storage, and then when i pull it back out of local Storage, i just parse it as json, and it makes it a json Object that i can continue to use inside the app. And atomic css is real slick when you're using a well-documented Pre-built utility like tailwind css. I didn't have to write 100 Different margin classes and 100 different padding classes And all the different color and background and stuff. That was already done for me. But as we already saw, It makes things really verbose. So i've got container with mx Auto, mb4, px2, flex, flex wrap, which says that this Container element won't have anything greater than, i Think, 1100 pixel width. It'll have a margin auto on The left and right, a margin bottom of four, which is Actually one rem padding on the left and right of two, Which is half a rem, and then it implements flex box and will Wrap all of these items and so on. I'm not going to read all that To you. There's a lot of different classes to Write. But we have to write that stuff somewhere. It was pretty fun to just write it in there, because this is The entirety of the custom css that i had to write to make Wpbingo.com. I don't know if you noticed, But there's a lot of things that are styled on that page. And i had to write these two lines, because for some reason They didn't bake in to expect that somebody is going to try To make a bingo board out of this, and they want the cells to Be vertically stacked and share the space to try and make as Close to possible of a square. So i had to write that myself. But the rest all came from tailwind, and i just added Classes and worked on the fly, and it went really quick. But then i learned that scoring a bingo game is not a very Well-documented coding problem. Turns out there's not a lot of People out there on the internet who are making bingo boards and Saying, hey, everybody, here's how i scored this bingo board. So i got to build a whole bunch of new knowledge and figure Out how the heck am i going to score this thing myself. I have an entire array of 25 cells. They're found and not. And so what i figured out is that i would define all of the Possible winning combinations. So we've got all of our rows, Which include 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, and all of our columns, Which are the same thing, but rotated, right? So one column is 0, 5, 10, 15, and 20 in the array. And then diagonals. And then from these, i build the Winning sets. So we take those set keys, And for each of those, we grab the bingo square that belongs To that array key, which can belong to multiple groups, Because we have both horizontal and vertical and diagonal. So that very first square is at minimum in three different groups. And then from there, we've got score set. So i'll take one of those arrays, and we will count up how many Of them have been found. Very useful to use binary in this Case, because it hasn't been found at 0. If it hasn't been found, it's 1. So if you have an entire row Of found ones, that means we have a score of 5. And if we have a score of 5 when we score that set, Good news. You just got a bingo. So we are going to take that set, because we're iterating Over it outside of this, way back here. No, i don't have it on the screen. I have a check for wins function. And that check for wins function calls score game, As it iterates over each one of those sets. And it looks to see, is this a winning set? If it is, perfect. Add that to our winning set data. And then return true, otherwise return false. And we don't have a victory. And that's the entirety of how i score the game. Just four different functions. One to build the array. One to check if any of those arrays has a score of 5. If one does, we set victory to true, which causes the modal To show up, thanks to the v if statement in view. And then we have to register custom end points, because this Is driven by the wordpress rest api. So where are we getting this data? how are we getting it there? And this contains the entirety of wordpress code that i had to Write to make this. You ready? I went to wp cli, and i typed wp scaffold, plug-in, Wp bingo, skip tests, because i'm not going to write any Php unit tests for my tiny little headless javascript App and activate, because i always forget to activate a plug-in After i've created it, and i'm going, why isn't this working? I forgot to activate it. Success, we have a plug-in. Next, wp scaffold, post type, wp bingo. And i give it a name, and i give it an icon, and i tell it What plug-in it belongs to, which is the wp bingo plug-in That we just created. Then i created one taxonomy, Success, created a taxonomy for the bingo cards. Success, created a taxonomy for the bingo category. Success, and now in four lines on the command line, i have a Post type and two taxonomies inside of a brand-new plug-in, And it's ready to go. And all i had to do to get it Accessible via the rest api is nothing, because we get that for Free, because the rest api is written so well. And if you created your own custom post type a long time ago, you might not have it in the rest api, because Maybe it's not defaulting to true, but all you need to Say is show in rest is true inside of your register post type Definition. I cut out all of the other Bits, because they're not relevant to this. I think we all know what post types are. If you don't, you Should google register post type, because it's really well Documented on developer.wordpress.org. You don't even need to have rest base or rest controller Class set, because just setting true will default to Using the slug up here for your post type as the Rest base, and by default it will use the post's controller for Making it accessible via rest. So you really only need to Define these bottom two lines if you want to change that. And that's it. Just by the sheer nature of My post type existing, it's available to me in the rest api. I did have to make one modification so that i could Sort things randomly, because i want to get 24 random Squares every time somebody is building a bingo board. And by default the random sort is disabled. So i filtered the rest wp bingo collection params to say that When i specify order by, i am allowed to say that it's random. And now it won't yell at me when i try to do that in my Rest request. Don't do this in production, Because it is very non-performant, because it is Very non-cashable, which means that if somebody found out About this and stuck a botnet at this web address, they Would bring down the server by hitting it with thousands upon Thousands of uncashable requests until it cried uncle and Collapsed. You could add caching to it, Which is wise, or do it slightly differently so that it doesn't Bring things down, but that's why it's turned off by default Because it's not performant and they didn't want everybody's Website to suddenly be susceptible to a ddOS attack. Next, i had to modify the rest response. I didn't have to, but i wanted to, so i wouldn't have to Use the script to say just give me the title and we're going To call that a label and set found to zero by default because Nobody has found it because we're building a brand new board. And that's it. That was everything i had to write in Wordpress in php to make the thing work. Then it works when i hit it via postman to make sure that Everything's there. And that's it. So i have a bunch of additional resources if you want to Learn more about the rest api and how to do cool stuff Or about modular design and do cool stuff. If you want everything that i offer at wp sessions for this Weekend, it's half off. I don't ever do that. So that's a pretty big deal. If you want to learn more about View, if you want to learn about tailwind or atomic css, There's lots of resources here and you can get all of them At wpsessions.com slash wc mia, just like the hashtag for The event. So there you go. That's how i made it. And don't forget to play during The keynote because you could win a prize if you get a bingo While matt is being interviewed by john. And you tweet out a screenshot of your victory. So yes. Oh, yeah, that's not in there. Yeah, tweet a screenshot. Make sure that you include the Hashtags wp bingo and wc mia. Otherwise we won't know that You won and you won't be able to win whatever the prizes are That you're going to win right after the keynote is done. And that's it. Thank you all. Our next speaker. Thank you. You will be available for questions. If you have any questions, I'm all around.