Geoff Kimball, Product Designer • Wikia, Wednesday, Jan 13, 2016
Geoff Kimball from ZURB, a main architect behind Foundation 6, a popular CSS framework, presents and explains how Foundation 6 uses their new static site generator Panini as a central build tool.
Panini is a custom built, light-weight static site generator that works as a plugin to gulp. ZURB migrated from the grunt based assemble, to Panini, when launching Foundation 6.
Full transcript of the presentation below:
[Presenter: Chris Bach] Okay. So maybe I’ll come on all of a sudden. Anyway, thanks so much for coming guys. This is our fourth meetup, Static Web Tech Meetup and we are really excited today as Foundation 6 has chosen to work with the static site generator intimately as part of the setup. And Geoff right here from ZURB Foundation is here to tell us more about it. So, thank you very much. All right.
[Main Presenter: Geoff Kimball] Thank you. Please keep clapping. Well, thank you. So my name’s Geoff from ZURB once again, those are my first two slides, I already blew that part. First off, thank you so much guys for having us. We’re gonna have a lot of fun today talking about Node and static sites, those kinds of things, let’s get into it.
Today for my talk I’m going to talk about the ZURB template which is a kind of new thing that we rolled out along with Foundation 6. It’s basically a way for users of Foundation to use the same tools that ZURB uses to deliver front-end code to clients. And we do that through the Gulp task runner and also a custom templating thing that we wrote called Panini. Together the two form a delicious-build system.
So I’m Geoff Kimball. Those are @ signs you can look at. I am a designer and a front-end developer at ZURB. ZURB is a little agency in Campbell, California, near San Jose. We work with companies both large and small on many kinds of design problems. We also maintain open source projects on the side so we’ve been very heavily invested in open source for like five or six years mainly with the Foundation framework. Do any guys out there like use Foundation in your projects? Okay, I know what framework you guys all use.
So let’s talk about Panini. This is a Node library that we developed specifically for the ZURB template to solve the very specific problem of like compiling flat files from a bunch of elementary pieces. For about two years, ZURB used an internal template for a client work which is powered by Grunt and Assemble. This was something that at first was actually just another branch of a template we had and whenever you’d start work at ZURB they’d be like, “What do you use for client works?” Like, “Okay, we’ll go find this branch of this one thing. “That’s what most people use.” Eventually we standardized that into a client template but we kept it a secret because nobody else should know about how we deliver code. With the launch of Foundation 6 we knew that we wanted a kind of a more robust ecosystem around the framework. We wanted more tools to help people get started quickly so that’s why we came up with more templates. We developed a full GUI called Yeti Launch which is similar to CodeKit or Kitematic. It’s basically a GUI that allows you to spin up Foundation projects without having a full dev environment setup. Like we’re really big on trying to kind of make our ideas accessible to people. With that we said, well why don’t we take the tools that we’re going to use to deliver Foundation 6 code to clients and just give that to our user base? Because there’s really nothing secret about it. There’s no server passwords, there’s no weird configuration in there. We tend to use the same tools that any other web developer would use so why don’t we distribute that to people?
We use that mainly to deliver static HTML. ZURB is not a dev shop in client work, we mostly do design work. When we do front-end we’re very focused on pattern libraries. So, you know, we will deliver static HTML to clients and we will deliver a really kick-ass set of CSS components all written in SASS. Very well-organized and all very well-documented with a custom style guide that we designed just for that client. And we do all that with our client templates. We wanted to take all those bells and whistles, the things that we use in our internal process and we wanted to give those to the community. Right, so why not share that with people?
I wish that GIF was not that small. I blame Reveal.js. By making our own client stack public this allows us to do a few things. One is we can more effectively dogfood our tools. You know because here now we’re saying okay, like this thing is valuable but here’s why. Or because this is something that we use for our client work and we need to make sure that it is worthwhile. So by putting it out in the open we also can get more community feedback on it, they can help us fix bugs which they definitely have done already which is very nice. And it also can make our users feel cool because they’re using things a cool design agency uses. We were kind of big on that, that’s mostly a marketing thing but we’re definitely big on that, too. This idea of like here’s the thing we use, you know, right? Like we didn’t make this in a vacuum. This is designed around a very specific purpose and we are now giving that scaffold to our user base.
What does our build system do? In Foundation 5 we use Grunt for a lot of stuff. Grunt powered all of the different tasks we needed for the Foundation framework itself and Grunt also powered our client template. In making the shift from 5 to 6, pretty much across the board we switched our choice of task runner from Grunt to Gulp. A lot of that is because we kind of like the mental model of it for–admittedly it was hot at the time, you know, as now like NPM scripts are but we still like Gulp. We like it because it’s a series of tubes. Do any of you guys here like use Gulp in like any of your build systems or? Hands, hands, hands, hands, hands. Cool. Gulp is a fine tool and not just because it’s trendy, it’s legitimately a very nice tool. Gulp 4 is coming out soon and it’s making a lot of improvements to kind of how that thing works. So definitely worth checking out.
Once again, these are kind of the hot features. One extra feature in there which is not in the graph is so, you know, kind of like I mentioned before. We deliver style guides to our clients and we used to write our style guides with a lot of raw HTML that was run through highlight.js. We’re able to streamline that process from five to six and we created a small plugin for that called Style Sherpa which can generate a full HTML style guide for you from a single markdown file. This is another instance where we saw kind of two opportunities. One was to streamline a process we had. It was taking designers like a day or two to write a full style guide just because they had to code everything by hand. We kind of identified an opportunity to streamline an internal process and then take the tool that we wrote and give it out to the community for free. You know, just kind of like how open source is. We’ve definitely been leaning more into open source these days by taking all these useful tools that we build for ourselves and then distributing them to our community.
So why Panini then? There’s no shortage of static web site generators. There whole meetups for them so that’s probably proof that there are quite a few choices out there. Why on earth do we write our own? And there are a few reasons for that. Part of it, so we were kind of surveying that landscape. We used Assemble in Foundation 5 and Assemble is a really, really nice tool. It was just kind of a combination of factors that prevented us from using a larger static site generator. Part of it was that Assemble 0.6 which was in development was not done yet. That version was going to bring Gulp compatibility and a more flexible API, and part of it was just okay, well, they haven’t gotten it done which you can’t knock them for because you know, like even that we at ZURB get paid to do open source, we still fully understand the problem of like not being able to commit as much time as you want to open source. We’re definitely sympathetic to that. Part of it was just okay, we’re not sure if we can stick with Assemble because it’s not done yet so we’re not sure. Then we started looking for kind of smaller tools, like is there anything that can just do like really basic like handlebars compilation for us? And what we kind of landed on was that we just needed a kind of smaller more focused tool. This is actually the original version in quotes of Panini. This was just built in another repo where we needed a very simple Gulp plugin to compile handlebars, layouts and parsers into flat files. And I could not find a plugin that just did that one specific thing so I wrote it in about 20 lines of code. And this is almost what the actual 1.0 of Panini looks like. It was just segmented out to have more individual files, have proper unit test, all that stuff. But this kind of shows that the tool itself has a very like simple humble beginnings. It was designed for one extremely specific purpose. A purpose so simple and specific that you could write it in like 20 lines of code. And eventually that was something that we did develop into a full library.
When we thought about when we needed to have a templating system there was kind of a few things and these are things that are common to a lot of static site generators. We wanted the layout page partial model. Right, like that’s the model you get out of Jekyll, that’s the model you get out of Metalsmith. Or just kind of like any of these static site generators. That’s something that you get out of just you know, programming the language in general. All right, like you get that out of Rails, you get that out of any old framework like that. We need that of course. We need support for like page-specific data and we also wanted like useful helper functions for prototyping. We do a lot of prototyping with our static site tools. Like code that’s not necessarily for production. We were kind of looking at small things like oh, can we build a tool that also maybe helps us like, you know, repeat a lot of static HTML or can it inject placeholder data for us? We were kind of looking at a specific spin on this concept as well where it’s not quite static sites, it’s more like prototype sites because that tends to be more what ZURB’s client work is about. Even when we’re looking at this concept of building a static site generator, Panini is not something I would call a static site generator, I would call it a flat file compiler which is another set of confusing words but that’s fine.
From there we’re looking at this idea, like okay, well, if we need to cover this one area of our template of our static site generator which is HTML templating, what tool are we using? Because all the existing tools are like incredibly expansive which is a good thing but we already have this structure built. So the tool that we need just for the HTML part can be a lot more focused and that’s where Panini comes into play. Because Panini is designed to do one thing and do it very well.
There’s kind of a handful of development goals in there. One was very minimal configuration. All of the features are optional except for having layouts. All right, so kind of in a typical static site model, you have like common layout files and then you inject your pages into these templates and that’s how you get flat files. Those are the only required features. Panini also supports custom handlebars helpers, external data through JSON or YAML and it also supports external partials as well. Those are all optional features and the only thing you need to turn them on is you just point it at a directory of files. It’s extremely low overhead in terms of configuration. It’s also a very focused feature set. I’m definitely very fond of libraries and library maintainers who like to be opinionated about their work because that prevents feature creep, that prevents your library from going out of scope, and that prevents your library from overlapping with people who might be doing other things better.
We were never going to set out to actually like recreate Assemble or recreate Metalsmith or Jekyll or any of these things because the people who do that do it really well, right? We don’t really need to get into that territory which is why Panini is more limited in its feature set which is intentional. Because we can then focus on that one very specific goal of kind of compiling flat files and we can let Panini exist in kind of this wider cog or no, not wider cog. A cog in a wider machine of the full ZURB template that we have.
Because of that, then, it also doesn’t dominate the build process. It makes it easily replaceable. For example, one thing we’ve considered with the ZURB template is building Yeoman generators for it. Like right now we have just one ZURB template, you know it only uses Panini, it only uses Sass. It doesn’t have Babel, it doesn’t have pushCSS. It doesn’t have any of the things that people like to use. We’ve considered trying to think of the ZURB template as being more modular. The fact that Panini is just one piece of that machine means that like our entire build system is more modular as a result. Because the part where you compile the HTML is not dominating your entire build process. It’s one piece which means you can very easily swap it out.
All right, so small tools–and this is a thing that especially no developers love to talk about is the idea of small tools. There’s a prominent Node developer named Sindre Sorhus. He has published 600 Node libraries. The main reason he’s published 600 Node libraries is because a lot of them are like 10 lines of code. Because his thing is like small modules. It’s like well, I solved this one problem in 10 lines of code. Like what is the point of cutting and pasting it into other projects that I just make it like a module for you. The Node community definitely has a fetish for small modules and Panini kind of, that’s a little harsh. I like it. And Panini definitely fits into that idea of like this thing does one thing and it does it extremely well. And because the features set is focused it’s very easy for us to kind of swap it out for something that fits our needs better if we need it.
Along with Panini, the other big part of the Zurb template was a style guide generator we wrote. Once again, our big focus when we do front-end code for clients is making a pattern library. We use Foundation for all of our client work but we are writing a lot of custom UI components for the specific designs that we made for our clients. And we want to document that because we are doing a hand off to developers and we need to make sure that that hand off goes as smoothly as possible. To do that, you know, not only do we write very well-organized Sass code where every component is in a partial, we write Sass variables if we can. We also document all of our custom components with a style guide for that specific client. And this was a somewhat arduous process. If we kind of look at example of what that used to look like. Here’s kind of what the client template would look like, like kind of a stock one. Like we fill it in with a few very basic Foundation components and then our designers for specific projects will start adding their components to the bottom. A typical style guide for a client will probably have like 20 different sections, right. Like something almost the size of the Foundation documentation because there’s so much custom stuff that we wrote for them that we need to document. Now the process for writing this usually looks something like this. It was one very long HTML file. If you wanted to do a code sample with a live demo, you had to wrap it in pre and code tags so that it would run through highlight.js. And you had to not indent it or it would indent the code sample and mess up the formatting. Your entire style guide was this huge HTML file with a lot of weird indentation and like a alternation like this.
This was a thing where we accepted it for a while because it was just how we did things but we had to eventually find a way to make this stuff easier. To do that, this was once again a thing like with Panini where we wrote this very small library for one specific use case and realized it would actually be useful as a package that we distribute to people. Now we can actually write it in Markdown and we have a custom markdown parser in there that can take HTML samples and automatically render the live demo. You aren’t doing this nonsense of like doubling up all your code to show like code sample in a demo. You’re doing it all through Markdown in one page and it creates a full HTML style guide for you. Yeah, once again like we made it for one client and then that was a matter of cutting and pasting the code into a new project making it into an actual library with test and all that, and then distributing that as a Node package. And that package is called Style Sherpa.
Style Sherpa in general is less than 100 lines of code. That’s how it estimates once again like how small it is because it designed to do one specific thing which is convert markdown to an HTML style guide. And because the tool itself is very simple, it’s not very hard to maintain and we kind of always know what the feature set there is. Like we could have built it into Panini but that would also require maybe overextending Panini beyond what we wanted. You know, kind of beyond how we wanted to keep it as a simple tool. With that we ended up with kind of two different plugins for that.
In conclusion before I get into the code for that, definitely a core tenet of Foundation increasingly is kind of making complex ideas feel accessible. If you go back to when like CSS frameworks were a new concept, you know, just like the very existence of responsive grids kind of made responsive layout a little bit more palatable to people. It help people understand this idea that okay, you know, maybe on this layout if you have three sections they all stack on each other on mobile. But on a midsize screen maybe you have like a two up layout and on a larger screen you have a three up layout. And responsive grids made that very easy to kind of understand because we have class structures for that and now we have Sass mixin libraries for that. And we’re able to kind of solve those problems of responsive layout and then kind of distribute that to our users.
We do the same thing you know with the ZURB template, right. There’s definitely a big portion of our audience that is designers, not engineers. They’re not going to necessarily be as familiar with all of the bleeding edge front-end web development. And the bleeding edge is a complete pain in the ass to work with. I probably spend an hour or two a day just like helping people get out of NPM issues through no fault of their own. Just the fact that this stuff is so easy to break and like configurations are so easy to mess up that you can spend a lot of time fighting with build systems. So with that we said okay, if we’re going to go all in on this concept of using build systems, we want to create the scaffold for our users that is going to kind of make that feel accessible. Like here’s everything, we have a setup for you. We even built the GUI tool of Yeti Launch to even make the process of installing those templates a lot easier as well. We’re definitely big on making our ideas accessible to people. And I believe this is my last slide but do not clap yet because I have other stuff to show.
Those are kind of the elementary pieces of our build system. And what Gulp does is it makes it easy to compartmentalize all that functionality so that it’s easy to kind of reason about.
Next we’re going to pipe it through UnCSS for production builds. We’re then going to send it to minifyCSS which is going to compress it. We’re then going to send it through a source mapper so we get source maps in our browser. And then finally we get our finished CSS file which we then dump out to the disc, and then that is what the user’s actually seeing in their browser.
Once again, since Gulp’s whole thing is streams and plugins that are not aware of each other, it makes your build system highly modular. For example if you know you’re never going to use UnCSS removing it from your build process is as easy as commenting it out. All right, so now it’s gonna go source map, Sass, autoprefixer, minify, source maps, dest. It’s just going to skip that one piece entirely and that’s totally fine because autoprefixer spits out CSS. And minifyCSS takes in CSS. Those two plugins are technically still compatible even though they have no idea which the other one is.
This is really awesome in terms of like a way that we can kind of maintain our build process because if we want to add a new feature it’s very easy. For example, some people had, we had a feature request recently to add a plugin called Gulp Notify. What Gulp Notify does is it actually adds a like push notification when a task finishes. Adding that is as easy as installing the plugin for it and then adding notify, and it’s saying like Sass finished, and that’s all you have to do. Right, so it’s entirely compatible with the rest of our build process. All we had to do was add one extra line of code and then our entire build system would still work in the exact same way.
When we talk about Panini, that’s where we kind of get into this concept of modularity kind of helping us out, all right? Like some static site generators have full CLIs that mandate a certain directory structure. Some static site generators do more than we need this one specific thing to do. But if we need a more robust tool it would be very easy to remove Panini.
This is basically how it works. This is what it looks like when it’s fully configured. Pretty much all you have to do is just pass in the names of folders. You don’t have to give it file extensions or glob matching or anything like that. You just give it a name of folders and then it will take in all of your HTML pages and it will give you flat files out on the other side. And if we wanted to run this through any other other stuff we could. For example, for Foundation for Emails for Ink. Have you any of you guys ever done like HTML emails before? Familiar with what a nightmare process that is? This guy.
The way HTML emails work is you can’t have external CSS. All of your CSS has to be inline on the style attributes of the tags. That is literally how an HTML email works. I think I can even find an example for you. Let’s do that. We go in here and then here. Here’s all of our inline CSS. This is literally because most email clients don’t like external CSS. You have to take a normal CSS file and put all of the individual properties on the tags. That is how HTML email works. All of you, like none of you raised your hand except like two people. You are all extremely lucky that you don’t have to do this. And to be fair I don’t have to do this, my co-workers do. A build process is something that you could, you know, do this with.
If we were to go back to our other template, let’s say that this was actually an email generator but we still wanted to use Panini to have like a full templating engine for our emails. After we run it through our emails we might use the Gulp plugin for inlining CSS. All right, so we’d say inline CSS which is a plugin. We might use minify HTML which is another Gulp plugin. It’s very easy for us to tack on new plugins to a process just by adding a single line of code. And that is because of the kind of nature of Node streams. They’re just built around a plugin that takes in the file and then it spits out a file and that’s all it knows how to do. As long as the adjacent plugins know how to use the same file format, you’re totally fine. This is actually what our Foundation for Emails template does. It runs your emails through Panini. It inlines your CSS to make the monstrosity you see here. And then it also compresses the CSS with minifyHTML to compress the HTML to make your email even smaller.
Once again, this is a basic idea that like composability can create for really powerful build systems. It reduces your reliance on any specific technology. Like if we were to use like maybe for example like in our documentation we have a few custom tools. If we were to just use Jekyll for our tool set, if one day we didn’t have a feature from Jekyll we would have to hope that a plugin existed for that. But because our build system is completely modular and every single piece is isolated, it’s very easy for us to swap out technologies whenever we need them. And we think that’s extremely powerful for us as developers of Foundation and also for our users of Foundation as well.
All right, yeah so that’s what I got there. Thank you guys so much for listening. There are some @ signs again. If you guys have any questions about like stuff we do at Foundation please let me know.
[Voiceover] Sherpa sounds interesting.
[Voiceover] Don’t quite understand what it does yet.
[Geoff] All right. All right, I can roll with that. Let’s actually open that up. This is the boilerplate for the ZURB template. It comes with a page called Style Guide. This is an HTML style guide. This just uses like a basic tab group to kind of organize things. And we give you kind of these five like stock categories that are just things that are common in Foundation. This entire template is generated from one markdown file. If I go into the code for that I have it’s kind of hard to see this layout. I have a folder called style guide and I have this markdown file that does all this stuff. Basically, it takes every H1 it sees and it converts that into a single page. It’s all written in markdown. It’s a lot easier to write, it’s a lot easier work at code samples. I could add a new section down here. One, two, three, four. Let’s say that I’m gonna do one for a section, that’s what it is. And then I can go in here and I can add some like paragraphs of text. You know, the format is a lot easier. I can just use markdown for things. I can bold things, I can add links. That’s very easy. And the main hot thing here is code samples. Writing a code sample is easy enough so I can like you know, have some kind of button here. And when I render that it’s still running.
Now I have a new section here and it converted all my markdown HTML. It also ran our code sample through highlight.js to highlight it properly. But a common thing when you make style guides is you need to show the live sample below. That this is easy as adding HTML_example to this. And now when I refresh I get a full sample below it.
This seems like a small thing but it’s actually like something that people didn’t always automate. Like people would like specially like with our style guides we would paste the HTML sample. Like hope there were no special characters that would break it in the pretags and then put the line down them below. Even in the Foundation documentation itself we were actually writing both of these things by hand. Literally just by writing one very simple markdown function you can kind of extend the markdown code fencing syntax to allow for this. Those are kind of the main things we do there. We are interested in expanding this tool to make concepts like generating color palettes easier, things like that. But for now it’s basically a way to streamline a process we already have and make it probably take like half the time.
[Voiceover] So was that sort of like a template for SuperCollider or something or?
Yeah. Oh you’re the guy who tweeted at me about this.
No? No, you’re not? Okay, never mind. A guy tweeted me about SuperCollider and I was amazed somebody did that. This is very similar. I actually borrowed the same code snippet from that. SuperCollider is our documentation generator. It’s whole thing is that it combines data from multiple documentation generators into one. Whereas like tools like SassDoc, JSDoc will give you a stock template. This one is designed to take things for multiple languages and mash them into one. But yeah, we have this exact same thing in the markdown parser for that one because this specific thing is something that we use all time in our documentation. Literally just being able to not cut and paste things saves us a ton of time in writing documentation. James, you had a question?
[Voiceover] Yeah, my question was is it just limited to like HTML examples maybe for?
Well some part of it is that you can’t like really render a Sass or a CSS example. The reason this one works is because you’re just taking HTML code and then pasting it below the code sample. It doesn’t have support for CSS because if you do that like what exactly are you previewing below it? For now it is mostly for HTML. And you could maybe use something like JSX or something but I think it’s about it.
[Voiceover] Can you use Bootstrap instead of Foundation?
You could, you could. You know, we’re not going to encourage that but realistically, none of the tools that we write because like frameworks are just CSS mostly so it tends to be pretty environment agnostic. I’ll share a secret with you, here’s the config file. I’m not gonna do this but you know, you could replace that back package. Yes, it is possible to use the stack with not Foundation. Actually the style guide would break because it uses Foundation CSS but everything else is totally agnostic. Just don’t tell my boss I said that.
One of you had a question? I saw a hand raised, there’s one in the back.
[Voiceover] So, when you’re actually writing HTML what do you use in the templating, what does it look like?
We use handlebars. If I go to my base layout here. We use handlebars for our templating mostly because it is probably the easiest to kind of grasp in terms of the syntax. Like if we compare it to like lodash which has like two whole symbols, things like that. Or like Slim or Jade templates which use that kind of Python style, like only indented syntax. HTML tends to be the easiest for people to understand we found because it can layer on top of HTML very easily and it’s just two curly braces so it’s also a lot easier to type. That’s why we tend to use handlebars. We might extend this tool eventually to have multiple like a guy asked us if we could add Jade support but for now it’s just handlebars.
[Voiceover] Did you look at JSX?
We did not, no. I mean, that would be interesting. I’ve not actually seen JSX used for client side templating mainly because I’ve not seen it used outside of a React context but that would definitely be interesting to kind of look at. What’s up?
[Voiceover] Is there a composite to front matter throughout the templates?
Yeah, there is front matter support. Any individual page can have a front matter block. Part of that is like if you want to change the layout you can do that. If you have multiple layouts like maybe you have like a blog or something you can do that. But you can also insert whatever metadata you want. Like if I want an important list of breakfast I can say. And then that will be injected as a handlebars variable. I can say like each breakfasts. And then I can iterate through that very easily. It is also possible to inject a global data so you can define a data folder and you can put in JSON or YAML files and it will inject those for every single page it wants. It is possible to get in static data through that way as well. You can do page level and you can do global data.
[Voiceover] Is there any way to have pages that doesn’t have like a one to one corresponding–
Right, right. That is one thing that Panini does not do. It can’t make a directory listing for you. That is something we could add but that then gets back to the idea that we use this for more prototyping than the static sites which is why we don’t have some of those features. But that is something kind of on a list of features that we would like to explore.
I had mentioned that maybe we would do more stuff with like rich data in these style guides and one example I gave was generating color palettes. If we look in here we give you this kind of basic section for defining a color palette. The way that it’s made is just with HTML. This is all just handwritten HTML which is annoying because this is structured data. You shouldn’t have to write out HTML by hand for something that is structured data. If there are ways that we can do things like that for colors or typography or like very basic elementary elements that you would always display the same way, I would definitely like to explore that. Like if it’s something like oh, you have a front matter block and you give it an array of colors and it generates that code for you, something like that.
[Voiceover] If it’s only used for prototyping, then why the focus on performance, minifying js, etc.?