After over 2,000 Git commits, kaidez.com gets a long-overdue redesign. It was a struggle due to limited free time, but it was also a lot of fun and an excellent learning experience.
The README uses a lot of verbose code-speak so a non-verbose (but also lengthy) walk-through is probably needed. So let’s proceed with that, shall we?
Table of Contents
- Goodbye, WordPress…
- …Hello, Jekyll
- Design In-Browser
- Mobile First
- Overall Design
- SEO & Accessibility
- Web Hosting
- Grunt & My Deployment Workflow
- Post-Launch Tasks
If you’re a regular GitHub user then you’re probably familiar with Jekyll, the blog-aware static site generator. Sites that run using GitHub Pages give Jekyll its underlying HTML structure, so the word “Jekyll” is regularly thrown around in GitHub circles.
I used Jekyll to create multiple site layouts using Liquid, a templating markup language with some internal logic. Whenever I run
jekyll build from the command line while in my project folder, Jekyll utilizes the templates and logic to output a static, production-ready copy of the site.
The outputted site does some very cool things…here’s short list:
- lots of content is written in Markdown…it all gets converted to HTML.
- the logic displays posts on the home page in a very “dynamic” way (more on this in a future post).
- four category-specific pages are generated.
- an XML-powered RSS file for syndication is built.
- an HTML site map is created.
- a short list of related posts is placed at the end of each post.
Ruby is a Jekyll dependency so this site does use two Ruby-based plugins at the development level: one for generating a search engine-friendly XML Sitemap, and one used in conjunction with Lea Verou’s excellent PrismJS syntax highlighter plugin. But Jekyll really does the work of prepping this site’s content for deployment.
Because it generates static sites, Jekyll eliminates the need for SQL queries and server-side script parsing. Combine that with asset minification, applying a cache manifest and using MaxCDN to serve up static content, kaidez.com loads into a web browser pretty fast. Ads, social networking widgets and images slow things down sometimes, but the site’s overall page-load time is still minimal.
I exported the content from my old WordPress site to Jekyll using the WordPress to Jekyll Exporter, but the Jekyll migration docs lists alternative export methods. Also, Vito Botta’s two-part article on importing content from WordPress to Jekyll is the definitive article on the subject.
Jekyll is increasing in popularity: I’m guessing this is due to the fact that it can easily create a site which can be hosted on GitHub for free. Also, Jekyll’s attracting lots of contributors that are working together to make the platform better.
I’m happy with Jekyll but please note that walking away from WordPress was not easy after using it for five years. WordPress did a lot of work via its high-quality plugins…work that’s now 100% my responsibility.
Migrating from WordPress to Jekyll isn’t always the “right” solution: a succinct post from Chirs Coyier sums up why.
And let’s be fair: it’s easy to generate static content with WordPress. There would still be some database interaction so Jekyll may implements things faster, but it’s possible. Frederick Townes’ excellent W3 Total Cache plugin performs HTML static conversions quite well.
Also, Jekyll is definitely geared towards the blogger that likes to write code so in most cases, it probably won’t be used for a client solution. WordPress, Drupal, SiteCore and Joomla are still best of breed in this arena, my personal preference being for WordPress.
While I did use a pencil and paper to sketch out the site before coding things, I completely disregarded wireframes and PhotoShop mockups. Reason being, wireframes and mockups don’t account for the differences among the various browsers and devices…at least, not well.
Instead, I designed this site within a browser using various desktop and remote tools to debug against the different browsers and devices. This was easy when I started working in WordPress and even easier when I jumped over to Jekyll.
Divya Manian outlines the design-in-browser process better than me…
“Mobile First” has gone from a buzz word to a de facto standard. It basically means “develop and position content for mobile devices before doing so for desktop devices”…this should always be applied to both content strategy and code.
No issues with applying Mobile First to my content strategy. I did a complete content audit of my previous site based on the ROT principle, then either eliminated lots of content I didn’t need or moved it to the bottom of the page.
Going Mobile First with the code was a bit of problem that still needs to be cleaned up a bit. This site is responsive via CSS3 media queries and I implemented the method outlined by Jon Korpi, coding a vertically thin, non-responsive layout outside the media queries, with the help of Sass, of course. All of this is for the benefit of oldIE.
I may not have implemented this method properly…I ended up writing more code than I planned on. The code “works” but I know it can be neater and need to revisit it.
Important note: by “oldIE,” I mean Internet Explorer 8 only. The site looks crappy in IE8 at the time of the relaunch, but I’m planning to fix it post-launch.
In terms of supporting IE versions prior to 8, I’ll just paraphrase Shakespeare:
“By my head, you don’t support IE7 and IE6!!!”
“By my heel, I care not!!!”
Past all this, some Mobile First things are done right:
- no third-party affiliate ads load in the site’s mobile view. Google ads have to load in this view due to their rules and restrictions, but they do so asynchronously…and responsively. More on that shortly.
the site utilizes four vendor fonts but only two are available to the mobile view, resulting in two less server requests.
CSS3 gradients, box shadows and text shadows render heavy browser paints that can impend site load time…they appear on the site’s tablet and desktop views but are removed from the its mobile view.
Blogs are usually simple in design…I stuck with that rule when redesigning kaidez.com. I’m fine with the site’s overall look & feel but think the header could be better, especially since the two modules at the bottom look (I think) really nice. I may revisit the header sometime in the future.
The blue color is just something I came up with, color scheme-wise. I used this color palette over at Colour Lovers as an overall guide.
The site uses Google’s Open Sans and Open Sans Bold fonts (mostly for page content) as well as Robot Condensed (mostly for headers). Some font icons also appear on the page courtesy of Font Awesome.
I employed the aforementioned (and awesome) PrismJS for code snippet highlighting. It has a great build tool which generates the plugin code needed to implement syntax highlighting wherever you want to on your site.
I created a 404 page with a little humor, but added content to it in the hopes of further engaging whomever lands on it.
By ignoring oldIE, I was able to apply some CSS3 animations and transitions to the site…although not as much as I wanted to. I did try to do some things that were more “grand” but ran into cross-browser issues on the modern browsers. So for now, these animations and transitions are limited to some of the link rollovers on the desktop view only.
I did spend a few hours trying to apply a flat design to the site, but it’s tough. Like Swiss/International style before it, flat design is all about designing a whole lot more with a whole lot less…this is easier said than done.
But while its simplicity is difficult to implement, flat design ties in well with the general simplicity of most blog layouts. So I’ll probably go with a flat design next time.
Side note: flat design leads to a higher-performing site…oh, yes it does, for Paul Irish tells us so.
- to run PrismJS.
- to power the site’s search functionality via the Tipue plugin for jQuery.
- to execute the mobile menu’s show/hide functionality.
- to create both affiliate ads and the search box off-DOM, then load them onto the page (a DEFINITE future blog post).
- to show and hide the affiliate ads based on media queries with the help of the enquire.js.
- to run client-side form validation.
- to let AJAX process form submissions.
At the time of this blog post, there are 16 particular JS files I brought into the site build. Some are core libraries, some are plugins and some contain code I wrote.
Some of the code I wrote depends on some of the libraries and plugins. In the past, this meant I would have make sure all these files were listed in
<script> tags on my page, and in a specific order to ensure that none of their functionality would break.
Of course, I would concatenate and minify these 16 files into one, but would still need to ensure that the files were concatenated/minified in the proper order so, again, nothing broke. You have to worry about this stuff when doing JS development.
RequireJS does all of the worrying for me. I made sure it was properly configured on my page, wrote single code modules, and made sure the modules referenced any libraries and/or plugins it depended on. RequireJS did the rest, including minifying and concatenating things in the proper order.
I also suggest that you read this GitHub Gist where David Desandro from Twitter asked a question that sparked an excellent discussion about the benefits of RequireJS as well as AMD, which RequireJS is heavily based upon.
RequireJS doesn’t interact with all the site’s JavaScipt. It ignores proxy JS bought in by ads and Disqus but there are other things it ignores.
Modernizr is one such thing. While your RequireJS file should be placed as to close to the bottom as possible, it’s best practice to place Modernizr above the closing
<head> tag. The Google Fonts load in using the JS-based Google/Typekit Web Font Loader and should be placed at the top of the page before Modernizr.
- RequireJS also runs its code asynchronously.
the Web Font Loader code actually loads synchronously, but can load asynchronously. But, as its documentation states, lots of FOUTS will be generated if the Loader comes into your page asynchronously.
This other asynchronous code consists of:
- Google Analytics: watches/analyzes traffic.
Google Webmaster Tools: tracks crawl errors, validates XML sitemaps, etc.
Google Adsense: for loading ads.
Social sharing functionality on the post pages: props to Nicholas Gallagher here.
I also have to give props to the Google Dev Team: all their code mentioned here has been in need of a cleanup for the few years leading up to this writing. They certainly cleaned it up.
Especially the ad code…not only is it async, but it’s also RESPONSIVE!
Google ads don’t scale when the window is resized. Its related code just uses media queries to detect the window width on page-load, then loads in a Google ad based on this detection. Your ads sizes can only be the ones that Google has already designated.
All is not perfect with the Google stuff: the Adsense code still loads in a lot of unoptimized assets, causing a bit of a performance hit. But many of these assets load in async (as do the Disqus ones).
Bower is a browser-based package manager that runs on top of Node. When it’s properly configured and you type
bower list on the command line from your project folder, Bower checks to see if any of these packages needs to be updated (as well as Bower itself). If any packages need updating, typing
bower update <whatever-the-package> into the CLI takes care of the update.
Bower does not track EVERY library on kaidez.com: it downloads packages from remote repos, primarily those hosted on GitHub. Some packages like Tipue aren’t on remote repos…no worries.
SEO & Accessibility
The two best SEO practices you can implement on your site are 1) create compelling new content, and 2) regularly cultivate your existing content to make it more compelling. Compelling content is primarily (but not singularly) defined by the main search engines as content with a significant amount of external backlinks.
If your content strategy doesn’t implement these two tasks, you don’t have a content strategy. And I’ve definitely gotten slight traffic bumps when I publish even a trivial post so there’s definitely something to creating new content.
So moving forward, I’ll try to be more consistent with publishing stuff with the goal of making it as standout as possible to garner more external backlinks. This will require lengthy keyword research, running Google all-in-title searches and crafting enticing meta descriptions. I’ll also be updating my existing GitHub tutorial post as it’s in desperate need of cultivating.
Still, I did the following SEO technical stuff behind the scenes:
- implemented Schema.org data.
- made sure each page had a canonical link.
- generated an XML sitemap for the search engines.
- made sure at least one section had pagination…view this here.
- embedded Open Graph protocols.
- signed up for Twitter Cards.
Making a site accessible to people with disabilities is also a good SEO practice…and something you should just do anyway. So I did the following:
- started marking up the links with a
titleattribute for easy tab-throughs (this will be “in progress” for a quite while).
- ran some pages through a screen-reader.
- turned off all styles and read the unstyled page content out loud (which is basically what a screen-reader does).
- made sure that any elements that needed to be hidden were done so properly as per Yahoo’s accessibility suggestions. There are a few spots that I didn’t do this, but it’s mostly done site-wide.
If you don’t think making your site accessible to people with disabilities is worth your time, you’re dead wrong. Accessibility is important…especially on mobile. Austin Seraphin eloquently explains why.
If you still need convincing after reading that, refer to what Jen Kramer says:
“Websites that are built to be accessible will also be accessible your number one blind user: Google.”
All this being said, spending some time on the Yahoo! Accessibility blog is time well spent.
I’m sticking with my basic Media Temple Grid Server package but deciding on a web host was really something I struggled with up to the last minute.
I wanted a hosting package that would run my site as well as let me install things like Node and Ruby. My Grid Server package doesn’t really let me install anything extra so I could either upgrade to Media Temple DV Managed or sign up a with cloud-based host…either Rackspace or Amazon Web Services in this case.
Going with either DV Managed, Rackspace or AWS meant installing a LAMP stack on my own, which I’d never done up to that point. So I wanted SOME tech support in case I needed help and Rackspace seemed to pride itself on NOT providing any. So they were out.
Media Temple has EXCELLENT customer service but DV Managed was bit more expensive then a general AWS package. So I passed on upgrading my MT account and planned on hooking up with AWS at some point.
AWS also doesn’t provide tech support but I got a better vibe from them, customer service-wise. Plus, their popularity is steadily increasing to the point that there’s tons of documentation for their various services online. So much so that I figured out how to install a LAMP stack on a (somewhat) free AWS Usage Tier.
Through its S3 service, AWS is well-suited for static sites….many people host static sites on S3 and serve their static content off of MaxCDN. Kyle Rush from the 2012 Obama campaign runs this setup and has a great write-up about it.
Heroku is insanely awesome. It’s a cloud application platform that’s “AWS-like” but focuses on creating single-page applications whereas AWS can create SPAs but is focused on creating a whole lot more.
Heroku will let me do a limited amount of Node/Ruby stuff for free….limited but powerful. I’m still researching how much of it is free but if it’s enough, there’s no reason to upgrade my current hosting package.
I’m sticking with my generic, PHP-included Media Temple plan for now and will do some fancy coding stuff on Heroku. But while I took all of the above tech stuff into consideration, I have to say that MT’s excellent customer service was a big reason I stayed with them.
Media Temple recently began offering a DV Developer Package that offers a bare virtual machine. It may be too bare but it still may suit my specific future needs…still researching this as of this post.
Grunt & My Deployment Workflow
All these various processes means various tasks need to run at various times. And instead of manually performing the tasks one-by-one when needed, I’ve automated all of them under Grunt.
And as I’ve told anyone that would listen for the past two months, Grunt is my new God.
A boatload of Grunt plugins have been created by both the community and the Grunt core committers. These plugins let me create tasks within my dev environment, giving it a high level of functionality.
For example: there’s a grunt-watch plugin that lets me watch for file additions and changes, performing specific tasks when these additions/changes occur. If Bower updates jQuery core, Grunt automatically copies it over to a spot in my project folder. If a .png file is added to a certain folder, Grunt automatically fires up optiping to minify it.
grunt watch stuff is awesome but it’s my
grunt ppush task where things really rock out. It’s the task that triggers the production deployment sequence and works as follows:
- The grunt-shell plugin runs a task that executes a bash command that creates a “_deploy” directory in my project folder.
The grunt-targethtml plugin runs a task that embeds both Google Analytics code and a production-ready copy of the site’s main CSS file to the previously mentioned page layouts.
The grunt-jekyll plugin runs a task that uses Jekyll to build the site based on the layouts and dumps the build into “_deploy”.
The grunt-cdn plugin runs a task that appends the MaxCDN URL to the proper images, CSS and JS files in “_deploy”.
The grunt-contrib-htmlmin plugin runs a task that minifies the HTML in “_deploy”.
The grunt-manifest plugin runs a task that builds the cache manifest and dumps it into “_deploy”.
The grunt-sftp-deploy plugin runs a task that deploys the minified, optimized site build in “_deploy” up to my live site.
The grunt-targethtml plugin runs another task that not only removes the Google Analytics code and minified CSS from the templates, but also adds an unminified dev version of the CSS file to the templates. All this has to be done so the templates can safely build a dev version of the site.
The grunt-jekyll plugin runs another task that builds a dev copy of the site. This is really just done as test to see if the previous task properly rebuilt the templates for the dev site and may be removed eventually.
The grunt-shell plugin runs another task that executes a bash command that deletes “_deploy” from my project folder.
I’m being bombastic when outlining my deployment sequence like this but am doing so to prove a point. The combination all the above-mentioned Grunt tasks allowed me to craft a powerful, lightweight, highly-customizable IDE that not only lets me work efficiently but made the entire development process FUN!
If you’ve ever read The Pragmatic Programmer, you’re familiar with the term “good enough software”. It means, “the code may not be perfect, but it gets the job done.” And I do feel that way about some parts of the site.
Except for the overall neatness of the CSS, I’m fine with the production code. It’s optimized for mobile, renders no console errors (although some 3rd-party code does), loads fast, looks and acts great across different browsers/devices (except oldIE-based stuff), utilizes SEO best practices and executes most post-load events at the current recommended target rate of 60 frames per second.
But I’m obviously critical about the CSS and somewhat critical of how some things are working at the development level. The “good enough software” principle actually encourages such criticism so here are some things that I want to improve upon at a (not too) later date:
- Modify Grunt some more: Grunt tasks can be configured to some very finite degrees and I know that I can do more in this area. The image minification task is acting odd…need to figure that out. Also, some tasks are repetitive, particularly with the Bower stuff. Grunt has a programmatic API that (I think) can help make things DRY but I need to delve into it some more.
Clean up the CSS & Sass: Again, I KNOW that the CSS/Sass in its current format could be cleaned up and optimized. And I do want to make it work in IE8. My hope is to do all this using OOCSS principles.
Make the mobile menu/searchbox run off of CSS transitions instead of jQuery: when the site’s width is set to 568px or less in a media query-enabled browser, both the menu and searchbox will only appear and disappear by clicking on some buttons at the top.This show/hide animation is powered by jQuery but powering it off of CSS3 animations is the more optimal approach (read more about this here). Doing this means restructuring the header and I was too close to being done with the redesign to do all that. So this may be done later and if so, it will also be an opportunity to redo the header from a styling standpoint.
Using Backbone in the contact form: I’m really itching to use Backbone in a project and started to do so with my contact form, but this would add rendering/event weight to the form’s performance and be too much. I still want to use Backbone though so I may do this in the future.
A better deployment method: if your Jekyll site content is more than just a home page and blog posts AND is hosted anyplace other than GitHub, you may have to redeploy the ENTIRE site every time you make a change…even a small one. There are ways to use Git commit hooks to deploy your site after it’s pushed up to GitHub, but it’s tough to do with Jekyll. Still researching this.
Utilizing all these dev tools & techniques was just as rewarding as redesigning the site. I received a WHOLE lot of education by doing all this and am the better developer for it.
Thanks for reading this very VERY long post and feel free to ask me questions!!!