<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Thoughts by rafeca</title>
 <link href="http://feeds.feedburner.com/rafeca" rel="self"/>
 <link href="http://rafeca.com"/>
 <updated>2015-06-13T15:48:15+00:00</updated>
 <id>http://rafeca.com</id>
 <author>
   <name>Rafael Oleza</name>
   <email>rafeca@gmail.com</email>
 </author>

 
 <entry>
   <title>Creating responsive emails</title>
   <link href="http://rafeca.com/2012/11/04/creating-responsive-emails"/>
   <updated>2012-11-04T00:00:00+00:00</updated>
   <id>http://rafeca.com/2012/11/04/creating-responsive-emails</id>
   <content type="html">&lt;p&gt;There is a lot of buzz right now about responsive web design, lots of designers, developers, UX experts and marketing
people are talking about it and several &lt;a href=&quot;http://starbucks.com&quot;&gt;major companies&lt;/a&gt; have already migrated their web sites
from two specific versions for mobile and desktop to a single responsive design.&lt;/p&gt;

&lt;p&gt;Something really surprising is that emails have been ignored when talking about responsive design,
and everybody seems to assume (wrongly) that responsive design only affects to web pages.&lt;/p&gt;

&lt;p&gt;In fact, emails have been hated by web developers and designers for years... nowadays, nobody likes to go back
to the 90&amp;#39;s and create table-based layouts with inline CSS and not being able to use most of the CSS properties
(even basic stuff like the &lt;code&gt;float&lt;/code&gt; property is not safe to use on emails)...&lt;/p&gt;

&lt;p&gt;But this is not an excuse to ignore the email: lots of companies rely more on their email campaigns than
on their website so they can&amp;#39;t just ignore their increasing mobile users.&lt;/p&gt;

&lt;h1&gt;Why responsive?&lt;/h1&gt;

&lt;p&gt;First of all, because there is no alternative: in opposition to web sites, on email if you want to target
your mobile users the only way to do it is by using a responsive design (well, you could ask them what kind
of email they want to receive, but this isn&amp;#39;t useful on most cases when users check their emails from several devices).&lt;/p&gt;

&lt;p&gt;Secondly, because we can. Thanks to the smartphones and the email clients they feature (which are
almost the same as their web browsers), we are able to add tons of CSS3 magic to our emails (and this includes media
queries!).&lt;/p&gt;

&lt;h1&gt;Design principles&lt;/h1&gt;

&lt;p&gt;It&amp;#39;s important to notice that we have to keep supporting old email clients and webmail clients... So I&amp;#39;m sorry, but we
won&amp;#39;t be able to get rid of the table layout... this means that the email structure will be almost the same as
regular emails.&lt;/p&gt;

&lt;p&gt;My main advice on email designs is to keep them simple: for example try not to emulate background images by creating
huge tables with tons of cells with images inside.&lt;/p&gt;

&lt;p&gt;Instead of this, a simple layout should do the work. If you want to add any elaborated element or effect, just use CSS/CSS3
providing a fallback for old Email clients (as you would do in regular web development). This technique is useful for border
radius and background images.&lt;/p&gt;

&lt;p&gt;Also, another tip for making your life easier is to use single column layouts: it will be much easier to make them
responsive.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/responsive-emails/simple-design.png&quot; alt=&quot;Example of a simple email design&quot;&gt;&lt;/p&gt;

&lt;p&gt;The previous example corresponds to one the &lt;a href=&quot;http://giffgaff.com&quot;&gt;giffgaff&lt;/a&gt; campaign emails designed by
&lt;a href=&quot;http://twitter.com/bipolarArtist&quot;&gt;@bipolarArtist&lt;/a&gt;. The design is really simple and clean, which makes it easy to implement
as a responsive design.&lt;/p&gt;

&lt;p&gt;Even though, it has two subtle effects that have been implemented using CSS rules not recommended for emails:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;table&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;box&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;580&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;cellpadding=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;cellspacing=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;border=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;border-radius: 7px;&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;boxcell&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;580&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;background-image: url(black-triangle.png);&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Rules like &lt;code&gt;border-radius&lt;/code&gt; and &lt;code&gt;background-image&lt;/code&gt; won&amp;#39;t be supported by all the email clients, but this is not a big deal as
long as the email still looks well on those clients:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/responsive-emails/simple-design-old-clients.png&quot; alt=&quot;How the simple design looks on old clients&quot;&gt;
&lt;center&gt;&lt;em&gt;The same mail displayed on &amp;quot;old&amp;quot; email clients&lt;/em&gt;&lt;/center&gt;&lt;/p&gt;

&lt;h1&gt;Making it responsive&lt;/h1&gt;

&lt;p&gt;When an email is opened from a mobile device (like an iOS or Android device), the email client rescales the email viewpoint to make it fit horizontally on its screen. This makes the text,
images and all the details almost unreadable. And even though most clients keep a minimum font size for texts when zooming out, this size is not big enough to
be confortable to be read:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/responsive-emails/simple-design-mobile.png&quot; alt=&quot;Example of a simple email design viewed from a mobile&quot; class=&quot;noshadow&quot;/&gt;&lt;/p&gt;

&lt;h2&gt;Adjusting the email container width&lt;/h2&gt;

&lt;p&gt;The first thing to do to make it look better is to change the main container width to fit the mobile screen size, so
this way the mail client won&amp;#39;t need to rescale it. To do so, we can use CSS media queries (notice that smartphone
email clients, as opposite to webmail clients, are able to read CSS properties not defined inline):&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;only&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;screen&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;480px&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;/** your mobile styles go here **/&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, inside the media query, we should redefine every table width to match the mobile horizontal size. If desktop emails
use 600px as a standard width, 320px is a good size to choose for the mobile version.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;only&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;screen&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;480px&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;box&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;td&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;box&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;300px&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;(Note that attribute selectors are being used to &lt;a href=&quot;http://www.campaignmonitor.com/blog/post/3457/media-query-issues-in-yahoo-mail-mobile-email/&quot;&gt;prevent Yahoo! Mail from displaying the mobile version&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;All the tables in the email should be modified in the media query (to make them smaller), so this is why I recommend
keeping the layouts simple and use as less tables as possible.&lt;/p&gt;

&lt;h2&gt;Adjusting other stuff&lt;/h2&gt;

&lt;p&gt;Just changing the table widths won&amp;#39;t be enough in most situations: if the email contains big images they&amp;#39;ll prevent the
tables to become thinner... so we&amp;#39;ll have to reduce the image sizes as well.&lt;/p&gt;

&lt;p&gt;The most efficient way to do so is by setting a &lt;code&gt;max-width&lt;/code&gt; for all the images:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;only&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;screen&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;480px&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;container&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100%&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Also, we can change font sizes, margins, and even hide elements... whatever is needed to make the email look good on smaller screens.&lt;/p&gt;

&lt;p&gt;With a few adjustments we&amp;#39;ll get an email with nice big fonts which is easy to read in mobile devices:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/responsive-emails/responsive-design-mobile.png&quot; alt=&quot;Example of a responsive email design&quot; class=&quot;noshadow&quot;/&gt;&lt;/p&gt;

&lt;h2&gt;Using mobile specific images&lt;/h2&gt;

&lt;p&gt;As you may have noticed in the previous screenshot, reducing image dimensions to fit them in the screen may lead to too small images
that don&amp;#39;t look well.&lt;/p&gt;

&lt;p&gt;To fix this, we can replace the big images by their mobile optimized versions. This can be done inside the media query, but we must create a
rule for each image.&lt;/p&gt;

&lt;p&gt;First of all, we should put the image element inside a parent element that can be uniquely identified on the CSS:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;info-goodybags&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;gfx/info-goodybags.png&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we should hide the image tag and apply a background image to the container element inside the media query:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;only&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;screen&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;480px&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;info-goodybags&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;none&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;info-goodybags&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;transparent&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;url(gfx/info-goodybags-mobile.png)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;no-repeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;210px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;139px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With this, we can use a smaller image for mobile that won&amp;#39;t be scaled down on mobile devices and therefore it will look much better:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/responsive-emails/responsive-design-mobile-final.png&quot; alt=&quot;Example of a responsive email design with optimized images&quot; class=&quot;noshadow&quot;/&gt;&lt;/p&gt;

&lt;p&gt;Main problem here is that there is no automatic way to replace all the images by its mobile version without having to do it one by one (and setting
in the CSS the image width and height), so this becomes a time consuming job in emails with lots of images.&lt;/p&gt;

&lt;h2&gt;Using high resolution images&lt;/h2&gt;

&lt;p&gt;Emails can also contain images optimized for high pixel density screens (like the retina displays). Again, it&amp;#39;s easy to replace a single
image by its high-resolution alternative, but it becomes a crafting job to do this for lots of images.&lt;/p&gt;

&lt;p&gt;Using media queries we can target mobile devices with high-resolution displays and make them render the optimized images:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;only&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;screen&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;480px&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;info-goodybags&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;none&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;c&quot;&gt;/* Image for mobile */&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;info-goodybags&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;transparent&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;url(gfx/info-goodybags-mobile.png)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;no-repeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;210px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;139px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;c&quot;&gt;/* HiDpi image for mobile */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;min-device-pixel-ratio&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;transparent&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;gfx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;info-goodybags-mobile&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@2x&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.png&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;no-repeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;background-size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;210px&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;139px&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; We can also provide high resolution images for the desktop version of the image, but this would mean creating yet
another CSS rule and another version of each image and another and in this case it wouldn&amp;#39;t be available to most email clients
(remember that webmail clients like Gmail doesn&amp;#39;t support CSS selectors).&lt;/p&gt;

&lt;h2&gt;Working with multiple columns&lt;/h2&gt;

&lt;p&gt;As I said at the beginning of the post, I don&amp;#39;t recommend having multiple columns in responsive emails: it adds even more complexity to
the layouts and in most cases single-column emails are simpler and cleaner.&lt;/p&gt;

&lt;p&gt;Even though, in some situations it&amp;#39;s nice to have several columns in the desktop version, which may be displayed as a single column
in the mobile version:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/responsive-emails/multi-column.png&quot; alt=&quot;Footer of the email with multiple links&quot;&gt;
&lt;center&gt;&lt;em&gt;The footers of emails usually have multiple columns to accommodate all the links&lt;/em&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;To do so, we should have an html like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;table&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;linkstable&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;540&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;cellpadding=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;cellspacing=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;border=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;linkscell&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;table&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;180&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;cellpadding=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;cellspacing=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;border=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- content of first column --&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;linkscell&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- (...) --&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- second column --&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see a nested table inside each column is needed, which makes HTML more verbose and complicated.&lt;/p&gt;

&lt;p&gt;Now, to display these columns as a single column in the mobile version, we have to redefine the style again using media queries:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;only&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;screen&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;480px&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;linkstable&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;260px&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;nt&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;linkstable&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.linkscell&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;nt&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;linkstable&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.linkscell&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;260px&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;margin-top&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;15px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The important rule here is the &lt;code&gt;display: block&lt;/code&gt;. It will make the table cells behave like regular block elements and then they
will be moved one at the bottom of the other:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/responsive-emails/multi-column-mobile.png&quot; alt=&quot;Multi-column as a single column in mobile&quot; class=&quot;noshadow&quot;/&gt;&lt;/p&gt;

&lt;h1&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;If your company uses email as an important marketing resource and you are not sending responsive emails yet, you are loosing money. There
is no technical or business reason to not switch to responsive emails. So if you have the needed resources, redesign your emails and create
a responsive version and your conversion rates on mobile will be improved immediately.&lt;/p&gt;

&lt;h1&gt;Update&lt;/h1&gt;

&lt;p&gt;I have opensourced this whole responsive email as a template, to serve as inspiration to future readers. You can find the code 
&lt;a href=&quot;https://github.com/rafeca/email-templates&quot;&gt;in GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Automate your release flow</title>
   <link href="http://rafeca.com/2012/01/17/automate-your-release-flow"/>
   <updated>2012-01-17T00:00:00+00:00</updated>
   <id>http://rafeca.com/2012/01/17/automate-your-release-flow</id>
   <content type="html">&lt;p&gt;When working on an opensource project or library, it&amp;#39;s really important to
&lt;a href=&quot;http://en.wikipedia.org/wiki/Release_early,_release_often&quot;&gt;release often&lt;/a&gt; new versions and to
document them properly.&lt;/p&gt;

&lt;p&gt;In this post I&amp;#39;m not going to talk about the benefits of frequent releases in software
development, I&amp;#39;m just going to help you to mitigate the main problem associated to frequents releases:
The release overhead which is the time you spend on preparing each release. This overhead is not
that big at first, but when releasing really often it becomes a boring repetitive time-consuming task
that could eventually make you release less often.&lt;/p&gt;

&lt;p&gt;The most efficient way to reduce this overhead is by automating most parts of the release process, with
the help of the tools you use on your daily development process.&lt;/p&gt;

&lt;p&gt;First of all, let&amp;#39;s detect the most common steps involved in a release:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Implement the release features.&lt;/li&gt;
&lt;li&gt;Increase the version of the library.&lt;/li&gt;
&lt;li&gt;Update the changelog with all the relevant changes since last version.&lt;/li&gt;
&lt;li&gt;If you&amp;#39;ve accepted pull requests or contributions, give some credit to the new contributors.&lt;/li&gt;
&lt;li&gt;Update the library website of the library with all the new info above.&lt;/li&gt;
&lt;li&gt;Push all the changes to the GitHub repository and create a tag for the new version.&lt;/li&gt;
&lt;li&gt;Publish the new version to the correspondent library repository.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once all those steps are done, then you can start working on the next release and repeate all the steps
again.&lt;/p&gt;

&lt;h1&gt;1. Implement the release features&lt;/h1&gt;

&lt;p&gt;Although this step does not really belong to the release process, this is the most important thing to do
in a release: if you don&amp;#39;t add anything new or fix something in your library, there is no point doing a
new release, it&amp;#39;s important to plan which kind of release you&amp;#39;re planning to do (major, minor, bug fix)
and what changes are you going to include.&lt;/p&gt;

&lt;p&gt;Before starting the development of your next version, you should update your library&amp;#39;s README file to
reflect the new usage options that the new version will have (if any). This will guide you through
the development process like some kind of specification and you&amp;#39;ll get the benefits of the
&lt;a href=&quot;http://tom.preston-werner.com/2010/08/23/readme-driven-development.html&quot;&gt;Readme Driven Development&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You should try to keep the documentation really simple: In most cases just a &lt;code&gt;README.md&lt;/code&gt; file with some
simple usage examples &lt;a href=&quot;http://jesusabdullah.github.com/2011/11/09/readmes.html&quot;&gt;are enough&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you need more in-deep examples, you can create them in the &lt;code&gt;examples/&lt;/code&gt; folder. If you document the
using inline comments with the &lt;a href=&quot;http://jashkenas.github.com/docco/&quot;&gt;Dooco&lt;/a&gt; syntax, you&amp;#39;ll be able to
transform them to beautiful HTML files with all the comments displayed alongside the code.&lt;/p&gt;

&lt;p&gt;Also, I recommend you to create a new branch for the release, commiting all your changes there, and once
done then merge them to the master branch.&lt;/p&gt;

&lt;h1&gt;2. Increase the version of the library&lt;/h1&gt;

&lt;p&gt;Once all the changes are implemented and tested (all your tests pass &amp;dash; you&amp;#39;re doing TDD, don&amp;#39;t
you?) and the README is updated, it starts the release process.&lt;/p&gt;

&lt;p&gt;First thing to do is to increase the library version. In some place in your library you must define
the current version. If you&amp;#39;re planning to publish your library to a package manager you should
insert the current version in some specific place (for example in the &lt;code&gt;gemspec&lt;/code&gt; file for
&lt;a href=&quot;http://rubygems.org/&quot;&gt;RubyGems&lt;/a&gt; or in the &lt;code&gt;package.json&lt;/code&gt; file for &lt;a href=&quot;http://npmjs.org/&quot;&gt;npm&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;It&amp;#39;s recommended to define the package version in just a single place, if you need the library
version somewhere else you should get it from this single place where it&amp;#39;s defined.&lt;/p&gt;

&lt;p&gt;For example in Node.js packages, if you want to make the version available to the outside, it&amp;#39;s
good to do the following:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readFileSync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__dirname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/../package.json&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;utf8&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This way you only have to change the library version in a single place, so it will be easier to create
an script that parses this single file and updates the version.&lt;/p&gt;

&lt;h1&gt;3. Update the changelog&lt;/h1&gt;

&lt;p&gt;Keeping an updated changelog manually is a tedious task, so there are a lot of developers who don&amp;#39;t
do it at all. Even though, you should create it and mantain it updated: it will become really helpful
for the developers using your library.&lt;/p&gt;

&lt;p&gt;The standard in most GitHub projects is to use a file called &lt;code&gt;History.md&lt;/code&gt; located in the root
of the project. The file should be written in Markdown format and should contain the full library
changelog.&lt;/p&gt;

&lt;p&gt;You can format this file using your preferred layout, it&amp;#39;s important to specify the version dates and
to format it clearly. This is the layout I use:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;### 0.1.3 — *November 17, 2011*

  * Fixed the GitHub publishing of tags in the jake task
  * Updated package.json to make it compatible with Node.js 0.6.x
  * Updated travis YAML file to use the new Node.js support on Travis

### 0.1.2 — *November 14, 2011*

  * Updated Jakefile with tasks to automate publishing new versions
  (...)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The best way to automate the generation of this file is by getting all git commit messages since
last version. If you commit your changes using
&lt;a href=&quot;http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html&quot;&gt;well formed commit messages&lt;/a&gt;,
then each commit summary can be used as a single bullet point in the changelog.&lt;/p&gt;

&lt;p&gt;How can this be achieved? It&amp;#39;s very easy: with git and the following single line command you can get
all the changes since last created tag.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git log &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;git describe --tags --abbrev&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;..HEAD --pretty&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;format:&lt;span class=&quot;s2&quot;&gt;&amp;quot;  * %s&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This command prints all the changes between some initial revision and the HEAD, formatted as a plain
text bulleted list.&lt;/p&gt;

&lt;p&gt;The initial revision is calculated using the command &lt;code&gt;git describe --tags --abbrev=0&lt;/code&gt;, which outputs
the most recent tag that is in the same branch as the current HEAD.&lt;/p&gt;

&lt;h1&gt;4. List all the contributors&lt;/h1&gt;

&lt;p&gt;It&amp;#39;s important to give credit to the people who contributes to your library: this way you may
encourage more people to join to your project and help you.&lt;/p&gt;

&lt;p&gt;An standard way to do it is by creating an &lt;code&gt;AUTHORS&lt;/code&gt; file in the root of the project with the
following format:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;John Doe &amp;lt;john_doe@foo.com&amp;gt;
Chuck Norris &amp;lt;chuck@norris.com&amp;gt;
Bruce Wayne &amp;lt;dark_knight@gotham.com&amp;gt;
(...)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To get all the contributors, git is there again to help you: you can get all the commiter names and
their email address by calling the following command:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git log --all --format&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;%aN &amp;lt;%aE&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sort -u&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So you just have to replace all the contents in the &lt;code&gt;AUTHORS&lt;/code&gt; file by the output of the command above.&lt;/p&gt;

&lt;h1&gt;5. Update the library website&lt;/h1&gt;

&lt;p&gt;It&amp;#39;s nice to have a public website for your library: It gives you more visibility on the Internet and
it can display your package documentation in a more personalized way. GitHub allows packages to have
a public web site with static pages, so you don&amp;#39;t need to pay for a host and you can update your package
site directly with &lt;code&gt;git&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Creating the main page based on README file&lt;/h2&gt;

&lt;p&gt;I recommend you to reuse the main &lt;code&gt;README.md&lt;/code&gt; file of your library for the public site: if your readme
is &lt;a href=&quot;http://jesusabdullah.github.com/2011/11/09/readmes.html&quot;&gt;good enough&lt;/a&gt; it will be more than enough,
and this way you won&amp;#39;t have to update two different things each time you modify your library
(remember you dont&amp;#39; want to repeat yourself!).&lt;/p&gt;

&lt;p&gt;For doing so, you must use a markdown parser that outputs mardown code to HTML. You can use
&lt;a href=&quot;http://daringfireball.net/projects/markdown/&quot;&gt;the official one&lt;/a&gt;, or use &lt;a href=&quot;https://github.com/benmills/robotskirt&quot;&gt;any&lt;/a&gt;
&lt;a href=&quot;https://github.com/nex3/maruku&quot;&gt;markdown&lt;/a&gt; &lt;a href=&quot;https://github.com/tanoku/redcarpet&quot;&gt;library&lt;/a&gt; written
in your library language.&lt;/p&gt;

&lt;p&gt;An easy way to generate a full HTML file from a Markdown is by using two partial HTML files (a header
and a footer) and then insert the markdown output within them.&lt;/p&gt;

&lt;p&gt;The header partial file would look like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My awesome library - a library full of awesomeness&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;media=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;all&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;stylesheets/main.css&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;javascripts/sh_main.min.js&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;javascripts/sh_javascript.min.js&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;forkme&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;http://github.com/rafeca/awesome&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Fork me on GitHub&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;gfx/forkme&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Fork me on GitHub&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;container&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And the footer file like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sh_highlightDocument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Between the header and the footer files you can add as much information as you want, for example
the changelog, the contributors and even the license:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;markdown README.md &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; markdown History.md &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; markdown AUTHORS &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; markdown LICENSE&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; cat docs/_header.html - docs/_footer.html &amp;gt; docs/index.html&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This command will insert the output of the four markdown files between the &lt;code&gt;_header.html&lt;/code&gt; and
&lt;code&gt;_footer.html&lt;/code&gt; files and then save the resulting file as &lt;code&gt;index.html&lt;/code&gt; in the &lt;code&gt;docs/&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;If you prefer to have multiple pages in your site instead of one large page, you can still do
it by calling the previous command multiple times with different contents:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;markdown README.md&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; cat docs/_header.html - docs/_footer.html &amp;gt; docs/index.html
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;markdown AUTHORS&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; cat docs/_header.html - docs/_footer.html &amp;gt; docs/authors.html
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;markdown LICENSE&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; cat docs/_header.html - docs/_footer.html &amp;gt; docs/license.html&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Creating the example pages&lt;/h2&gt;

&lt;p&gt;As I said before, Docco library parses regular code files and transforms them to HTML files with
all the comments displayed alongside the code.&lt;/p&gt;

&lt;p&gt;Executing the Docco command is trivial:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docco examples/*&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will create an HTML file in the &lt;code&gt;doc/&lt;/code&gt; folder for each file in the &lt;code&gt;examples/&lt;/code&gt; folder. It
will also create a &lt;code&gt;docco.css&lt;/code&gt; which will make the HTML example files look beautiful.&lt;/p&gt;

&lt;h2&gt;Creating/updating the gh-pages branch&lt;/h2&gt;

&lt;p&gt;Now you have the full public site inside the &lt;code&gt;docs/&lt;/code&gt; folder, which will look more or less like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tree docs/
docs
├── example1.html
├── example2.html
├── docco.css
├── index.html
├── images
│   └── logo.png
├── javascripts
│   ├── sh_main.min.js
│   └── sh_javascript.min.js
└── stylesheets
    └── main.css&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;What we want to do now is to move all those files to the &lt;code&gt;gh-pages&lt;/code&gt; branch to allow GitHub to create
our &lt;a href=&quot;http://pages.github.com/&quot;&gt;repository Page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To do so, most developers create the &lt;code&gt;gh-pages&lt;/code&gt; as a new root branch and then copy manually all the
files in the &lt;code&gt;docs/&lt;/code&gt; folder to the &lt;code&gt;gh-pages&lt;/code&gt; branch and then commit the changes. This approach is
totally valid (actually, GitHub Pages instructions recommend to do it this way). Even though, if you
use this method you&amp;#39;ll end up having the &lt;code&gt;gh-pages&lt;/code&gt; branch completely independent from the &lt;code&gt;master&lt;/code&gt;
branch (so both branches won&amp;#39;t have any relashionship and then it&amp;#39;ll be hard to know which revision
of the library the web site is from).&lt;/p&gt;

&lt;p&gt;Check this screenshot of the network graph of a regular library (the
&lt;a href=&quot;https://github.com/visionmedia/mocha&quot;&gt;Mocha test framework&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/agile-release-flow/linear-network.png&quot; alt=&quot;Regular way to export &quot;&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the &lt;code&gt;gh-pages&lt;/code&gt; branch goes independently of the &lt;code&gt;master&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;So, a better way to copy the &lt;code&gt;docs/&lt;/code&gt; folder to the &lt;code&gt;gh-pages&lt;/code&gt; branch is by creating the &lt;code&gt;gh-pages&lt;/code&gt;
branch as a regular git branch, remove everything from the branch but the &lt;code&gt;docs/&lt;/code&gt; folder and
move the &lt;code&gt;docs/&lt;/code&gt; folder to the root of the branch. The final step is commit everything in the &lt;code&gt;gh-pages&lt;/code&gt;
branch.&lt;/p&gt;

&lt;p&gt;To do all this we only need the following 4 commands:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git checkout -b gh-pages
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ls &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; grep -v docs &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; xargs rm -rf
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git mv docs/* .
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git commit -a -m &lt;span class=&quot;s2&quot;&gt;&amp;quot;Initial commit in pages branch&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This has to be done only once: once the branch is created, everytime you want to update the &lt;code&gt;gh-pages&lt;/code&gt; branch
you only have to merge the changes from the &lt;code&gt;master&lt;/code&gt; branch:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git checkout gh-pages
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git merge -s subtree master&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It&amp;#39;s important to specify the Subtree merging strategy when performing the merge, this way git will
detect that all the changes in the &lt;code&gt;docs/&lt;/code&gt; subfolder have to go to the root folder and you won&amp;#39;t get
any conflict when merging.&lt;/p&gt;

&lt;p&gt;With this last way of copying the site to the &lt;code&gt;gh-pages&lt;/code&gt; branch, we get the following history tree, which shows
clearly the relation between the public site and the library code:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/agile-release-flow/merged-network.png&quot; alt=&quot;Merged way to export &quot;&gt;&lt;/p&gt;

&lt;h1&gt;6. Push all the changes to GitHub and create the tag&lt;/h1&gt;

&lt;p&gt;Now that everything is ready, you only have to create the git tag and push everything to GitHub:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git tag 1.0.0
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git push origin master gh-pages 1.0.0&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1&gt;7. Publish the new version to the correspondent library repository&lt;/h1&gt;

&lt;p&gt;This last step depends on the package manager where you want to upload your library.
Most package managers provide really good tools that simplify a lot the upload process... for example,
if you use RubyGems you&amp;#39;ll only have to do:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gem build myawesomelibrary.gemspec
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gem push myawesomelibrary-1.0.0.gem&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or in Node.js if you are using &lt;code&gt;npm&lt;/code&gt; it&amp;#39;s even simpler:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm publish&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1&gt;One more thing...&lt;/h1&gt;

&lt;p&gt;If you are developing Node.js packages, you can check out my
&lt;a href=&quot;http://rafeca.com/node-releasetools&quot;&gt;Release Tools&lt;/a&gt; package, which implements all those automatisms (some of
them are even improved) and exposes everything in a very simple API. For instance, the whole previous release
process can be automated using the following task:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;releaseTools&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;releasetools&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;Step&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;releaseTools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;updateVersionInPackageJson&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;minor&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;releaseTools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;updateChangelog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;releaseTools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;updateAuthorsFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;releaseTools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createExamples&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;releaseTools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;commitToGit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;releaseTools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createSite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;releaseTools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;updatePagesBranch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;releaseTools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pushToGit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;releaseTools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;npmPublish&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>html5 web notifications</title>
   <link href="http://rafeca.com/2011/11/15/html5-notifications"/>
   <updated>2011-11-15T00:00:00+00:00</updated>
   <id>http://rafeca.com/2011/11/15/html5-notifications</id>
   <content type="html">&lt;p&gt;One of the HTML5 features I&amp;#39;ve played with recently is the &lt;a href=&quot;http://www.w3.org/TR/notifications/&quot;&gt;Web notifications API&lt;/a&gt;,
which adds desktop-class notifications to the browser.&lt;/p&gt;

&lt;h1&gt;Compatibility&lt;/h1&gt;

&lt;p&gt;The web notifications spec is still an early draft so it&amp;#39;s subject to change, and the only browser implementing it is
Google Chrome (all the other browsers are not planning to support it in short-term), so Web notifications are only
suitable for use in few very specific scenarios... use them with care!&lt;/p&gt;

&lt;h1&gt;Who&amp;#39;s already using Web notifications&lt;/h1&gt;

&lt;p&gt;As the spec and the first implementation of Web notifications were written by Google, they were the first to use
them in a real world product: in fact Gmail
&lt;a href=&quot;http://gmailblog.blogspot.com/2011/01/desktop-notifications-for-emails-and.html&quot;&gt;has been using them&lt;/a&gt; for several months.&lt;/p&gt;

&lt;h1&gt;How to use them&lt;/h1&gt;

&lt;p&gt;To use the Notifications API, first of all you have to let the user grant permissions to your page to show notifications.&lt;/p&gt;

&lt;p&gt;To do so, the first to do is to check if she has already granted the permissions by calling the &lt;code&gt;checkPermission()&lt;/code&gt;
method. This method returns 0 in case the user has already granted permissions and 1 if not:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// function to check if the user has already granted notification permissions&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hasNotificationsPermissions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Check if the browser supports notifications&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;webkitNotifications&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;webkitNotifications&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;checkPermission&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And then use the previous function to create the method &lt;code&gt;askForPermissions()&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// function to ask for notification permissions if the user hasn&amp;#39;t done it already&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;askForPermissions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;askForPermissions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;webkitNotifications&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hasNotificationsPermissions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;webkitNotifications&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;requestPermission&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Also, it&amp;#39;s very important to point out that the &lt;code&gt;requestPermission()&lt;/code&gt; method only works when it&amp;#39;s been triggered by a
user-generated event, like a &lt;code&gt;click&lt;/code&gt; or &lt;code&gt;keypress&lt;/code&gt; event (to prevent unsolicited requests). So we have to create a
button in our app to ask for notification permissions:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;notification-permissions&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Ask for notification permissions&lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;#notification-permissions&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;askForPermissions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the user clicks on the button, she will get a popup which asks her to grant the website permissions:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/html5-notifications/request-permissions-popup.png&quot; alt=&quot;Grant permissions popup&quot;&gt;&lt;/p&gt;

&lt;p&gt;Once she clicks on &amp;quot;Allow&amp;quot;, we&amp;#39;ll be able to start sending notifications. As the notifications are
displayed indefinitely (once created they never disappear), I use a simple wrapper function to send
notifications with a timeout:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Sends a notification that expires after a timeout. If timeout = 0 it does not expire&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sendNotification&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sendNotification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showOnFocus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Default values for optional params&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;timeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;timeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;timeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;showOnFocus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showOnFocus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showOnFocus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Check if the browser window is focused&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;isWindowFocused&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;:focus&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Check if we should send the notification based on the showOnFocus parameter&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;shouldNotify&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isWindowFocused&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;isWindowFocused&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showOnFocus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;webkitNotifications&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;shouldNotify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Create the notification object&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;notification&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;webkitNotifications&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createNotification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Display the notification&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;notification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;timeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// Hide the notification after the timeout&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;notification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cancel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, this wrapper function has also a last argument called &lt;code&gt;showOnFocus&lt;/code&gt;, which allows restricting
notifications only when the browser window is not the active window in the desktop. When no &lt;code&gt;timeout&lt;/code&gt; or &lt;code&gt;showOnFocus&lt;/code&gt;
parameters are specified, it behaves just identically as the original browser method.&lt;/p&gt;

&lt;p&gt;Finally, this is how web notifications look on OSX (using Google Chrome, of course):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/html5-notifications/notification.png&quot; alt=&quot;Example of a web notification&quot;&gt;&lt;/p&gt;

&lt;h1&gt;Scope of usage&lt;/h1&gt;

&lt;p&gt;As I said before, Web notifications are only available on Google Chrome, so the usage scope is really reduced; I would
only recommend using it if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are Google.&lt;/li&gt;
&lt;li&gt;You are doing some proof of concept of HTML5 features.&lt;/li&gt;
&lt;li&gt;You provide a good fallback mechanism for notifications on the other browsers (for basically the 80% of
&lt;a href=&quot;http://en.wikipedia.org/wiki/Usage_share_of_web_browsers&quot;&gt;your visitors&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;You are developing an application for the &lt;a href=&quot;https://chrome.google.com/webstore&quot;&gt;Chrome Web Store&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In fact, I&amp;#39;ve been testing the Web Notifications in this last scenario, which is a perfect scenario for Web Notifications
as all the visitors will use Google Chrome for sure. Also, having desktop-class notifications in an application
is really useful, no matter if the app is being executed on a browser.&lt;/p&gt;

&lt;h1&gt;Improvements needed in the Notifications API&lt;/h1&gt;

&lt;p&gt;Although all of this sounds good, there are some flaws in the current specification of Web Notifications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is no way to only send notifications if the browser window is focused, this is a must as most times you only
want to send notifications when the user has the browser window on the background and can&amp;#39;t see the messages rendered
on the browser window.&lt;/li&gt;
&lt;li&gt;There is no way to show notifications that expire, why the heck do I want to show a notification that stays in the user&amp;#39;s
desktop forever? There should be a timeout param in the Notifications API.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, the current implementation on Google Chrome would improve a lot if instead of using its own notification display
system, it were integrated with external notification systems like &lt;a href=&quot;http://growl.info/&quot;&gt;Growl&lt;/a&gt; or
&lt;a href=&quot;http://developer.gnome.org/libnotify/&quot;&gt;libnotify&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Creating this blog</title>
   <link href="http://rafeca.com/2011/11/09/creating-this-blog"/>
   <updated>2011-11-09T00:00:00+00:00</updated>
   <id>http://rafeca.com/2011/11/09/creating-this-blog</id>
   <content type="html">&lt;p&gt;Ok... creating a blog and start talking about how you have created it looks a little bit useless...
but at least this is much more useful than a Hello World post, so in this first post I&amp;#39;m going to
explain a little bit how I set up everything.&lt;/p&gt;

&lt;h1&gt;Choosing Jekyll as a blog system&lt;/h1&gt;

&lt;p&gt;Instead of using a more classic blog system like Wordpress or Drupal, I decided to try
&lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;, which is a static site generator written in Ruby. It does not
require any DB and it doesn&amp;#39;t have any dynamic generated page: it just parses a set of plain text
files that contain the posts and templates and generates static HTML files that can be
served with any Web Server.&lt;/p&gt;

&lt;p&gt;There is a lot of info on the net about Jekyll, you can find out more about it in
&lt;a href=&quot;https://github.com/mojombo/jekyll/wiki/Usage&quot;&gt;its official wiki&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Jekyll has a lot of advantages (and some disadvantages, also), those are the ones that made
me choose it:&lt;/p&gt;

&lt;h2&gt;Posts are Markdown files&lt;/h2&gt;

&lt;p&gt;As I said above, Jekyll gets the blog contents from regular text files. Those text files can
have HTML code, &lt;a href=&quot;http://textile.sitemonks.com/&quot;&gt;Textile&lt;/a&gt; or &lt;a href=&quot;http://daringfireball.net/projects/markdown/&quot;&gt;Markdown&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&amp;#39;ve been using Markdown lately, and I find it very simple, super-easy to learn and very readable,
so in my opinion it&amp;#39;s the best format for writing blog posts.&lt;/p&gt;

&lt;h2&gt;It&amp;#39;s customizable&lt;/h2&gt;

&lt;p&gt;As Jekyll creates the static HTML pages by just inserting the posts inside some defined templates,
so I can create line-by-line the HTML of the pages very easily.&lt;/p&gt;

&lt;p&gt;This is cool, I don&amp;#39;t have to modify some thousand-lines-html-templates with complex structures and tons
of config parameters (the same applies to those insane CSS files) anymore.&lt;/p&gt;

&lt;h2&gt;GitHub hosting&lt;/h2&gt;

&lt;p&gt;Well, it turns out that
&lt;a href=&quot;http://pages.github.com/#using_jekyll_for_complex_layouts&quot;&gt;GitHub pages support Jekyll&lt;/a&gt;, so
just by creating a GIT repository with a Jekyll blog, GitHub automatically creates all the blog
static pages and each time I push new code, the blog is regenerated... an awesome hosting for free!&lt;/p&gt;

&lt;h2&gt;GIT workflow for blogging&lt;/h2&gt;

&lt;p&gt;It&amp;#39;s awesome to have all my posts on regular text files inside a GIT repository, so every time
I push my last commits I am publishing my pending posts.&lt;/p&gt;

&lt;p&gt;I can even create branches for writing drafts, notes, or just vague ideas about possible future posts,
and once I finish writing the post I merge to master and voilà: the post is published.&lt;/p&gt;

&lt;h2&gt;No web interface&lt;/h2&gt;

&lt;p&gt;I write my posts using TextMate or VIM, and publish them using the command line via GIT, this is my
regular workflow when I develop so I&amp;#39;m very comfortable with it.&lt;/p&gt;

&lt;p&gt;I can do everything while offline and I can automate some tasks thanks to ZSH scripts or GIT commands.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Ok, now let&amp;#39;s talk about real stuff... Those are the basic steps I followed to create this blog,&lt;/p&gt;

&lt;h1&gt;Creating the templates&lt;/h1&gt;

&lt;p&gt;This was actually the easiest part, I just created the main layout in &lt;code&gt;_layouts/default.html&lt;/code&gt;
and a layout for the posts  in &lt;code&gt;_layout/post.html&lt;/code&gt;, which inherits from the main layout. Jekyll
uses the &lt;a href=&quot;http://liquidmarkup.org/&quot;&gt;Liquid template engine&lt;/a&gt;, which has the following beautiful format:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;{{ page.title }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    {{ content }}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;ul&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;posts_list&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      {% for post in site.posts %}
        {% include post.html %}
      {% endfor %}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can check both templates in my GitHub repository: &lt;a href=&quot;https://github.com/rafeca/rafeca.github.com/blob/master/_layouts/&quot;&gt;&lt;code&gt;_layouts/&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;Code highlighting&lt;/h1&gt;

&lt;p&gt;Liquid automatically parses source code and highlights it when it finds the &lt;code&gt;highlight&lt;/code&gt; tag:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;highlight&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;javascript&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;world&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;hello&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;endhighlight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But when I was creating the blog, the last version of Liquid was the 2.3.0, which had a bug on
&lt;a href=&quot;https://github.com/imathis/octopress/issues/243&quot;&gt;code highlighting&lt;/a&gt; that made it crash, so I had two options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Downgrade Liquid version to 2.2.2&lt;/li&gt;
&lt;li&gt;Use &lt;a href=&quot;https://github.com/tanoku/redcarpet&quot;&gt;RedCarpet&lt;/a&gt;, a Markdown parser created by
&lt;a href=&quot;http://twitter.com/tanoku&quot;&gt;Vicent Marti&lt;/a&gt;, a Catalan GitHub employee.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Obviously, I chose the second option ;) To change the markdown parser in Jekyll, I had to add
a new config parameter in the Jekyll &lt;code&gt;_config.yml&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;markdown&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;redcarpet&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1&gt;Adding comments&lt;/h1&gt;

&lt;p&gt;As Jekylls creates static pages for the blog, it doesn&amp;#39;t provide comments on the posts. So I found
3 different options to solve the issue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don&amp;#39;t provide comments justifying that nobody is going to comment on blog like this one.&lt;/li&gt;
&lt;li&gt;Use GitHub issues to host the comments, as it is explained
&lt;a href=&quot;http://ivanzuzak.info/2011/02/18/github-hosted-comments-for-github-hosted-blogs.html&quot;&gt;here&lt;/a&gt;.
This is a really cool hack, but I didn&amp;#39;t want to force readers to have a GitHub account and
I wanted to allow writing the comments within the blog.&lt;/li&gt;
&lt;li&gt;Use DISQUS, which is a third party commenting system that provides a Javascript widget to embed
comments to any page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end I opted for DISQUS, because it provides all the functionality that I need. Even though
I don&amp;#39;t really like its UI and I had to tweak some of its CSS classes to make it fit properly
in the design... So maybe in the future I switch to another commenting system&lt;/p&gt;

&lt;h1&gt;Other fun stuff&lt;/h1&gt;

&lt;p&gt;I wanted to have a way to list all the posts with a certain tag, and to accomplish it I needed to create a
static page for every tag, which would look like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;---
layout: default
title: Thoughts by rafeca
---
&lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Thoughts by rafeca&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Posts in category &amp;quot;git&amp;quot;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;ul&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;posts_list&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  {% for post in site.categories.git %}
    {% include post.html %}
  {% endfor %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To create all those pages I used a &lt;a href=&quot;http://rake.rubyforge.org/&quot;&gt;Rake&lt;/a&gt; task (Rake is a build library for Ruby).
I opted to use Rake because Jekyll is written in Ruby, so this way I could access natively to the Jekylls API
to get the list of tags.&lt;/p&gt;

&lt;p&gt;This is the Rake task that I&amp;#39;m using (it&amp;#39;s a slightly modified version of this &lt;a href=&quot;https://gist.github.com/790778&quot;&gt;Gist&lt;/a&gt;):&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Generate tag pages&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:tags&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Generating tag pages...&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;jekyll&amp;#39;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;configuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;site&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Site&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;categories&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;posts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTML&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;layout: default&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;title: Thoughts by rafeca&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;&amp;lt;h1&amp;gt;Thoughts by rafeca&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;&amp;lt;h2&amp;gt;Posts in category &amp;quot;#{category}&amp;quot;&amp;lt;/h2&amp;gt;&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;&amp;lt;ul class=&amp;quot;posts_list&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;  {% for post in site.categories.#{category} %}&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;    {% include post.html %}&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;  {% endfor %}&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;    HTML&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;tag/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.html&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;w+&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;tag/#{category}.html generated!&amp;#39;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Done!&amp;#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see I&amp;#39;m iterating over all the Jekyll categories and creating the HTML file for each category.
Pretty simple, huh?&lt;/p&gt;

&lt;p&gt;So, this way the only thing I have to do before committing a new post is to execute the Rake task:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rake tags
Generating tag pages...
Configuration from _config.yml
tag/blog.html generated!
tag/git.html generated!
tag/markdown.html generated!
tag/ruby.html generated!
Done!&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1&gt;Conclusions&lt;/h1&gt;

&lt;p&gt;Now I can write my posts using VIM, and publish them via the command line with GIT, this way I feel much more
comfortable while writing, and I hope this will help me write more and keep the blog updated :)&lt;/p&gt;
</content>
 </entry>
 
 
</feed>
