<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Ricardo Lopes</title>
    <description>Hacker, tech enthusiast, learner, judo black belt and occasional blogger</description>
    <link>http://ricardolopes.net</link>
    <atom:link href="http://ricardolopes.net/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>The most amazing animal in the world</title>
        <description>&lt;p&gt;&lt;em&gt;Is it the cat? The dog? The velociraptor? Or something completely different? This is the blog post format of the lightning talk “The most amazing animal in the world” I recently gave at &lt;a href=&quot;https://www.futurelearn.com&quot;&gt;FutureLearn&lt;/a&gt; and &lt;a href=&quot;http://thundercloud.community&quot;&gt;Thundercloud LND&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is an animal out there that is far more amazing than anything else we might have known before. An animal that has been found in the heights of the Himalayas, the warmth of Japanese hot springs, the high pressures of the bottom of the ocean, the freezing cold of Antarctica, among other places. An animal that you’ve probably never seen before, as it’s no longer than 1.5 mm. An animal that has been on this planet far longer than we have, and that will probably remain after we’re all long gone. That animal is the water bear, also known as tardigrade, and this post will explain why it is, by far, the most amazing animal in the world.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ricardolopes.net/assets/2015-07-23-tardigrade.jpg&quot; alt=&quot;A tardigrade&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Tardigrades have been on this planet for the last 500 million years. In comparison, humanity started 2 million years ago. Even the earliest dinosaurs (227 million years ago) are closer in time to us than to the first tardigrades. This means that the tardigrades have survived the natural disaster that pushed dinosaurs to extinction. In fact, they’ve survived all 5 mass extinctions of this planet. But how did they manage to do that?&lt;/p&gt;

&lt;h2 id=&quot;heat&quot;&gt;Heat&lt;/h2&gt;

&lt;p&gt;Tardigrades are incredibly resistant to extreme heat. How extreme is that, exactly?&lt;/p&gt;

&lt;p&gt;Most heat-tolerant organisms support up to 122 ºC. These organisms are typically simple bacteria, as more complex ones would more easily have a weak spot. Tardigrades, however, can do even better: in one experiment, they were able to support some impressive &lt;a href=&quot;http://link.springer.com/chapter/10.1007%2F978-94-007-1896-8_12&quot;&gt;151 ºC&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ricardolopes.net/assets/2015-07-23-fire.png&quot; alt=&quot;Kill it with fire! (Good luck with that)&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;cold&quot;&gt;Cold&lt;/h2&gt;

&lt;p&gt;The coldest temperature ever recorded on Earth was some freezing -89.2 ºC. So animals don’t really need to worry about anything colder than that. Except for the tardigrade, which supports temperatures as low as -272 ºC! That’s about just one degree above absolute zero, the lowest temperature that can ever exist in the universe, when molecules stop moving and even gases turn into solids.&lt;/p&gt;

&lt;p&gt;Near absolute zero, crystals start forming inside animals’ bodies. These crystals can tear apart crucial molecules like the DNA. However, tardigrades seem to be able to prevent that, thanks to their superpower:&lt;/p&gt;

&lt;h2 id=&quot;tun&quot;&gt;Tun&lt;/h2&gt;

&lt;p&gt;Tardigrades have a superpower called the tun state. They can get into a state where they get rid of all the water in their bodies and their metabolism slows down to near 0%. This is like hibernation, improved. Because they replaced the water in their bodies, they can survive near absolute zero temperatures without great risk of crystals forming inside them. They can also survive in this state for &lt;a href=&quot;http://onlinelibrary.wiley.com/doi/10.1017/S095283690200078X/abstract;jsessionid=D097CFC6DB91E86A2F94F324BC8D2B99.f04t04, http://www.annualreviews.org/doi/abs/10.1146/annurev.physiol.60.1.73&quot;&gt;many years&lt;/a&gt;, without the need to eat or drink.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ricardolopes.net/assets/2015-07-23-tun.png&quot; alt=&quot;A tardigrade in its tun state&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After getting into this protective state, tardigrades only need to get in contact with water to return to their normal state and get back to business.&lt;/p&gt;

&lt;h2 id=&quot;pressure&quot;&gt;Pressure&lt;/h2&gt;

&lt;p&gt;Pressure, apparently, is measured with megapascals (MPa). I don’t know what 1 MPa means, and probably neither do most of you, so let’s put things in perspective:&lt;/p&gt;

&lt;p&gt;Most systems stop metabolising and start failing at around 30 MPa. The deepest part of the sea, the Challenger Deep in the Mariana Trench (around 11 km deep), can get pressure up to 100 MPa. So that’s the strongest any living organism on Earth would need to support. The strongest bacteria, however, can manage up to 300 MPa before dying. And tardigrades? Those can support &lt;a href=&quot;http://www.nature.com/nature/journal/v395/n6705/full/395853a0.html&quot;&gt;up to 600 MPa&lt;/a&gt;. That’s twice as much as the strongest bacteria, and 6x more than the strongest pressure on this planet!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ricardolopes.net/assets/2015-07-23-pressure.png&quot; alt=&quot;It's there in my CV: I work well under pressure&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;radiation&quot;&gt;Radiation&lt;/h2&gt;

&lt;p&gt;At this point there seems to be little left that could surprise us. These tiny animals just seem to be consistently breaking records. So how do they fare when handling radiation?&lt;/p&gt;

&lt;p&gt;Tardigrades are able to sustain &lt;a href=&quot;http://informahealthcare.com/doi/abs/10.1080/09553000600972956&quot;&gt;1,000x more radiation than other animals&lt;/a&gt;. A thousand times more. They support up to between 5,000 and 6,200 Gy (grays, the unit for absorbed radiation), while humans, for instance, can’t take more than between 5 and 10 Gy.&lt;/p&gt;

&lt;p&gt;This incredible resistance to radiation helps explain the next and last fact, which might well be the most impressive of them all.&lt;/p&gt;

&lt;h2 id=&quot;space&quot;&gt;Space&lt;/h2&gt;

&lt;p&gt;If the previous facts weren’t enough to convince you that we’re talking about the most amazing animal in the world, how about this one: the tardigrade was the first (and only) known animal to survive in space. And by surviving in space, I mean being &lt;a href=&quot;http://www.newscientist.com/article/dn14690-water-bears-are-first-animal-to-survive-space-vacuum.html&quot;&gt;left in the vacuum for days, completely exposed to solar radiation&lt;/a&gt;. And then returning home and successfully hatching healthy offspring. Humans, in comparison, would die in seconds, either by suffocation or due to the radiation.&lt;/p&gt;

&lt;h2 id=&quot;so-lets-recap&quot;&gt;So let’s recap&lt;/h2&gt;

&lt;p&gt;Tardigrades:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;survived 5 mass extinctions (and counting)&lt;/li&gt;
  &lt;li&gt;manage up to 151 ºC&lt;/li&gt;
  &lt;li&gt;and down to ~1 ºC above absolute zero&lt;/li&gt;
  &lt;li&gt;which is 3x colder than the coldest place on Earth&lt;/li&gt;
  &lt;li&gt;have an amazing superpower: the tun state&lt;/li&gt;
  &lt;li&gt;can live years without food and water&lt;/li&gt;
  &lt;li&gt;can handle 6x more pressure than the highest pressure on Earth&lt;/li&gt;
  &lt;li&gt;sustain 1,000x more radiation than other animals&lt;/li&gt;
  &lt;li&gt;are the only known animal to survive in space&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that’s why tardigrades are definitely the most amazing animal in the &lt;del&gt;world&lt;/del&gt; universe!&lt;/p&gt;

&lt;p&gt;Cool links if you want to know more about them:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Tardigrade&quot;&gt;Wikipedia page on tardigrades&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.bbc.com/earth/story/20150313-the-toughest-animals-on-earth&quot;&gt;A recent BBC article&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;This one includes &lt;a href=&quot;http://tvblogs.nationalgeographic.com/2014/03/19/5-reasons-why-the-tardigrade-is-natures-toughest-animal/&quot;&gt;tardigrades and Neil deGrasse Tyson gifs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Thu, 23 Jul 2015 00:00:00 +0100</pubDate>
        <link>http://ricardolopes.net/blog/the-most-amazing-animal-in-the-world/</link>
        <guid isPermaLink="true">http://ricardolopes.net/blog/the-most-amazing-animal-in-the-world/</guid>
        
        <category>animals</category>
        
        <category>trivia</category>
        
        
        <category>talk</category>
        
      </item>
    
      <item>
        <title>Setting up a hacker's blog with Jekyll, part 3</title>
        <description>&lt;p&gt;This is the last part of my small series of tutorials about building your own blog with Jekyll, no autogenerated code included. You can read the previous posts, &lt;a href=&quot;/blog/setting-up-a-hackers-blog-with-jekyll/&quot;&gt;part 1&lt;/a&gt; and &lt;a href=&quot;/blog/setting-up-a-hackers-blog-with-jekyll-part-2/&quot;&gt;part 2&lt;/a&gt;. In this last tutorial we’ll be working with the same blog example code as in the previous ones. However, if you’re just looking for a particular solution to a problem you might be facing, these examples should be self-contained enough to help.&lt;/p&gt;

&lt;p&gt;Just to recap from the previous tutorials: we’re using the gem &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; to generate our blog’s static pages. We do that by running &lt;code&gt;jekyll serve&lt;/code&gt;, which also allows us to test it in our browser locally. Our blog code structure is currently looking like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&lt;/span&gt;_config.yml
_layouts
    default.html
    post.html
_includes
    disqus.html
    paginator.html
_posts
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-02-01-hello-world.md
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-03-01-my-second-post.md
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-04-01-aprils-fools-post.md
_site
index.html&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And now let’s improve it.&lt;/p&gt;

&lt;h2 id=&quot;rss-feed&quot;&gt;RSS feed&lt;/h2&gt;

&lt;p&gt;What’s a blog without an RSS feed to let readers subscribe to it? To get one, you need an XML file complying with the RSS spec, and then a link to that file from your default layout, so that it’s available for every page of your blog. Let’s start with the XML file. You can simply create a &lt;code&gt;feed.xml&lt;/code&gt; in your project root, like you have for &lt;code&gt;index.html&lt;/code&gt;. Let’s fill it with the blog’s latest posts:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span&gt;&lt;/span&gt;---
---

&lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;rss&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;version=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;2.0&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:atom=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;http://www.w3.org/2005/Atom&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;channel&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;{{ site.name | xml_escape }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;description&amp;gt;&lt;/span&gt;{{ site.description | xml_escape }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;link&amp;gt;&lt;/span&gt;{{ site.url }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/link&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;atom:link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ site.url }}/feed.xml&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;self&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;application/rss+xml&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    {% for post in site.posts limit:10 %}
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;item&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;{{ post.title | xml_escape }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;description&amp;gt;&lt;/span&gt;{{ post.content | xml_escape }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;pubDate&amp;gt;&lt;/span&gt;{{ post.date | date_to_rfc822 }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/pubDate&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;link&amp;gt;&lt;/span&gt;{{ site.url }}{{ post.url }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/link&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;guid&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;isPermaLink=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{{ site.url }}{{ post.url }}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/guid&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    {% endfor %}
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/channel&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/rss&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This code fetches relevant information from &lt;code&gt;site.name&lt;/code&gt;, &lt;code&gt;site.description&lt;/code&gt;, &lt;code&gt;site.url&lt;/code&gt; and &lt;code&gt;site.posts&lt;/code&gt;. That last one we already used in the first tutorial for building the initial index page, so should be no surprise. The other ones are values we can define in &lt;code&gt;_config.yml&lt;/code&gt;. We’ve previously set the value of &lt;code&gt;name&lt;/code&gt;. Now we can add &lt;code&gt;description&lt;/code&gt; and &lt;code&gt;url&lt;/code&gt; as well:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;name: My blog
description: This is my new blog
url: http://www.example.com

author: Ricardo Lopes
twitter: ricardoplopes

permalink: &amp;quot;/:title&amp;quot;

paginate: 2
paginate_path: &amp;quot;/:num&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, Jekyll should have generated a &lt;code&gt;_site/feed.xml&lt;/code&gt; file that includes the blog’s posts. The last thing we need to do is including the feed in the blog pages. We can do that in &lt;code&gt;_layouts/default.html&lt;/code&gt;, so that all pages include it, by placing the relevant line inside the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; element:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
---

&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ site.name }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;alternate&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;application/rss+xml&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ site.title }}&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ site.url }}/feed.xml&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;max-width: 800px; margin: 20px auto&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ site.name }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;

      {{ content }}

      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;hr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
      © {{ site.time | date: &amp;#39;%Y&amp;#39; }} {{ site.author }}.
      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;https://twitter.com/{{ site.twitter }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Follow me on Twitter&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And that’s all you need to do to set up a feed so that your readers can start subscribing to your blog.&lt;/p&gt;

&lt;p&gt;And now for something completely different: styling.&lt;/p&gt;

&lt;h2 id=&quot;styling-with-sass&quot;&gt;Styling with SASS&lt;/h2&gt;

&lt;p&gt;Given the choice between something terrible and an improvement, you’d probably go for the improvement. So our blog’s style will be in SASS instead of plain CSS. Those files will live in the new &lt;code&gt;_sass&lt;/code&gt; directory of our project (didn’t see that one coming). For every &lt;code&gt;jekyll serve&lt;/code&gt;, the SASS files will be compiled and the necessary CSS will be generated in the &lt;code&gt;_site&lt;/code&gt; directory, like the rest of the generated static pages.&lt;/p&gt;

&lt;p&gt;Let’s start this exercise with a simple refactor. Just by looking at the last code example, we can see some ugly inline CSS in an HTML file. That’s not what any serious codebase should look like. Let’s separate those styles into their own styling file (like &lt;code&gt;_sass/style.scss&lt;/code&gt;) and leave the HTML alone:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;#body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;800px&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;20px&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;auto&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;/figure&gt;

&lt;p&gt;We’re applying those rules to a DOM element with id &lt;code&gt;body&lt;/code&gt;. So now, in &lt;code&gt;_layouts/default.html&lt;/code&gt;, we can replace:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;max-width: 800px; margin: 20px auto&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;with:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;body&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Great, so now if you check the newly generated pages… you’ll see that we’ve just broken the previous style. That’s because we still need to include the generated CSS file, &lt;code&gt;css/main.css&lt;/code&gt;, in the layout. The final code should now look like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
---

&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ site.name }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&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;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/css/main.css&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;alternate&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;application/rss+xml&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ site.title }}&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ site.url }}/feed.xml&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;body&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ site.name }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;

      {{ content }}

      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;hr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
      © {{ site.time | date: &amp;#39;%Y&amp;#39; }} {{ site.author }}.
      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;https://twitter.com/{{ site.twitter }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Follow me on Twitter&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now we should get our old style back.&lt;/p&gt;

&lt;p&gt;Because SASS augments CSS in some interesting ways, we can explore new things in our new styles file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$body-width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;800&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$phone-max-width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;570&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$desktop-vertical-margins&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$phone-vertical-margins&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$main-color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;#F91111&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$text-color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;#564A4A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@mixin&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; on-phone&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$phone-max-width&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;@content&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;span class=&quot;nn&quot;&gt;#body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body-width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;text-color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;desktop-vertical-margins&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;auto&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;nt&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;on-phone&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;phone-vertical-margins&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;auto&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;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;main-color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;text-decoration&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:hover&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;lighten&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;color-main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;text-decoration&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;underline&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;/figure&gt;

&lt;p&gt;Some things this code does, if you’re not too familiar with SASS:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Nesting: if we’re styling links and want to ad additional styles to its &lt;code&gt;hover&lt;/code&gt; status, we only need to define &lt;code&gt;&amp;amp;:hover&lt;/code&gt; inside &lt;code&gt;a&lt;/code&gt;, instead of having a separate &lt;code&gt;a:hover&lt;/code&gt;. Great for avoiding scattering things all over the place;&lt;/li&gt;
  &lt;li&gt;Saving commonly used values like colours into variables that can be used in CSS properties. Great for DRY;&lt;/li&gt;
  &lt;li&gt;Using mixins to define different styles for different situations, like setting a smaller margin for smartphones. Also great for DRY.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Studying the things we can do with SASS is out of scope of this tutorial, so if you want to know more, I encourage you to explore the great tutorials that can be found online.&lt;/p&gt;

&lt;h2 id=&quot;categories&quot;&gt;Categories&lt;/h2&gt;

&lt;p&gt;Now that the blog is looking more complete, we want to be able to categorise posts. Every post starts with a front matter that configures, in YAML, the post’s metadata. So if we want to add a category to a post, we just need to define it like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
title: Hello World!
category: unrelated
---

Welcome to my new **blog**!&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And now we can change &lt;code&gt;index.html&lt;/code&gt; to include the post category:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

{% for post in paginator.posts %}
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ post.url }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {% if post.category %}&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Category: {{ post.category }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{% endif %}
  {{ post.excerpt }}
{% endfor %}

{% include paginator.html %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And we can also change &lt;code&gt;_layouts/post.html&lt;/code&gt; to do the same change:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {{ page.date | date_to_string }}
  {% if post.category %} | Category: {{ post.category }}{% endif %}
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
{{ content }}

{% include disqus.html %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Great. Now we want categories to link to their own pages, where we can see the list of all the posts with that category. Unfortunately, Jekyll doesn’t support that. Fortunately, it lets us build our own custom plugins, so we will do just that to solve our problem.&lt;/p&gt;

&lt;p&gt;Plugins in Jekyll can be Generators, Converters, Commands and Tags. You can check the &lt;a href=&quot;http://jekyllrb.com/docs/plugins/&quot;&gt;documentation&lt;/a&gt; for more details on each type of plugin. We’ll build a generator that will, unsurprisingly, generate new pages for the blog’s categories. That generator will use a new layout, similar to our existing &lt;code&gt;index.html&lt;/code&gt;, but showing only the posts for that category, and including the category name as a page title. Let’s then create a &lt;code&gt;_layouts/category_index.html&lt;/code&gt; with the following code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.category }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;

{% for post in site.posts %}
  {% if post.category == page.category %}
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ post.url }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    {{ post.excerpt }}
  {% endif %}
{% endfor %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can now start developing the plugin. It will go into the new &lt;code&gt;_plugins&lt;/code&gt; directory. Let’s call it &lt;code&gt;_plugins/categories.rb&lt;/code&gt;. Its classes will live inside the &lt;code&gt;Jekyll&lt;/code&gt; module. The first step will be to define the category index page for the generator to use:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Jekyll&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CategoryIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Page&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&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;p&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;vi&quot;&gt;@site&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@base&lt;/span&gt; &lt;span class=&quot;o&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;source&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&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;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;categories&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Utils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slugify&lt;/span&gt;&lt;span class=&quot;p&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;vi&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;index.html&amp;#39;&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_yaml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&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;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;_layouts&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;category_index.html&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;category&amp;#39;&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;n&quot;&gt;category&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you’ve noticed the new &lt;code&gt;page.category&lt;/code&gt; in the &lt;code&gt;_layouts/category_index.html&lt;/code&gt; code, you can now see that it comes from this &lt;code&gt;CategoryIndex&lt;/code&gt;, from this line: &lt;code&gt;self.data['category'] = category&lt;/code&gt;. We can now add the generator that will create a new &lt;code&gt;CategoryIndex&lt;/code&gt; for every category of the blog and save it as a blog page:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Jekyll&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CategoryIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Page&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&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;p&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;vi&quot;&gt;@site&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@base&lt;/span&gt; &lt;span class=&quot;o&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;source&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&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;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;categories&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Utils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slugify&lt;/span&gt;&lt;span class=&quot;p&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;vi&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;index.html&amp;#39;&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_yaml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&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;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;_layouts&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;category_index.html&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;category&amp;#39;&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;n&quot;&gt;category&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CategoryGenerator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Generator&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;safe&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;generate&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;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&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;layouts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;category_index&amp;#39;&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;keys&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;o&quot;&gt;|&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;write_category_index&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;p&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;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;write_category_index&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;p&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;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CategoryIndex&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;site&lt;/span&gt;&lt;span class=&quot;p&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;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;render&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;layouts&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;site_payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&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;dest&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;pages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We now finally have category pages. So we can update &lt;code&gt;index.html&lt;/code&gt; and &lt;code&gt;_layouts/post.html&lt;/code&gt; to link to them:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

{% for post in paginator.posts %}
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ post.url }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {% if post.category %}&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Category: &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/categories/{{ post.category | slugify }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.category }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{% endif %}
  {{ post.excerpt }}
{% endfor %}

{% include paginator.html %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {{ page.date | date_to_string }}
  {% if page.category %} | Category: &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/categories/{{ page.category | slugify }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.category }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{% endif %}
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
{{ content }}

{% include disqus.html %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And now we finally have categories fully working. Please beware that if you’re using Github Pages to host your blog, it blocks most plugins (including all custom ones) from running. So if you’re using it, you should make sure that you’ve generated the &lt;code&gt;_site&lt;/code&gt; directory (that way it doesn’t matter that it doesn’t run your plugins, because the static pages have already been generated).&lt;/p&gt;

&lt;h2 id=&quot;tags&quot;&gt;Tags&lt;/h2&gt;

&lt;p&gt;One more thing: post tags. These are very similar to categories: you can just define them in the post’s front matter, but there’s no Jekyll support for individual tag pages, so we must create our own. Fortunately, because it’s so similar to categories, we can draw inspiration from the previous section.&lt;/p&gt;

&lt;p&gt;First, we’ll add a list of tags to our posts:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
title: Hello World!
category: unrelated
tags:
 - hello world
 - blog
---

Welcome to my new **blog**!&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now we can create the layout for the tag individual pages, where we’ll show a list of posts with that tag. Let’s call it &lt;code&gt;_layout/tag_index.html&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.tag }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;

{% for post in site.posts %}
  {% for tag in post.tags %}
    {% if tag == page.tag %}
      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ post.url }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
      {{ post.excerpt }}
    {% endif %}
  {% endfor %}
{% endfor %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can now adapt the code in &lt;code&gt;_plugins/categories.rb&lt;/code&gt; to generate these tag index pages and their generator, and save it in the new &lt;code&gt;_plugins/tags.rb&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Jekyll&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TagIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Page&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@site&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@base&lt;/span&gt; &lt;span class=&quot;o&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;source&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&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;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;tags&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Utils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slugify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;index.html&amp;#39;&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_yaml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&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;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;_layouts&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;tag_index.html&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;tag&amp;#39;&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;n&quot;&gt;tag&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TagGenerator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Generator&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;safe&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;generate&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;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&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;layouts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;tag_index&amp;#39;&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;tags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&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;tag&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;write_tag_index&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;write_tag_index&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TagIndex&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;site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;render&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;layouts&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;site_payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&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;dest&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;pages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And finally we add the list of post tags to &lt;code&gt;index.html&lt;/code&gt; and &lt;code&gt;_layouts/post.html&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

{% for post in paginator.posts %}
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ post.url }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {% if post.category %}&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Category: &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/categories/{{ post.category | slugify }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.category }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{% endif %}
  {{ post.excerpt }}
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Post tags:&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    {% for tag in post.tags %}
      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/tags/{{ tag | slugify }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ tag }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    {% endfor %}
  &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
{% endfor %}

{% include paginator.html %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {{ page.date | date_to_string }}
  {% if page.category %} | Category: &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/categories/{{ page.category | slugify }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.category }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{% endif %}
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
{{ content }}
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Post tags:&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {% for tag in page.tags %}
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/tags/{{ tag | slugify }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ tag }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {% endfor %}
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;

{% include disqus.html %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And we also have tags working. Last section’s warning is still relevant for this: if you’re using Github Pages to host your blog, make sure you upload the generated &lt;code&gt;_site&lt;/code&gt; directory, otherwise this plugin won’t work, because of their plugin restrictions.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;After having improved our blog in this last tutorial, we should now have a structure like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&lt;/span&gt;_config.yml
_layouts
    category_index.html
    default.html
    post.html
    tag_index.html
_includes
    disqus.html
    paginator.html
_plugins
    categories.rb
    tags.rb
_posts
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-02-01-hello-world.md
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-03-01-my-second-post.md
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-04-01-aprils-fools-post.md
_saas
    style.scss
_site
index.html
feed.html&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We now have a fully functional blog with categories, tags, proper styling, a feed to subscribe to and all the other features shown in the previous parts of this tutorial, like comments and pagination. There is, of course, a lot more that we can do. If you’ve followed through, I’d recommend you to take a look at the official documentation, where you can find more detailed information about each thing. You can also take a look at my own blog’s &lt;a href=&quot;https://github.com/rplopes/ricardolopes.net&quot;&gt;source code&lt;/a&gt;, which is open source and available on Github.&lt;/p&gt;
</description>
        <pubDate>Fri, 19 Jun 2015 00:00:00 +0100</pubDate>
        <link>http://ricardolopes.net/blog/setting-up-a-hackers-blog-with-jekyll-part-3/</link>
        <guid isPermaLink="true">http://ricardolopes.net/blog/setting-up-a-hackers-blog-with-jekyll-part-3/</guid>
        
        <category>Jekyll</category>
        
        <category>Ruby</category>
        
        <category>blogging</category>
        
        <category>RSS</category>
        
        <category>SASS</category>
        
        <category>HTML</category>
        
        
        <category>tutorial</category>
        
      </item>
    
      <item>
        <title>A layman's guide to good passwords online</title>
        <description>&lt;p&gt;We have a problem with passwords: they suck. They’re hard to memorise, easy to steal and sometimes have to fit to very specific and silly rules. Online security, nowadays, is just too complicated. So most people tend to end up ignoring security practises, making them vulnerable to cyberattacks. You know you should be doing better, but you don’t know exactly how or why, and your patience and energy are better focused somewhere else, right? If so, then this guide is for you.&lt;/p&gt;

&lt;p&gt;Let’s start debunking some myths and exploring easy and secure practises you can start implementing today. By the end of this guide, dealing with your passwords should actually be simpler and need less of your energy than before.&lt;/p&gt;

&lt;h2 id=&quot;use-long-not-cryptic-passwords&quot;&gt;Use long, not cryptic passwords&lt;/h2&gt;

&lt;p&gt;You’ve probably heard that the strongest passwords are the ones that have letters (lowercase and uppercase), numbers, special symbols like # or ! and that aren’t common words. So something like &lt;code&gt;b@2Y&amp;amp;s&lt;/code&gt; would be great. But that’s too hard to remember, so you go for something simpler, or decide to note that down somewhere.&lt;/p&gt;

&lt;p&gt;I have some good news for you: that example password I just showed you is actually terrible, and you shouldn’t torture yourself trying to memorise something like that. Why is it terrible?&lt;/p&gt;

&lt;p&gt;A typical attack tries to guess your password by trying every single possible combination of characters until it finds the right one. So it could start trying for &lt;code&gt;a&lt;/code&gt;, then &lt;code&gt;b&lt;/code&gt;, then &lt;code&gt;c&lt;/code&gt;, at some point going through &lt;code&gt;Y&lt;/code&gt;, &lt;code&gt;Z&lt;/code&gt;, &lt;code&gt;aa&lt;/code&gt;, &lt;code&gt;ab&lt;/code&gt;, and so on. For 1-character long passwords with letters and numbers, that means that such an attack tries 62 different possibilities (26 lowercase letters, 26 uppercase letters and 10 numbers, from 0 to 9). For 2-characters long passwords, the number of different possibilities rises to 3,906. And so on. For a 6-characters long password that’s around 57 billion different combinations.&lt;/p&gt;

&lt;p&gt;But &lt;code&gt;b@2Y&amp;amp;s&lt;/code&gt; includes special symbols like @ and +. Let’s say that means that there are now 38 more symbols to consider, making it a total of 100 (26 lowercase letters, 26 uppercase letters, 10 numbers and 38 special symbols). Now, the number of different possibilities to consider to break your 6-characters long password increases to 1 trillion. That’s why adding those symbols is good: it’s more combinations that attackers have to try.&lt;/p&gt;

&lt;p&gt;However, if, instead of adding those symbols, we just increase the password size from 6 to 8 characters, the number of different combinations rises to 222 trillion. So a password like &lt;code&gt;2Bananas&lt;/code&gt; is 222 times harder to break than a password like &lt;code&gt;b@2Y&amp;amp;s&lt;/code&gt;! If you add numbers and special symbols it gets even better, of course. But that doesn’t mean having to come up with impossible to remember passwords. Something like &lt;code&gt;2Bananas!!&lt;/code&gt; would need 101,010,101 trillion combinations (also because it increases in size).&lt;/p&gt;

&lt;p&gt;Why is this important? Those numbers of different combinations might all seem too big to be a problem. However, computers are getting increasingly fast. If a computer can try a billion combinations per second, for instance, then breaking &lt;code&gt;b@2Y&amp;amp;s&lt;/code&gt; takes less than 17 minutes. Breaking &lt;code&gt;2Bananas&lt;/code&gt; would take around 2.5 hours. Breaking &lt;code&gt;2Bananas!!&lt;/code&gt; would take 3,200 years.&lt;/p&gt;

&lt;p&gt;So if there’s one thing you should be remembering from this post is this: longer passwords are &lt;em&gt;way&lt;/em&gt; better than shorter passwords, even if you don’t use special characters. They’re also way easier to remember. So go ahead and change them now. The biggest example I showed was still small (just 10-characters long), so that the numbers wouldn’t be too high to understand. But in practise it’s better to use even longer passwords.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://xkcd.com/936/&quot;&gt;Here’s a great comic&lt;/a&gt; on this topic.&lt;/p&gt;

&lt;h2 id=&quot;dont-use-common-passwords&quot;&gt;Don’t use common passwords&lt;/h2&gt;

&lt;p&gt;Just because you were just freed from using cryptic passwords like &lt;code&gt;Rs*F2Q9kn%[L&lt;/code&gt;, it doesn’t mean that you can use &lt;em&gt;any&lt;/em&gt; word for a password. You’ve just learned how to protect against a brute-force attack, but there are other kinds of attacks.&lt;/p&gt;

&lt;p&gt;Attackers know that brute-force attacks can be extremely inefficient against long passwords. Wait 3,200 years to break a password? Good luck with that. So they like shortcuts. If a lot of people use &lt;code&gt;password&lt;/code&gt;, &lt;code&gt;qwerty&lt;/code&gt;, &lt;code&gt;1234567890&lt;/code&gt; or others, then there’s no need to wait for all possible combinations: they can just try those ones first. Here’s a list of the 10 most common passwords, as of 2014:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code&gt;123456&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;password&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;12345&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;12345678&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;qwerty&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;1234567890&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;1234&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;baseball&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;dragon&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;football&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A lot of accounts are currently using one of those passwords. This means that if an attacker doesn’t want to wait to get access to logged in accounts, they just need to try these. So if you use any of these passwords for any of your online accounts, change it &lt;em&gt;right now&lt;/em&gt;, because it takes any serious attacker a fraction of a second to break it, even if you’re not specifically the only target! In fact, take a look at the &lt;a href=&quot;http://www.prweb.com/releases/2015/01/prweb12456779.htm&quot;&gt;original, longer list&lt;/a&gt; and make sure it’s not in there also.&lt;/p&gt;

&lt;p&gt;Using your email address, full name, name of the website you’re visiting or anything like that isn’t also going to be a lot safer. Those are all things that an attacker will know. So it’s important that you choose uncommon or illogical words or phrases, because those will be nearly impossible to guess (once again, refer to the comic in the previous section).&lt;/p&gt;

&lt;p&gt;So, one last time, please remember: &lt;em&gt;never&lt;/em&gt; use any of those most popular passwords as a password to any kind of account you might have. Having one of those is almost as safe as having nothing at all.&lt;/p&gt;

&lt;h2 id=&quot;dont-repeat-passwords&quot;&gt;Don’t repeat passwords&lt;/h2&gt;

&lt;p&gt;You’ve probably heard this one before. You should have different passwords for every account. But it’s so hard to remember any password, how could anyone possibly remember that many? And why should you even do it, exactly?&lt;/p&gt;

&lt;p&gt;If a website you’re using doesn’t properly protect login details and gets hacked, a list with your email and password gets leaked for every attacker to use. So if you’re using the same combination in different websites, no matter how secure they might be, your account there will still be compromised. Sometimes you don’t even need to have a website get hacked: you just need someone to get physical access to your PC, or to &lt;a href=&quot;http://arstechnica.com/security/2015/04/hacked-french-network-exposed-its-own-passwords-during-tv-interview/&quot;&gt;glance at your post-it with a complicated password written down&lt;/a&gt;, among other possibilities. Getting passwords is easy. So you don’t want people entering your bank account because somebody watched you type your Facebook password.&lt;/p&gt;

&lt;p&gt;So how can anyone remember so many different passwords? I hope that if you read the previous sections, this one gets easier. We’ve discussed how cryptic, impossible to memorise passwords aren’t that good, and how memorable phrases are actually much more secure. If that still sounds too difficult to do for every single account you have online, then make sure that you do it at least for the most important ones (like your bank account, or your email account where you keep important confidential notes).&lt;/p&gt;

&lt;p&gt;Since you should now be using phrases as passwords, you might want to make some rules that let you have different passwords for different accounts without having too much to memorise. For instance, you could include the main colour of the website. So for Facebook you could use &lt;code&gt;2BlueBananas&lt;/code&gt;, and for GMail &lt;code&gt;2RedBananas&lt;/code&gt;. This isn’t perfect, and you shouldn’t be too obvious (like just adding the website name), but it’s better than nothing.&lt;/p&gt;

&lt;p&gt;A better approach to have great passwords that never repeat for different websites is to use a password manager. A password manager is an application that you can have in your devices that will generate strong passwords for your and store them securely. This way, passwords can be long and cryptic, because you don’t need to remember them, and you can have one of those per account. Comparing different password managers and explaining how to use them goes out of scope of this guide, but it might be a good topic for a future one. If you’re curious, I invite you to investigate more and start using one. It will be the best you’ll do for your security online.&lt;/p&gt;

&lt;h3 id=&quot;im-lost-summary-please&quot;&gt;I’m lost, summary please&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Use long passwords. For every character that you add, breaking your password gets incredibly more difficult. It’s ok if it’s 20, 30 characters long.&lt;/li&gt;
  &lt;li&gt;Don’t use cryptic passwords. There’s no point in trying to memorise &lt;code&gt;b@2Y&amp;amp;s&lt;/code&gt; (or noting it down somewhere insecure) if longer, more memorable passwords like &lt;code&gt;2Bananas!!&lt;/code&gt; are way more secure.&lt;/li&gt;
  &lt;li&gt;Don’t use common passwords. Those are the absolute worst. Really. Never use anything from &lt;a href=&quot;http://www.prweb.com/releases/2015/01/prweb12456779.htm&quot;&gt;this list&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Use different passwords for different accounts. At least for important accounts, like your bank.&lt;/li&gt;
  &lt;li&gt;Coming up with some rules (like adding the colour of the website) is not perfect, but better than doing nothing.&lt;/li&gt;
  &lt;li&gt;Better yet, you could start using a password manager that will pick great passwords for you and store them securely, so that you can have one per account and will never need to memorise them again.&lt;/li&gt;
  &lt;li&gt;Watch this &lt;a href=&quot;https://www.youtube.com/watch?v=yzGzB-yYKcc&quot;&gt;short interview with Edward Snowden&lt;/a&gt;, who knows a lot more about this than I do.&lt;/li&gt;
  &lt;li&gt;Share this post with your friends. Seriously, they’re probably vulnerable to cyberattacks right now, and you can help them improve their security online.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 01 May 2015 00:00:00 +0100</pubDate>
        <link>http://ricardolopes.net/blog/a-laymans-guide-to-good-passwords-online/</link>
        <guid isPermaLink="true">http://ricardolopes.net/blog/a-laymans-guide-to-good-passwords-online/</guid>
        
        <category>cybersecurity</category>
        
        
        <category>tutorial</category>
        
      </item>
    
      <item>
        <title>Setting up a hacker's blog with Jekyll, part 2</title>
        <description>&lt;p&gt;Feeling like building your new bog from scratch with tools that empower you to develop it the way you want? You’ve come to the right place. If you’re just starting, make sure you read &lt;a href=&quot;/blog/setting-up-a-hackers-blog-with-jekyll/&quot;&gt;part 1&lt;/a&gt; of this tutorial, where you can learn the advantages of using Jekyll over other options and how to use it to create a basic blog from scratch. In this second part we’ll be working with the same blog example code to extend it and make it more interesting. However, if you’re just looking for a particular solution to a problem you might have with your existing blog, these examples should be self-contained enough.&lt;/p&gt;

&lt;p&gt;Just to recap from the previous tutorial: we’re using the gem &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; to generate our blog’s static pages. We do that by running &lt;code&gt;jekyll serve&lt;/code&gt;, which also allows us to test it in our browser locally. Our blog code structure is currently looking like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&lt;/span&gt;_config.yml
_layouts
    default.html
    post.html
_posts
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-02-01-hello-world.md
_site
index.html&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now without further ado let’s get hacking.&lt;/p&gt;

&lt;h2 id=&quot;better-urls&quot;&gt;Better URLs&lt;/h2&gt;

&lt;p&gt;Jekyll defaults URLs to the format &lt;code&gt;/:year/:month/:day/:title.html&lt;/code&gt;. So our Hello World post has the URL &lt;code&gt;/2015/02/01/hello-world.html&lt;/code&gt;. However, this isn’t the best structure: it’s long and exposes a file extension and the full date. We can change this by setting a value to &lt;code&gt;permalink&lt;/code&gt; in &lt;code&gt;_config.yml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you’re ok with showing the full date on the URL (some blogs do this to give a temporal context and to make it easier to have multiple posts with the same slug), then you can set the value of &lt;code&gt;permalink&lt;/code&gt; to &lt;code&gt;pretty&lt;/code&gt;, which hides the HTML extension:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;name: My blog
author: Ricardo Lopes
twitter: ricardoplopes

permalink: pretty&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I typically prefer to remove the date from the URL, because I want my posts to be generally timeless, and because if they got an update, that URL would suddenly be misleading. You can do that setting &lt;code&gt;permalink&lt;/code&gt; to &lt;code&gt;none&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, that still exposes the HMTL file extension, which I also don’t want. Jekyll doesn’t provide a direct value for these requirements, but fortunately it lets you build your own custom URLs. So if you want URLs that simply display the post slug you need to change your &lt;code&gt;_config.yml&lt;/code&gt; to:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;name: My blog
author: Ricardo Lopes
twitter: ricardoplopes

permalink: &amp;quot;/:title&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can adapt that to your needs: prefer having the categories and the publication year included? Change it to &lt;code&gt;/:categories/:year/:title&lt;/code&gt;. And so on.&lt;/p&gt;

&lt;h2 id=&quot;paginating-our-list-of-posts&quot;&gt;Paginating our list of posts&lt;/h2&gt;

&lt;p&gt;Right now we’re displaying every single blog post in our index page, which is far from ideal. Since we have just one blog post so far we still don’t see a problem with it, but if we get to hundreds, we really shouldn’t be showing them all in one page.&lt;/p&gt;

&lt;p&gt;For the sake of experimentation, let’s create two new blog posts. Our posts directory should now look like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&lt;/span&gt;_posts
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-02-01-hello-world.md
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-03-01-my-second-post.md
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-04-01-aprils-fools-post.md&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now that we have 3 different posts, we can paginate our blog to show only 2 posts per page. Ideally you might want more posts per page, but for now this should be good enough to test what we want.&lt;/p&gt;

&lt;p&gt;Pagination is done by setting the number of posts per page in the config attribute &lt;code&gt;paginate&lt;/code&gt; and, if you want a particular URL for those pages, setting its format like the one described for permalinks in the config attribute &lt;code&gt;paginate_path&lt;/code&gt;. So to test for 2 posts per page, our &lt;code&gt;_config.yml&lt;/code&gt; would change to something like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;name: My blog
author: Ricardo Lopes
twitter: ricardoplopes

permalink: &amp;quot;/:title&amp;quot;

paginate: 2
paginate_path: &amp;quot;/:num&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;However, if you visit your blog now you’ll notice that it’s still not paginating. That’s because we’ve configured pagination, but we’re still not using it. Let’s look back at &lt;code&gt;index.html&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

{% for post in site.posts %}
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ post.url }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {{ post.excerpt }}
{% endfor %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We’re iterating over the full list of the website’s posts. We want to iterate over the posts that belong to a particular page of our pagination. To do that, we have to fetch &lt;code&gt;posts&lt;/code&gt; not from &lt;code&gt;site&lt;/code&gt;, but from &lt;code&gt;paginator&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

{% for post in paginator.posts %}
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ post.url }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {{ post.excerpt }}
{% endfor %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Great, now we should just see the latest two posts. And if we browse &lt;code&gt;/2&lt;/code&gt; we should see the second page, with the oldest post there. Still, there’s no paginator to browse different pages easily.&lt;/p&gt;

&lt;p&gt;We can add that to the end of &lt;code&gt;index.html&lt;/code&gt;, so that it shows after the list of posts. we only want to show it if there’s any need for it, i.e. only if there’s a previous page or a next page:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;...

{% if paginator.next_page or paginator.previous_page %}
  &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- paginator code here --&amp;gt;&lt;/span&gt;
{% endif %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;With this interface you can do the fanciest paginator you can think of. Here’s a suggestion for how &lt;code&gt;index.html&lt;/code&gt; might look like with one of the simplest paginators that can be done:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

{% for post in paginator.posts %}
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ post.url }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {{ post.excerpt }}
{% endfor %}

{% if paginator.next_page or paginator.previous_page %}
  {% if paginator.previous_page %}
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ paginator.previous_page_path }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Previous page&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {% else %}
    Previous page
  {% endif %}
  |
  {% if paginator.next_page %}
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ paginator.next_page_path }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Next page&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {% else %}
    Next page
  {% endif %}
{% endif %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Great, we now have pagination working with proper navigation. Our &lt;code&gt;index.html&lt;/code&gt; is starting to look crowded, though, and if we ever want to reuse the paginator code, there’s a lot there to copy and to maintain. It’s time to look at includes.&lt;/p&gt;

&lt;h2 id=&quot;includes&quot;&gt;Includes&lt;/h2&gt;

&lt;p&gt;Jekyll has this nice thing called includes, which are basically partials that you can reuse on multiple pages. So if you’ve just built your perfect paginator and you want to use it in different lists of posts, you can just put it in its own include and then just call it from those pages. Includes, unlike regular layouts, go inside their own directory: &lt;code&gt;_includes&lt;/code&gt;. If you want to isolate the paginator code into one, then you’ll need to create a &lt;code&gt;_includes/paginator.html&lt;/code&gt;. Using the same code as above, that file would be something like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;{% if paginator.next_page or paginator.previous_page %}
  {% if paginator.previous_page %}
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ paginator.previous_page_path }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Previous page&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {% else %}
    Previous page
  {% endif %}
  |
  {% if paginator.next_page %}
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ paginator.next_page_path }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Next page&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {% else %}
    Next page
  {% endif %}
{% endif %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As you can see, there’s no need to add a front matter for includes. Having this new file, we could then change our &lt;code&gt;index.html&lt;/code&gt; to be simply:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

{% for post in paginator.posts %}
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ post.url }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {{ post.excerpt }}
{% endfor %}

{% include paginator.html %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In the beginning, it might seem that using includes is an overkill that just scatters the code all over your code. However, as the code gets more complex, some parts start to repeat, or files start to get too big. Right now this paginator is only used for one page (the blog index), but is ready to be reused by other future pages, like tags or categories pages. Another good use for includes is using them to isolate external blocks, like share links or comments. Speaking of comments…&lt;/p&gt;

&lt;h2 id=&quot;comments-with-disqus&quot;&gt;Comments with Disqus&lt;/h2&gt;

&lt;p&gt;Because these blogs are nothing but a group of static pages, it’s impossible to serve comments as you would with Wordpress or something similar: when a reader wants to post a comment, there’s no database for it to go to. So the solution is to use a third-party tool to serve comments.&lt;/p&gt;

&lt;p&gt;There are plenty of solutions out there that can be used. The most popular one, which is also the one I’m using for my blog, must probably be &lt;a href=&quot;https://disqus.com/&quot;&gt;Disqus&lt;/a&gt;. It’s usually a good option because it allows users to post using their favourite social network accounts, lets the same account post on multiple blogs, instead of having to create a new one per blog, and gives blog authors a good set of tools to moderate and manage inbound comments.&lt;/p&gt;

&lt;p&gt;There are other platforms for blog comments, like Facebook’s, Google’s and more. You should really pick the one that you think makes more sense for the type of blog you’re creating. So if you’re building an awesome new hacker’s blog, there probably won’t be a big audience that prefers to use their personal Facebook accounts to engage in the discussions.&lt;/p&gt;

&lt;p&gt;Because Disqus is usually seen as a good generic option and because that’s what I experimented with when I built my blog, that’s the one I’m showing how to use. If you want to use another, you might still benefit from some of the tips below.&lt;/p&gt;

&lt;p&gt;To get started with Disqus go to &lt;a href=&quot;https://disqus.com/&quot;&gt;their website&lt;/a&gt;, register and follow their instructions. You should be given a code snippet to paste into your blog. That code snippet should be asking for important information like your username, the post’s identifier and the post’s URL. This is a great example of code that we can put in its own include. So let’s create a &lt;code&gt;_includes/disqus.html&lt;/code&gt; and drop the code there, using the right tags to fill the requested information:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;disqus_thread&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;disqus_shortname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;your_disqus_shortname&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;disqus_identifier&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;{{ page.url }}&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;disqus_url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;{{ site.url }}{{ page.url }}&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/* * * DON&amp;#39;T EDIT BELOW THIS LINE * * */&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;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dsq&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;createElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;script&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dsq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;text/javascript&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dsq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;async&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;nx&quot;&gt;dsq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&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;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;disqus_shortname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;.disqus.com/embed.js&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;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;head&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;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;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;body&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dsq&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;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Please remember that, because this is a third-party tool, it might have changed since this post was written. Make sure that you get the most up-to-date code instead of just copying this example.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that we have a new include, we just need to add it wherever we prefer. Because it’s comments, it makes sense to add it to the blog post layout. So &lt;code&gt;_layouts/post.html&lt;/code&gt; should be updated to:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.date | date_to_string }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
{{ content }}

{% include disqus.html %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That should be enough to have comments on your blog. Disqus will also give you moderator options through their website. Other providers should probably give you similar tools. If at some point you want to switch commenting providers, you can work on the new one’s code on its own include while still keeping the old one, and when you’re happy to do the switch you just need to change in the post layout the include to be used.&lt;/p&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next&lt;/h2&gt;

&lt;p&gt;After having improved our blog in this second tutorial, we should now have a structure like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&lt;/span&gt;_config.yml
_layouts
    default.html
    post.html
_includes
    disqus.html
    paginator.html
_posts
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-02-01-hello-world.md
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-03-01-my-second-post.md
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-04-01-aprils-fools-post.md
_site
index.html&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In this second tutorial we covered some more material to get to an awesome hacker’s blog. However, there’s still a lot more that we can add, and it wouldn’t fit in a single blog post. So there will be a third post where I’ll try to cover RSS, categories, tags and some theming. If you think that there’s something else worth mentioning, do shout.&lt;/p&gt;

&lt;p&gt;Don’t forget to &lt;a href=&quot;http://feeds.feedburner.com/ricardolopes/blog&quot;&gt;subscribe&lt;/a&gt; to get the latest updates as soon as they’re published. Alternatively, you can &lt;a href=&quot;https://twitter.com/ricardoplopes&quot;&gt;follow me on Twitter&lt;/a&gt;, where I plan to post the links to those updates. And, like I mentioned the last time, my blog’s source code is open, so you can learn from it and get some ideas through its &lt;a href=&quot;https://github.com/rplopes/ricardolopes.net&quot;&gt;Github project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href=&quot;/blog/setting-up-a-hackers-blog-with-jekyll-part-3/&quot;&gt;Part 3&lt;/a&gt; now available.&lt;/p&gt;
</description>
        <pubDate>Fri, 13 Mar 2015 00:00:00 +0000</pubDate>
        <link>http://ricardolopes.net/blog/setting-up-a-hackers-blog-with-jekyll-part-2/</link>
        <guid isPermaLink="true">http://ricardolopes.net/blog/setting-up-a-hackers-blog-with-jekyll-part-2/</guid>
        
        <category>Jekyll</category>
        
        <category>Ruby</category>
        
        <category>blogging</category>
        
        <category>HTML</category>
        
        
        <category>tutorial</category>
        
      </item>
    
      <item>
        <title>What if we found life on Mars?</title>
        <description>&lt;p&gt;&lt;em&gt;A week ago I gave a lightning talk at &lt;a href=&quot;http://www.futurelearn.com&quot;&gt;FutureLearn&lt;/a&gt; called “What if we found life on Mars?”. It’s a highly speculative theme, outside of my usual discussions around tech and software development, but one that I find particularly fascinating. So I thought that it would be a good idea to bring that talk’s ideas into a blog post format.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Recently we’ve been greeted with exciting news: Curiosity rover, which roams our neighbour planet Mars, has found &lt;a href=&quot;http://phys.org/news/2014-12-curiosity-rover-ancient-chemistry-mars.html&quot;&gt;active&lt;/a&gt; &lt;a href=&quot;http://news.discovery.com/space/wait-theres-more-curiosity-confirms-organics-on-mars-141216.htm&quot;&gt;organic&lt;/a&gt; &lt;a href=&quot;http://www.nasa.gov/press/2014/december/nasa-rover-finds-active-ancient-organic-chemistry-on-mars/index.html&quot;&gt;chemistry&lt;/a&gt;. This is big news because organic matter is one of the necessary conditions for life to emerge. Here’s what the team said about the discovery (emphasis mine):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;We think life began on Earth around 3.8 billion years ago, and our result shows that &lt;strong&gt;places on Mars had the same conditions at that time&lt;/strong&gt; – liquid water, a warm environment, and organic matter.&lt;/em&gt;&lt;/p&gt;

  &lt;p&gt;&lt;em&gt;&lt;strong&gt;So if life emerged on Earth in these conditions, why not on Mars as well?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;http://www.nasaspaceflight.com/2014/12/curiosity-organics-mars-opportunitys-10-year-anniversary/&quot;&gt;Curiosity confirms organics on Mars; Opportunity’s 10 year anniversary&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This exciting piece of news makes us all wonder: what if, indeed, we found evidence that there is or there was at some point life on Mars? And what does that mean for us?&lt;/p&gt;

&lt;h2 id=&quot;the-fermi-paradox&quot;&gt;The Fermi Paradox&lt;/h2&gt;

&lt;p&gt;To better understand what that would mean for us, we’ll look at the Fermi Paradox. Let’s start with some maths:&lt;/p&gt;

&lt;p&gt;There are around &lt;strong&gt;10&lt;sup&gt;22&lt;/sup&gt; to 10&lt;sup&gt;24&lt;/sup&gt; stars&lt;/strong&gt; in the observable universe. That’s 10,000 stars for every grain of sand on Earth. Our galaxy alone has between &lt;strong&gt;100 to 400 billion stars&lt;/strong&gt;. Knowing that around &lt;strong&gt;5 to 20%&lt;/strong&gt; of those stars are similar to our sun, then the lowest estimate points to &lt;strong&gt;at least 5 billion&lt;/strong&gt; sun-like stars in our galaxy. Also, we know that those stars have a probability of &lt;a href=&quot;http://www.pnas.org/content/110/48/19273.abstract&quot;&gt;around &lt;strong&gt;22%&lt;/strong&gt;&lt;/a&gt; of having en Earth-like planet orbiting it. Adding everything up, there’s &lt;strong&gt;at least 1 billion&lt;/strong&gt; Earth-like planets orbiting sun-like stars in our galaxy alone.&lt;/p&gt;

&lt;p&gt;Now we need to start getting speculative. How likely is it that a planet like that develops life? We know that Earth did, but we don’t know if this was a rare occurrence or not. So if we go for a conservative route and say there’s just a 1% probability of an Earth-like planet orbiting a sun-like star to develop life, then that means that there should be &lt;strong&gt;at least 10 million&lt;/strong&gt; different planets with life.&lt;/p&gt;

&lt;p&gt;Now, how many of those planets get life to evolve into an intelligent species? Once again, we know that life on Earth evolved to that point, but we have no way of knowing how rare we are. If we keep speculating with the same probability, then out of 1% of all those planets that developed life would emerge intelligent life. Adding all these conservative estimates up, that’s &lt;strong&gt;at least 100 thousand&lt;/strong&gt; different intelligent species across the galaxy!&lt;/p&gt;

&lt;p&gt;And that’s not all. The Earth is a young planet orbiting a young star. Our galaxy is old, and there are much older planets than ours out there. Can we imagine what would it be like for a species that evolved at the same rate as ours, but in a planet that’s just 1 billion years older? How would &lt;strong&gt;we&lt;/strong&gt; be in a billion years from now? Colonising our galaxy? That’s estimated to take around 5 million years, so if we’re talking about a 1 billion year period, then that’s something relatively quick to do for such a civilisation. Sending communications to other places in the universe? Also pretty likely. So if there are younger intelligent species, they should be already at that stage. The universe should be full of interplanetary communications from many different civilisations, and our galaxy should have been colonised by now.&lt;/p&gt;

&lt;h2 id=&quot;where-is-everybody&quot;&gt;Where is everybody?&lt;/h2&gt;

&lt;p&gt;So if the universe should be so full of life and communications, how come haven’t we seen anything yet? Our observations never registered any kind of artificial device that wasn’t launched from Earth. And although we keep listening for signals in many different wavelengths from space, we still didn’t get a single message. This doesn’t make any sense, when we think of our previous estimations. So there must be something else going on.&lt;/p&gt;

&lt;h3 id=&quot;theory-1-theyre-there-we-just-havent-heard-from-them&quot;&gt;Theory 1: They’re there, we just haven’t heard from them&lt;/h3&gt;

&lt;p&gt;One theory is that those civilisations exist, but for some reason we just never heard from them. And there are many possible explanations.&lt;/p&gt;

&lt;p&gt;Maybe some colonising species did indeed visit Earth at some point, but since our civilisation and recorded history are so young, they could have visited well before that, and so we would have no way to know about it now.&lt;/p&gt;

&lt;p&gt;Or maybe our galaxy is colonised, but we just live in some desolate rural area. Similarly, we could still be considered too primitive by more developed species, and so we could be living in some protected environment (think of something like a zoo).&lt;/p&gt;

&lt;p&gt;One scary possibility is that there might be a highly developed predator species. This would explain not only a lower number of existing intelligent civilisations than what we estimated, but also why they could be hiding their presence instead of broadcasting it. Let’s not think too much about this one, OK?&lt;/p&gt;

&lt;p&gt;Maybe our technology is just too primitive and our understanding of space too incomplete. We’re listening for radio signals, but maybe they use radio as much as we use smoke signals. Maybe there’s a lot of communication going on using different channels, like by manipulating sub-atomic particles, and we’re just too primitive to be able to listen to that.&lt;/p&gt;

&lt;p&gt;Many other possibilities exist to try to justify this. Maybe colonisation doesn’t make sense for higher civilisations after all, or maybe we’re just a product of a simulation of some other species, or maybe it’s something else no one thought of yet.&lt;/p&gt;

&lt;p&gt;However, there’s a scarier theory to explain this paradox.&lt;/p&gt;

&lt;h3 id=&quot;theory-2-there-are-no-higher-civilisations-in-existence&quot;&gt;Theory 2: There are no higher civilisations in existence&lt;/h3&gt;

&lt;p&gt;Maybe we’re really alone and there’s no one else in the entire universe. This should be highly unlikely, because of all the numbers we’ve seen before. So the best explanation for this is that we’re taking too much stuff for granted, and one of the steps between having a habitable planet and actually developing a galaxy-colonising civilisation must be nearly impossible to achieve.&lt;/p&gt;

&lt;p&gt;This hypothetical nearly impossible step is commonly referred as the Great Filter: there are probably many planets creating the simplest forms of life out there, but at some point in the evolution process there’s this filter that eliminates almost all of them. These are some of the steps that might qualify as the Great Filter:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Habitable star system&lt;/li&gt;
  &lt;li&gt;Reproductive molecules&lt;/li&gt;
  &lt;li&gt;Simple (prokaryotic) single-cell life&lt;/li&gt;
  &lt;li&gt;Complex (archaeatic and eukaryotic) single-cell life&lt;/li&gt;
  &lt;li&gt;Sexual reproduction&lt;/li&gt;
  &lt;li&gt;Multi-cell life&lt;/li&gt;
  &lt;li&gt;Tool-using animals with big brains&lt;/li&gt;
  &lt;li&gt;Intelligent life&lt;/li&gt;
  &lt;li&gt;Colonisation explosion&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this list, we’re currently on step 8, which means that we’ve successfully transitioned from all the previous steps. Unfortunately, because we don’t about any species from other planets, we don’t know how easy any of these steps are. Did we already pass the Great Filter and we’re now on our way to colonise the galaxy? Or is the Great Filter ahead of us?&lt;/p&gt;

&lt;p&gt;There are many reasons to why the Great Filter could lie ahead of us: maybe a civilisation is unable to start harvesting its galaxy’s resources before running out of its own planet’s. Or maybe the development of advanced artificial intelligence can result in extinction due to unexpected consequences. Or getting to galaxy exploration may take too much time to avoid some life-ending asteroid collision. Among many other depressing possibilities.&lt;/p&gt;

&lt;h2 id=&quot;back-to-mars-what-can-we-learn&quot;&gt;Back to Mars, what can we learn?&lt;/h2&gt;

&lt;p&gt;Looking back at the list of possible steps for the Great Filter, what would it mean for us to find life on Mars?&lt;/p&gt;

&lt;p&gt;Imagine that we find life on Mars at step 5: “sexual reproduction”. This means that that step and all the previous ones were easy steps, since 2 out of 2 studied planets (Earth and Mars) managed to get there. So the probability that the nearly impossible step lies ahead suddenly increases. In addition, still considering that example, we can assume that the next step, “multi-cell life”, would also be easy, since we’ve got records of that happening &lt;a href=&quot;http://www-eve.ucdavis.edu/grosberg/Grosberg pdf papers/2007 Grosberg &amp;amp; Strathmann.AREES.pdf&quot;&gt;46 times&lt;/a&gt; already. So the only possible difficult steps would be 7 (“tool-using animals with big brains”), 8 (“intelligent life”) or 9 (“colonisation explosion”). That would mean that the probability of having the Great Filter ahead of us would suddenly jump to 1 out of 3.&lt;/p&gt;

&lt;p&gt;So, in conclusion, if we found life on Mars, we’d probably be doomed, because that would mean that the chances of having the Great Filter ahead of us would increase dramatically. And having the Great Filter ahead of us means that our chances of reaching the next evolutionary step are as good as none.&lt;/p&gt;

&lt;p&gt;Some interesting reading material if you found this topic interesting:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wikipedia entries on the &lt;a href=&quot;http://en.wikipedia.org/wiki/Fermi_paradox#cite_ref-OSTI-19850301_3-0&quot;&gt;Fermi Paradox&lt;/a&gt; and the &lt;a href=&quot;http://en.wikipedia.org/wiki/Great_Filter&quot;&gt;Great Filter&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://waitbutwhy.com/2014/05/fermi-paradox.html&quot;&gt;The Fermi Paradox&lt;/a&gt; from What But Why&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.sentientdevelopments.com/2007/08/fermi-paradox-back-with-vengeance.html&quot;&gt;The Fermi Paradox: Back with a vengeance&lt;/a&gt; from Sentient Developments&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 28 Feb 2015 00:00:00 +0000</pubDate>
        <link>http://ricardolopes.net/blog/what-if-we-found-life-on-mars/</link>
        <guid isPermaLink="true">http://ricardolopes.net/blog/what-if-we-found-life-on-mars/</guid>
        
        <category>future</category>
        
        <category>universe</category>
        
        
        <category>talk</category>
        
      </item>
    
      <item>
        <title>Avoiding the “think outside the box” trap</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; This blog post was first published on the 25th of October of 2012. This means that most of its content might no longer be up-to-date. This was published in my previous blog, which has &lt;a href=&quot;/blog/a-postmortem-of-my-wordpress-blog/&quot;&gt;met an unfortunate end&lt;/a&gt;, and is being reposted now as an attempt to resurface some of the most popular posts that have been lost.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These days I’m getting sick and tired of all the “think outside the box” talk. In my area (technology and computers stuff) we have three kinds of young people: those who have yet to wake up for reality (mostly gamers that chose this area because it’s about those machines that can run videogames); those who want to play safe and spend their years being treated as slaves in a low-wage and unfulfilling job; and those that love to “think outside the box”. So what is that thoughtful activity anyway?&lt;/p&gt;

&lt;p&gt;“Thinking outside the box” means trying unconventional ideas and questioning the status quo to get to new conclusions and possibilities. Imagine all you take for granted in this world and all your beliefs being put in a box. That means that whenever you’re solving a problem or looking for an answer, you’re thinking inside that box of yours. You’re in your comfort zone. You’re safe. But there is a full world of possibilities outside of that box to be explored, and sometimes the answer to a problem might just be hidden outside of those boundaries. So you have to step out of your comfort zone and explore new ideas and beliefs you you want to get your answers.&lt;/p&gt;

&lt;p&gt;That is the theory. Now for reality.&lt;/p&gt;

&lt;p&gt;At least among rather young people (18 to 30?) in the technology area, that expression is very popular. People use it to try to stand out from the crowd, although much of the crowd is using it already by now. Even though they might not notice it, they’re not really using it in its original meaning anymore: for the tech guys, “thinking outside the box” is avoiding the low-wage unfulfilling job and challenging the standard, usually by trying to live an entrepreneur’s adventure or simply by chatting about the latest innovations and what cool technological projects could be made out of them. In every meetup, in every talk, in every event, there it is: the dreaded “think outside the box” telling you to create the next Google or Facebook and live the startup entrepreneur’s dream (this is actually an oversimplification, but I hope you can still see my point here).&lt;/p&gt;

&lt;p&gt;So, have you noticed something terribly wrong so far? If not, please read the description of the original meaning of that expression again. It seems that almost all the tech guys are pointing to the same direction when they talk about “thinking outside the box”. Not just to the same direction, but many times also to the very same spot! Now how’s that for challenging your beliefs, getting out of the comfort zone and exploring new ideas and possibilities? How come can you talk about shifting the way you question the world and then fall to the same exact spot as everybody else who tries to do the same?&lt;/p&gt;

&lt;p&gt;Eager to stand out from the crowd and expand their ideas, people move their thoughts out of their box, just to let them fall in another one. This “second box”, as it might be called, is just a trap state where you can easily fall if you don’t see it. But hey, nobody said it’d be easy to truly get out of that hated box! The whole purpose was to do the near-impossible and change the status quo, so it shouldn’t be too much of a surprise if there are some traps and pitfalls on the way.&lt;/p&gt;

&lt;p&gt;So how can that trap be avoided so that we can truly achieve great paradigm shifts and new discoveries? Unfortunately, there is no right answer for it, at least that I’m aware of. If I new it, I’m sure I’d be a much better and happier person by now. However, I’m sure it wouldn’t hurt to stop thinking so much about creating new startups and launching new technological products, and start trying to push creativity and imagination to come up with amazing new ideas. Not million-dollar business ideas (although those might also be welcome), but simply crazy ideas that at the end of the day will have an impact on you and on the world around you.&lt;/p&gt;

&lt;p&gt;How many tech folks would consider travelling to a country not knowing a single word of their language just to help children with family problems? How many with the right skills would work with a young NGO to develop their website without asking anything in return? And how many would spend hours every week watching recorded lectures online from the world’s best universities and doing their exercises?&lt;/p&gt;

&lt;p&gt;As every other guy will tell you, it’s still nice to look for entrepreneurship adventures, though (as I’ve also done and intend to keep doing). Just keep in mind that it’s just one pattern you can follow when you’re trying to think different and broaden your scope of the world, and that there is an endless list of other patterns, some of them better, others worse. Just don’t fall in the trap of immediately going for that “second box” if that wasn’t your initial goal.&lt;/p&gt;

&lt;p&gt;If you dodge that trap, there is a whole world of new adventures waiting for you. A scary world, way different from your usual assumptions and mostly unknown  And still, powerful enough to amaze you and to give you new insights and tools for critical thinking, problem solving and self-fulfilment.&lt;/p&gt;
</description>
        <pubDate>Sun, 22 Feb 2015 00:00:00 +0000</pubDate>
        <link>http://ricardolopes.net/blog/avoiding-the-think-outside-the-box-trap/</link>
        <guid isPermaLink="true">http://ricardolopes.net/blog/avoiding-the-think-outside-the-box-trap/</guid>
        
        <category>entrepreneurship</category>
        
        
        <category>rant</category>
        
      </item>
    
      <item>
        <title>More Semantic Web for Ruby: mastering your data</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; This blog post was first published on the 14th of October of 2013. This means that most of its content might no longer be up-to-date. This was published in my previous blog, which has &lt;a href=&quot;/blog/a-postmortem-of-my-wordpress-blog/&quot;&gt;met an unfortunate end&lt;/a&gt;, and is being reposted now as an attempt to resurface some of the most popular posts that have been lost.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In a &lt;a href=&quot;/blog/developing-for-the-semantic-web-with-ruby-on-rails-the-2012-guide/&quot;&gt;previous post&lt;/a&gt; I shared some important tips and resources for anyone who plans on developing for the Semantic Web in Ruby (like in a Ruby on Rails webapp). If you haven’t checked it yet, I strongly recommend you to do so. This new post goes a step further and shows you how to convert data from the Semantic Web to your app’s data model and also the other way around.&lt;/p&gt;

&lt;p&gt;To get our mappings between the Semantic Web data and our app’s data model we need some Ruby gems. The gem &lt;a href=&quot;https://rubygems.org/gems/rdf&quot;&gt;rdf&lt;/a&gt; lets us parse and work with RDF data in Ruby. The gem &lt;a href=&quot;https://rubygems.org/gems/linkeddata&quot;&gt;linkeddata&lt;/a&gt;  gives us additional resources for working with the semantic web and the Linked Data. Finally, I will also use the gem &lt;a href=&quot;https://rubygems.org/gems/rdf-turtle&quot;&gt;rdf-turtle&lt;/a&gt; because I find the Turtle notation to be clearer than the RDF/XML notation, so this gem helps us parse this alternative notation (if you won’t use Turtle, you’ll be just fine without this gem).&lt;/p&gt;

&lt;h2 id=&quot;importing-rdf-data-to-ruby&quot;&gt;Importing RDF data to Ruby&lt;/h2&gt;

&lt;p&gt;As we’ve seen in the previous tutorial, creating a semantic graph in Ruby for describing RDF data is as easy as doing:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Graph&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;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now we want to create a semantic graph based on the data of an existing RDF file. To do that, we need to change it to:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_of_rdf_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can now query that graph to import its data to our Ruby application. The rdf gem is powerful enough to allow querying that graph using pure Ruby code (no SPARQL needed).&lt;/p&gt;

&lt;p&gt;Let’s imagine we’re developing a blog and we’re importing RDF data about posts and their authors. We have the models &lt;code&gt;Post&lt;/code&gt; and &lt;code&gt;Author&lt;/code&gt; in our application. The RDF ontology that the data on that file is using is called &lt;code&gt;MyBlog&lt;/code&gt; and has the class &lt;code&gt;Post&lt;/code&gt; (for the authors, it reuses the class &lt;code&gt;Person&lt;/code&gt; from the well-known ontology &lt;a href=&quot;http://www.foaf-project.org&quot;&gt;FOAF&lt;/a&gt;). That ontology has also the properties &lt;code&gt;hasTitle&lt;/code&gt; (that links a &lt;code&gt;MyBlog:Post&lt;/code&gt; to a string of its title) and &lt;code&gt;hasAuthor&lt;/code&gt; (that links a &lt;code&gt;MyBlog:Post&lt;/code&gt; to a &lt;code&gt;FOAF:Person&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Here is an example of how we could query the graph to find all posts:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;MyBlog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Vocabulary&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;s2&quot;&gt;&amp;quot;http://ricardolopes.net/myblog.owl#&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Load the RDF file to a semantic graph&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path_of_rdf_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# To get all the posts, we need a SPARQL-like query, but using hashes&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;query_posts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Query&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;ss&quot;&gt;:post&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyBlog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;MyBlog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasTitle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;MyBlog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasAuthor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:author&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;# Build an array of results of that query&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query_posts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now we have an array called &lt;code&gt;results&lt;/code&gt; that holds all instances of objects with &lt;code&gt;RDF:type&lt;/code&gt; &lt;code&gt;MyBlog:Post&lt;/code&gt;. To import the relevant data, we should now iterate through these results and create a new &lt;code&gt;Post&lt;/code&gt; for each. Here is an example of how to do that and fetch each post’s title:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;results&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;result_post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Post&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;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can fetch the title of the post using &lt;code&gt;result_post.title&lt;/code&gt; because in the query that originated those results we asked to store the value of the property &lt;code&gt;MyBlog:hasTitle&lt;/code&gt; in a variable called &lt;code&gt;title&lt;/code&gt;. Remember that the value of &lt;code&gt;MyBlog:hasTitle&lt;/code&gt; is a string with the title of the post, so we can save its value directly in our Ruby class.&lt;/p&gt;

&lt;p&gt;To fetch each post’s author we need to do an extra step. Unlike &lt;code&gt;MyBlog:hasTitle&lt;/code&gt;, the &lt;code&gt;MyBlog:hasAuthor&lt;/code&gt; property doesn’t hold a string: it holds a reference to an individual of the class &lt;code&gt;FOAF:Person&lt;/code&gt;. For our application we want to store the author’s name and URI. To get the string with the name of a &lt;code&gt;FOAF:Person&lt;/code&gt; we need to query its property &lt;code&gt;FOAF:name&lt;/code&gt;. To get the string with their URI we use the reference of the individual. Here is an example of how we could modify the last piece of code to add the author’s name and URI to the post:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;results&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;result_post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Post&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;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# New query, this time to get the post&amp;#39;s author&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;query_author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Query&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;ss&quot;&gt;:author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FOAF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;FOAF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&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;# Get the authors and fetch the one from this post&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;query_author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&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;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;result_author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# If it&amp;#39;s the same reference, we found it!&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author_uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As we can see, this second query looks like it’s cluttering the code. This could be avoided if the original query (&lt;code&gt;query_posts&lt;/code&gt;) was already expecting it. So one way to greatly simplify this code would be to change &lt;code&gt;query_posts&lt;/code&gt; to the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query_posts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Query&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;ss&quot;&gt;:post&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyBlog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;MyBlog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasTitle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;MyBlog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasAuthor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;FOAF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&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;/figure&gt;

&lt;p&gt;This would fetch not only the full list of posts, but also the author (and their name) of that post, because its identifier is the same as the identifier of the value of &lt;code&gt;MyBlog:hasAuthor&lt;/code&gt; (&lt;code&gt;:author&lt;/code&gt;). However, if an author didn’t have a &lt;code&gt;FOAF:name&lt;/code&gt;, we wouldn’t get any information of that post, because that query expects results in all the variables we’re querying. In addition, if we wanted to fetch more information about the post (its creation date, its category, etc.), we should only include it in the initial query if it’s always present, because otherwise, since there’s a variable in the query with no value, the posts that don’t have that value won’t be fetched. So the solution to fetch that additional information only if it’s available is to do a second query (so even if that second query fails for posts without that value, the first query still succeeds and at least we got the essential information of the post).&lt;/p&gt;

&lt;p&gt;So unfortunately there might be situations where we do need to do further queries that make the overall code look uglier. However, there are always ways of trying to mitigate that problem as much as possible. One way is to create a separate method for these second queries, so to get the author’s name you only had to do:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;results&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;result_post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Post&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;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FOAF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# And the method would look like:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;new_query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Query&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;ss&quot;&gt;:element&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;property&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:property&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;n&quot;&gt;new_query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&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;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;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_s&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;element&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That method expects to return a string. It might need some adjustments for other tasks, like returning the URI of the element.&lt;/p&gt;

&lt;p&gt;With this information, it is now possible to fetch all the information we need from an RDF file to the Ruby application’s data model. Now we look at the exact opposite: exporting our application’s data into an RDF file.&lt;/p&gt;

&lt;h2 id=&quot;exporting-relational-data-from-ruby-to-semantic-data-in-rdf&quot;&gt;Exporting relational data from Ruby to semantic data in RDF&lt;/h2&gt;

&lt;p&gt;In the previous tutorial, in section “Putting the Semantic Web in Ruby on Rails”, we already saw how to create a semantic graph in Ruby, populate it with RDF classes and properties, and export it to a file. Now, we’re using the application’s data model to automatically export the application data.&lt;/p&gt;

&lt;p&gt;Lets use the same blog example for the export process. The first thing we need to do is get everything ready:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Graph&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;no&quot;&gt;FOAF&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FOAF&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# This vocabulary is known by the gem&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;MyBlog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Vocabulary&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;s2&quot;&gt;&amp;quot;http://ricardolopes.net/myblog.owl#&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Vocabulary&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;s2&quot;&gt;&amp;quot;http://example.com/myblogdata#&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code&gt;MyBlog&lt;/code&gt; represents the ontology we’ve been using. &lt;code&gt;data&lt;/code&gt; represents the namespace of this blog application (one of the many that would be using the &lt;code&gt;MyBlog&lt;/code&gt; ontology). We can now iterate through all the blog’s posts and save them to the semantic graph:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Post&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;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;generate_unique_uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&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;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyBlog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In the code snippet above we first fetch a unique URI for the blog post, because every object in RDF must have an identifying URI. We could implement a method to generate such URI based on some rules (an auto-incremented integer, truncating its title, etc.), or we could avoid that step if we saved its URI when we were importing the RDF data. However, if your application is intended to make it easier for users to manage semantic data, chances are not all the exported objects were previously imported.&lt;/p&gt;

&lt;p&gt;After generating the identifying URI, we use it to add the post to the semantic graph. &lt;code&gt;data[uri]&lt;/code&gt; joins the application’s namespace (defined in the snippet of code before this last one) with the generated URI (so if a post got an URI &lt;code&gt;my-first-post&lt;/code&gt;, it would result in &lt;code&gt;http://example.com/myblogdata#my-first-post&lt;/code&gt;). &lt;code&gt;RDF.type&lt;/code&gt; and &lt;code&gt;MyOnt.Post&lt;/code&gt; return the property &lt;code&gt;type&lt;/code&gt; of the ontology &lt;code&gt;RDF&lt;/code&gt; and the class &lt;code&gt;Post&lt;/code&gt; of the ontology &lt;code&gt;MyBlog&lt;/code&gt;, respectively. These three elements together are the equivalent of the following triple:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-erb&quot; data-lang=&quot;erb&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&amp;lt;http://example.com/myblogdata#my-first-post&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;http://ricardolopes.net/myblog.owl#Post&amp;gt; .&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This means that we are adding to the semantic graph a triple that states that the blog post identified by &lt;code&gt;my-first-post&lt;/code&gt; is of type &lt;code&gt;MyBlog:Post&lt;/code&gt;. We could extend the previous code to include the remaining information of the post:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Post&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;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;generate_unique_uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&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;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyBlog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&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;no&quot;&gt;MyBlog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finally, we also want to add the author information. Since the author is another RDF object, we need to create it and link it to the post:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;created_authors&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;no&quot;&gt;Post&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;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;generate_unique_uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&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;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyBlog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&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;no&quot;&gt;MyBlog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Only add new author element if it hasn&amp;#39;t been added before&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;created_authors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author_uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author_uri&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;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FOAF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author_uri&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;no&quot;&gt;FOAF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;created_authors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author_uri&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Link the post to its author&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&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;no&quot;&gt;MyBlog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasAuthor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author_uri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now we should have all the information we want in our semantic graph. The last step is to export it into an external file. This is something that we also dealt with in the previous tutorial, so now let’s try to do it using the Turtle notation, to generate files that are easier to read by humans:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PREFIXES&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;ss&quot;&gt;rdf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;http://www.w3.org/1999/02/22-rdf-syntax-ns#&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;owl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;http://www.w3.org/2002/07/owl#&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;xsd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;http://www.w3.org/2001/XMLSchema#&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;rdfs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;http://www.w3.org/2000/01/rdf-schema#&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;foaf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;http://xmlns.com/foaf/0.1/&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;myblog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;http://ricardolopes.net/myblog.owl#&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;http://example.com/myblogdata#&amp;#39;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Writer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:ttl&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;n&quot;&gt;buffer&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;writer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefixes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PREFIXES&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each_statement&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;statement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;statement&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code&gt;PREFIXES&lt;/code&gt; array is optional, but it’s a nice to have addition to make the resulting file easier to read. If you are using other ontologies, it’s better to add them to that array, as well. Then, we use an &lt;code&gt;RDF::Writer&lt;/code&gt; to write all statements of our semantic graph into a file using Turtle (&lt;code&gt;:ttl&lt;/code&gt;) notation. This is where the gem rdf-turtle comes in handy, so if you’re exporting to a different RDF notation, you probably won’t need it.&lt;/p&gt;

&lt;h2 id=&quot;to-sum-up&quot;&gt;To sum up&lt;/h2&gt;

&lt;p&gt;As with my previous tutorial, this one is also not intended to be a step-by-step manual that gives you a working demo by the end of it. Instead, this tutorial is meant to be a helper for everybody that is struggling with the integration of the Semantic Web and Ruby, and a complement to the previous tutorial. More specifically, it is intended to demonstrate how to import and export semantic data into/from a Ruby application that relies on a relational data model.&lt;/p&gt;

&lt;p&gt;As I’ve concluded in early 2012, Ruby tools for development with the Semantic Web are still not as good as tools that we can find for other languages, such as Java. Still, it’s good to see that it is in fact possible to import and export data seamlessly using pure Ruby, so if this is the main Semantic Web related feature your application is supposed to have, the good news is that it shouldn’t be too hard to develop it in Ruby on Rails, Sinatra or any other Ruby framework.&lt;/p&gt;
</description>
        <pubDate>Sun, 15 Feb 2015 00:00:00 +0000</pubDate>
        <link>http://ricardolopes.net/blog/more-semantic-web-for-ruby-mastering-your-data/</link>
        <guid isPermaLink="true">http://ricardolopes.net/blog/more-semantic-web-for-ruby-mastering-your-data/</guid>
        
        <category>Semantic Web</category>
        
        <category>Ruby</category>
        
        <category>Ruby on Rails</category>
        
        
        <category>tutorial</category>
        
      </item>
    
      <item>
        <title>Developing for the Semantic Web with Ruby on Rails, the 2012 guide</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; This blog post was first published on the 30th of January of 2012. This means that most of its content might no longer be up-to-date. This was published in my previous blog, which has &lt;a href=&quot;/blog/a-postmortem-of-my-wordpress-blog/&quot;&gt;met an unfortunate end&lt;/a&gt;, and is being reposted now as an attempt to resurface some of the most popular posts that have been lost.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Semantic Web, an Internet of of connected knowledge, meaningful data and machine-readable information, is seen as many as the future of the Internet. Envisioned by Tim Berners-Lee, its purpose is to transition from a web of unstructured documents into a “web of data”, in which we could browse and search for data not only based on syntactic  keywords, but also based on semantic meaning. However, it’s awkward to realise that most of the work around the Semantic Web is done in Java, and many technologies with great future potential, such as Ruby on Rails, are seemingly forgotten.&lt;/p&gt;

&lt;p&gt;Having developed a Semantic Web project using that Ruby framework, I found very scattered information and tiny bits of contributions, many already obsolete. It’s almost shocking to see so few and old information around such a modern framework with such a vibrant and participating community developing for it. As such, having collected many of those bits of information, I believe it’s time to put them together and finally create an updated guide to the development for the Semantic Web with Ruby on Rails.&lt;/p&gt;

&lt;p&gt;Disclaimer: This is not a step-by-step tutorial, so don’t expect to know how to develop a Semantic Web application in Ruby on Rails as soon as you finish reading this. The main goal of this article is to save hours of research and show the best and updated tools available. Also, the code examples aren’t necessarily complete or 100% correct, as their goal is to explain something, and not simply being copy+pasted to a tutorial application.&lt;/p&gt;

&lt;h2 id=&quot;building-the-ontology-and-fetching-relevant-data&quot;&gt;Building the ontology and fetching relevant data&lt;/h2&gt;

&lt;p&gt;If you’re going to develop a website using the concept of the Semantic Web, one of the first things you’ll need is an ontology. You may find many useful ontologies capable of describing the data your web application is going to use (the &lt;a href=&quot;http://swoogle.umbc.edu/&quot;&gt;Swoogle&lt;/a&gt; project might be a good place to start your search), but you might as well have to develop your own. If you’re building your own ontology, I recommend using &lt;a href=&quot;http://protege.stanford.edu/&quot;&gt;Protégé&lt;/a&gt; for it.&lt;/p&gt;

&lt;p&gt;The development of the ontology is out of the scope of this article, as it has no relation to the platform used to develop the web application itself, so if you don’t know how to start I’d recommend reading some simpler guides first (here’s a short &lt;a href=&quot;http://protege.stanford.edu/publications/ontology_development/ontology101.pdf&quot;&gt;collection&lt;/a&gt; &lt;a href=&quot;http://www.w3.org/TR/rdf-primer/&quot;&gt;of&lt;/a&gt; &lt;a href=&quot;http://www.w3.org/RDF/FAQ&quot;&gt;links&lt;/a&gt; &lt;a href=&quot;http://webcache.googleusercontent.com/search?q=cache:5-Tx99Kz6aEJ:pubs.cs.uct.ac.za/archive/00000257/01/technical_report.pdf&quot;&gt;that&lt;/a&gt; &lt;a href=&quot;http://www.slideshare.net/fadirra/semantic-web-intro-040411&quot;&gt;might&lt;/a&gt; help you with that).&lt;/p&gt;

&lt;p&gt;After you have the right ontology to power your web application, it’s time to to fetch the data. Unless you’re aiming for a very limited and controled set of elements, you’ll probably want to develop a screen scraper or use an external API. Using the Ruby gem &lt;a href=&quot;http://nokogiri.org/&quot;&gt;Nokogiri&lt;/a&gt;, you can easily browse and fetch the information you want from any useful website. Here is a simple example of a screen scraper for your application:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&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;n&quot;&gt;doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Nokogiri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTML&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;website_url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;.item&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;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;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;at_css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;.info h4 a&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;ss&quot;&gt;:href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;item_doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Nokogiri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTML&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

  &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item_doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;at_css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;h2#title a&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;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_s&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item_doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;at_css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;p.description&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;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_s&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;items&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;description&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As you see, this little example simply iterates through all the elements of the website of the class &lt;code&gt;item&lt;/code&gt;, browses to their specific page and then extracts the name and description. This technique may have its flaws, like being vulnerable to major website redesigns, but it’s also a very simple and rapid way of extracting large quantities of information.&lt;/p&gt;

&lt;p&gt;Ideally, you’ll want to save your new information in XML files or in a database, so you can use them later without having to run the fetcher again. This, of course, is just a temporary location, ready to change as soon as the Semantic Web enters the game.&lt;/p&gt;

&lt;h2 id=&quot;putting-the-semantic-web-in-ruby-on-rails&quot;&gt;Putting the Semantic Web in Ruby on Rails&lt;/h2&gt;

&lt;p&gt;It’s easy enough to develop for the Semantic Web in Java, as you can easily find a large set of tools to help you in every stage of the development. In Ruby it’s not that easy at all. After some research you’ll probably come across two Ruby gems that handle the semantic graph: &lt;a href=&quot;http://activerdf.org/&quot;&gt;ActiveRDF&lt;/a&gt; and &lt;a href=&quot;https://rubygems.org/gems/rdf&quot;&gt;RDF.rb&lt;/a&gt;. However, ActiveRDF is now outdated and it doesn’t seem to work as it should in Rails 3. So RDF.rb it is, then.&lt;/p&gt;

&lt;p&gt;Now that we have the tool to manage the semantic data, we should save our raw data in a semantic graph. We’ll use the N-Triples format for that. First you’ll need to define all the semantic relations of your data:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;MyOnt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Vocabulary&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;s2&quot;&gt;&amp;quot;http://ricardolopes.net/myont.owl#&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Graph&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;n&quot;&gt;items&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;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;uri&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;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyOnt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;uri&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;no&quot;&gt;MyOnt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This example assumes that you have an ontology with the URI &lt;code&gt;http://ricardolopes.net/myont.owl&lt;/code&gt;, which has at least a class &lt;code&gt;Item&lt;/code&gt; and a property &lt;code&gt;hasName&lt;/code&gt;. This example, as all others in this guide, is far from complete, as it is just used for quick demonstrations. One thing it doesn’t show is how to create the unique URI for each item. That is up to you to decide, as every project is different. However, when you have a unique identifier for every item, you probably should do something like &lt;code&gt;item[&quot;uri&quot;] = MyOnt[unique_identifier]&lt;/code&gt;. Beware, though, that if you use &lt;code&gt;MyOnt&lt;/code&gt; to store individuals, you’ll no longer have an empty ontology serving only as a schema. You’ll probably find it more useful to use an URI for the ontology schema and another for the individuals (&lt;code&gt;MyOnt&lt;/code&gt; and &lt;code&gt;Data&lt;/code&gt;, for instance).&lt;/p&gt;

&lt;p&gt;After that step, you’ll then need to store the information of the semantic graph you created in an N-Triples file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RDF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Writer&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;data/graph.nt&amp;quot;&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;writer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each_statement&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;stmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmt&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is it. you should now have a complete N-Triples file with all your semantic information. Now that you have the semantic data, you may start using its full potential.&lt;/p&gt;

&lt;h2 id=&quot;querying-the-graph&quot;&gt;Querying the graph&lt;/h2&gt;

&lt;p&gt;If you’re not new to the Semantic Web development you’re probably used to SPARQL when it comes to querying for information. In Ruby on Rails you’ll find it possible to do such queries using pure Ruby, thanks to the RDF.rb gem. Imagine you have the following information:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-erb&quot; data-lang=&quot;erb&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&amp;lt;http://ricardolopes.net/data/2011/01/10/ricardolopes&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;http://ricardolopes.net/myont.owl#Developer&amp;gt; .&lt;/span&gt;

&lt;span class=&quot;x&quot;&gt;&amp;lt;http://ricardolopes.net/data/2011/01/10/ricardolopes&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;http://ricardolopes.net/myont.owl#hasName&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;quot;Ricardo Lopes&amp;quot; .&lt;/span&gt;

&lt;span class=&quot;x&quot;&gt;&amp;lt;http://ricardolopes.net/data/2012/01/30/semanticwebarticle&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;http://ricardolopes.net/myont.owl#Article&amp;gt; .&lt;/span&gt;

&lt;span class=&quot;x&quot;&gt;&amp;lt;http://ricardolopes.net/data/2012/01/30/semanticwebarticle&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;http://ricardolopes.net/myont.owl#hasName&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;quot;Semantic Web article&amp;quot; .&lt;/span&gt;

&lt;span class=&quot;x&quot;&gt;&amp;lt;http://ricardolopes.net/data/2011/01/10/ricardolopes&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;http://ricardolopes.net/myont.owl#isAuthorOf&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;http://ricardolopes.net/data/2011/01/30/semanticwebarticle&amp;gt; .&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This means that we have an individual of the class &lt;code&gt;Developer&lt;/code&gt; that has the name “Ricardo Lopes”, and an individual of the class &lt;code&gt;Article&lt;/code&gt; that has the name “Semantic Web article”. We also have a relation that states that the &lt;code&gt;Developer&lt;/code&gt; “Ricardo Lopes” is the author of the &lt;code&gt;Article&lt;/code&gt; “Semantic Web article”.&lt;/p&gt;

&lt;p&gt;Imagine now that you’re showing the article “Semantic Web article” and want to show the name of its author. Using the RDF.rb gem, you could do it simply using Ruby:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;article_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Semantic Web article&amp;quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&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;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyOnt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;article_name&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;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmt1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# stmt1.subject now holds the URI of the article&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&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;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyOnt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isAuthorOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmt1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subject&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;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmt2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# stmt2.subject now holds the URI of the author&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&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;n&quot;&gt;stmt2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyOnt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&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;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmt3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# stmt3.object now holds the name of the author&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;author_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmt3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inspect&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you still prefer to use SPARQL instead of pure Ruby, there’s a gem for that: &lt;a href=&quot;https://github.com/gkellogg/sparql-grammar&quot;&gt;SPARQL-Grammar&lt;/a&gt;. Beware, though, that, as I’ve said before, the Semantic Web in Ruby has still a long road to run to catch up with languages such as Java. The work to bring SPARQL to Ruby is still very incomplete and there are many things you can’t do (sometimes I couldn’t even define prefixes, which resulted in some very ugly queries).&lt;/p&gt;

&lt;p&gt;You now have the tools you need to make full use of the semantic information of your application. With many Semantic Web applications, this is all you need to know. However, there’s more we can do. If you’re developing in Ruby on Rails, chances are you’re intending to put your web application on the cloud. And there’s also a good possibility that you may want to change some of your data in the future. That’s when a simple file is no longer an option to store your data and you must upgrade it to a Triple Store.&lt;/p&gt;

&lt;h2 id=&quot;leveling-up-to-a-triple-store&quot;&gt;Leveling up to a Triple Store&lt;/h2&gt;

&lt;p&gt;A Triple Store stands for an N-Triples file as a database stands for an XML file (sort of). So if you’ll ever need to update the semantic information of your web application, that’s what you should use.&lt;/p&gt;

&lt;p&gt;There are plenty of Triple Stores in Java for you to run locally or in your server, like &lt;a href=&quot;http://incubator.apache.org/jena/&quot;&gt;Jena&lt;/a&gt;, &lt;a href=&quot;http://www.franz.com/agraph/allegrograph/&quot;&gt;AllegroGraph&lt;/a&gt;, &lt;a href=&quot;http://www.aduna-software.com/technology/sesame&quot;&gt;Sesame&lt;/a&gt; and many more. There are interfaces that let your Ruby application interact with those Java Triple Stores, so if your server supports Java or localhost is as far as you’ll get, them one of those might be the right solution for you.&lt;/p&gt;

&lt;p&gt;However, if you’re developing the webapp in Ruby on Rails, chances are you want it online, and your infrastructure might not make it simple to support many languages and configurations. If that’s the case, then you need to develop an interface that creates an abstraction in your server’s database so it acts as a Triple Store. Such an abstraction would probably use a single 3-column table (for subject, predicate and object) and would return a set of triples for every query received. The hardest step should be converting from SPARQL or pure-Ruby RDF.rb queries into the proper SQL query.&lt;/p&gt;

&lt;p&gt;Fortunately, if you use PostgreSQL and/or SQLite, there’s an amazing work done that integrates those databases with RDF.rb data. It’s the Ruby gem &lt;a href=&quot;https://github.com/ruby-rdf/rdf-do&quot;&gt;RDF-do&lt;/a&gt;, and it may save you days of work and many frustrations.&lt;/p&gt;

&lt;h2 id=&quot;to-sum-up&quot;&gt;To sum up&lt;/h2&gt;

&lt;p&gt;Once one grasps the power of the Semantic Web, it’s not easy to ignore its advantages and future potential. However, as you can now see, the work around it in Ruby feels scattered and incomplete. Because it was so difficult to come across these scattered pieces of great work and because of what can be achieved when they are all connected, there was a great need of putting all this knowledge together. Yes, there are other similar guides online, but many are so outdated that may put you on the wrong track.&lt;/p&gt;

&lt;p&gt;As I’ve pointed out before, this wasn’t intended to be a step-by-step tutorial for you to copy+paste all the code you needed to develop a basic application. If this article is so long as it is, imagine how it would be with all that information. It’s more like an updated guide you can use to save hours of research and frustration.&lt;/p&gt;

&lt;p&gt;A follow-up tutorial is now available, describing how to import and export semantic data into/from Ruby: &lt;a href=&quot;/blog/more-semantic-web-for-ruby-mastering-your-data/&quot;&gt;More Semantic Web for Ruby: mastering your data&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Sun, 08 Feb 2015 00:00:00 +0000</pubDate>
        <link>http://ricardolopes.net/blog/developing-for-the-semantic-web-with-ruby-on-rails-the-2012-guide/</link>
        <guid isPermaLink="true">http://ricardolopes.net/blog/developing-for-the-semantic-web-with-ruby-on-rails-the-2012-guide/</guid>
        
        <category>Semantic Web</category>
        
        <category>Ruby</category>
        
        <category>Ruby on Rails</category>
        
        
        <category>tutorial</category>
        
      </item>
    
      <item>
        <title>Setting up a hacker's blog with Jekyll</title>
        <description>&lt;p&gt;If you’re looking for a blogging platform or framework to start sharing your thoughts with the rest of the world, there’s no shortage of options to consider. My previous blog was a self-hosted Wordpress install, a pretty popular option, which &lt;a href=&quot;/blog/a-postmortem-of-my-wordpress-blog/&quot;&gt;turned out to be a disaster for me&lt;/a&gt;. Other popular options include regular &lt;a href=&quot;https://wordpress.com/&quot;&gt;Wordpress&lt;/a&gt;, &lt;a href=&quot;https://medium.com/&quot;&gt;Medium&lt;/a&gt; or even &lt;a href=&quot;https://www.tumblr.com/&quot;&gt;Tumblr&lt;/a&gt;. However, if you want your blog to exercise your hacking skills, then &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; is the way to go.&lt;/p&gt;

&lt;p&gt;Jekyll is a static websites and blogs generator that is run from the command line. What this means is that instead of setting up a database of posts, comments, etc. and a webapp that connects to that database to generate dynamic webpages, it simply generates all the necessary pages upfront. This means that you don’t have to worry about databases, caching, running live server code, and so on: it’s as simple and practical as it can get.&lt;/p&gt;

&lt;p&gt;I wouldn’t recommend it to anyone with no programming background, however. You’re expected to deal with YAML files to change the website settings, HTML with Liquid tags to build the structure of every page, Ruby to develop or tweak any plugins and Markdown (or an alternative, like Textile or raw HTML) to write any post. Also, generating the website after every change (in design, structure, or simply after every new post) is done through the command line, and after that you still have to upload the generated files to your server.&lt;/p&gt;

&lt;p&gt;However, for the enthusiastic developer, this means that you have full control over the entire process. It also means that dealing with your blog feels closer than ever to hacking one of your projects. You can, in fact, never leave your favourite text editor: even for regular blog posts, I get to do everything with vim.&lt;/p&gt;

&lt;p&gt;Enough talk already. If I got your interest, let’s get hacking. This is a Ruby tutorial, so I’m assuming that you have Ruby installed and are comfortable enough using it.&lt;/p&gt;

&lt;h2 id=&quot;setting-up-jekyll&quot;&gt;Setting up Jekyll&lt;/h2&gt;

&lt;p&gt;Jekyll is a Ruby gem, so its installation is what you’d expect:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem install jekyll
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you have two options: you either ask Jekyll to build you a complete new site from its default template, or you just go ahead and build your own from scratch. For the former, you’d just need to type:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;jekyll new yourwebsitename
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After that, you’d have your brand new website in the newly created &lt;code&gt;yourwebsitename&lt;/code&gt; directory. From that directory, you’d only need to type &lt;code&gt;jekyll serve&lt;/code&gt; to generate the static files and be able to browse it.&lt;/p&gt;

&lt;p&gt;However, that doesn’t feel like hacking at all. So fire up your favourite text editor and get yourself a cup of coffee, because we’re building it the fun way.&lt;/p&gt;

&lt;h2 id=&quot;index&quot;&gt;Index&lt;/h2&gt;

&lt;p&gt;A typical Jekyll blog is structured into specific directories inside of the root project directory. So start by creating a directory for your new blog, where all the code will live.&lt;/p&gt;

&lt;p&gt;All the generated static files will go to the directory &lt;code&gt;_site&lt;/code&gt;. So if you create a new &lt;code&gt;index.html&lt;/code&gt; in your project root and run &lt;code&gt;jekyll serve&lt;/code&gt;, a &lt;code&gt;_site/index.html&lt;/code&gt; will be created. While that Jekyll server is running, you can view that generated page at &lt;code&gt;localhost:4000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For our new blog’s index, we’ll want to iterate through our list of blog posts and show their title and excerpt:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
---

{% for post in site.posts %}
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ post.url }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {{ post.excerpt }}
{% endfor %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The templating tags you can see are Liquid tags. You use &lt;code&gt;{% text %}&lt;/code&gt; for logic like iterating a list (like ERB’s &lt;code&gt;&amp;lt;% text %&amp;gt;&lt;/code&gt;, and &lt;code&gt;{{ text }}&lt;/code&gt; for text output (like ERB’s &lt;code&gt;&amp;lt;%= text %&amp;gt;&lt;/code&gt;). Another relevant remark about the code above is that you don’t need to surround the excerpt with &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; tags: its output already includes them.&lt;/p&gt;

&lt;p&gt;In this code we can see another important part of Jekyll: the front matter. It’s the block defined by the triple dashes, and it holds any configuration, in YAML, that you might need in a page. Right now we’re not needing anything, so we’ll just leave it empty. We can’t just remove it, because otherwise the Liquid tags won’t get parsed by Jekyll (it would just be treated as a regular, static HTML file).&lt;/p&gt;

&lt;p&gt;Trying to check the generated site with this code won’t show anything interesting. That’s because our blog still has no posts to display. Let’s fix that.&lt;/p&gt;

&lt;h2 id=&quot;posts&quot;&gt;Posts&lt;/h2&gt;

&lt;p&gt;The blog posts must be stored in the &lt;code&gt;_posts&lt;/code&gt; directory. Their filename should be their publication date followed by their intended URL identifier (slug). This ensures that you get your posts organised by date and you can immediatelly identify any of their files, while it also gives two important bits of information to Jekyll to use. So if you want to create your Hello World post, you would name it something like &lt;code&gt;_posts/2015-02-01-hello-world.md&lt;/code&gt; (in this tutorial I’m assuming we’re formatting our posts with Markdown). Here’s how that file would look like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
title: Hello World!
---

Welcome to my new **blog**!&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This time we have a use for the front matter: for a blog post we need to define a title. It’s not necessary to include the post publication date and slug, because Jekyll already gets them from the filename.&lt;/p&gt;

&lt;p&gt;Browsing the generated site should now start to get more interesting. You should now be able to see your new post listed in the blog index and be able to navigate to its page.&lt;/p&gt;

&lt;p&gt;However, everything still seems too simple and ugly. It’s time to give our blog a proper look.&lt;/p&gt;

&lt;h2 id=&quot;layouts&quot;&gt;Layouts&lt;/h2&gt;

&lt;p&gt;In Jekyll you theme your blog by providing a list of layouts. Those are stored in the &lt;code&gt;_layouts&lt;/code&gt; directory. Let’s start with a default layout &lt;code&gt;_layouts/default.html&lt;/code&gt; to apply to all our existing pages:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
---

&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;My blog&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;max-width: 800px; margin: 20px auto&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;My blog&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;

      {{ content }}

    &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We now have a slightly better design and the blog title in every page, linking to the blog index. The contents of every page will be replacing that &lt;code&gt;{{ content }}&lt;/code&gt;. And if you try to browse the generated site… you’ll see that nothing changed and the layout isn’t being used.&lt;/p&gt;

&lt;p&gt;To make every page use this new layout, we have to specify it in their front matters. So your index will have to change into:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

{% for post in site.posts %}
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ post.url }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  {{ post.excerpt }}
{% endfor %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And, likewise, the front matter of your post will also need to be updated:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
title: Hello World!
---

Welcome to my new **blog**!&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You should now be able to see the changes in the generated site. The design is still not great, but styling webpages is out of scope of this tutorial. Our blog post, however, still looks incomplete, without its title and publication date. We can fix that by introducing a new layout, just for blog posts. Fortunately, specific layouts can reuse more generic ones, to avoid duplicating a lot of code. Here’s how a &lt;code&gt;_layouts/post.html&lt;/code&gt; could look like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
layout: default
---

&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.title }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ page.date | date_to_string }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
{{ content }}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Notice that by setting a layout to a layout we avoid a lot of code repetition. Now if you change the layout in the post file from &lt;code&gt;default&lt;/code&gt; into &lt;code&gt;post&lt;/code&gt;, you should be able to see the post title and publication date in its page.&lt;/p&gt;

&lt;p&gt;Also, you might have noticed the new &lt;code&gt;| date_to_string&lt;/code&gt;. The &lt;code&gt;|&lt;/code&gt; is used in Liquid to apply the filter specified on the right to the element on the left. So in this example we’re applying the &lt;code&gt;date_to_string&lt;/code&gt; filter to &lt;code&gt;post.date&lt;/code&gt;, which converts the post publication date into a nicer to read string.&lt;/p&gt;

&lt;p&gt;So now we have a blog index, posts and a theme. Things are starting to look better, and you’re now in a position to start adding elements like a sidebar, Google Analytics, Disqus comments and anything else you want. So now let’s finish with some cleanup, to help with future improvements.&lt;/p&gt;

&lt;h2 id=&quot;configurations&quot;&gt;Configurations&lt;/h2&gt;

&lt;p&gt;In our defaut layout we’re hardcoding the name of our blog twice. If we want to add elements like an RSS feed, semantic annotations or others, chances are we’re going to have to hardcode it again. The same applies for other information like blog author, description and social media links.&lt;/p&gt;

&lt;p&gt;Fortunately, there is a place to store all this information: the configurations file, which acts like the ultimate front matter of the whole site. So create the &lt;code&gt;_config.yml&lt;/code&gt; file in the project root:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;name: My blog
author: Ricardo Lopes
twitter: ricardoplopes&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now we can access any of these variables through the &lt;code&gt;site&lt;/code&gt; object. We can now change the default layout to something more interesting (and maintainable):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&lt;/span&gt;---
---

&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ site.name }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;max-width: 800px; margin: 20px auto&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{{ site.name }}&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;

      {{ content }}

      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;hr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
      © {{ site.time | date: &amp;#39;%Y&amp;#39; }} {{ site.author }}.
      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;https://twitter.com/{{ site.twitter }}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Follow me on Twitter&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next&lt;/h2&gt;

&lt;p&gt;So far we’ve only really scratched the surface on what Jekyll can do for our blog. The current structure should be something like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&lt;/span&gt;_config.yml
_layouts
    default.html
    post.html
_posts
    &lt;span class=&quot;m&quot;&gt;2015&lt;/span&gt;-02-01-hello-world.md
_site
index.html&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;However, there’s a lot more hacking that can be done. Some examples are building an RSS feed, paginating the index page, getting better URLs, better theming and adding categories and tags. Also, although you can go ahead and upload the generated files to your personal server to get your blog online, it’s still worth to discuss some alternatives to ease that process.&lt;/p&gt;

&lt;p&gt;Unfortunately, it all starts to be too much for a single blog post. So expect to see all those examples explained in future tutorials, and don’t forget to &lt;a href=&quot;http://feeds.feedburner.com/ricardolopes/blog&quot;&gt;subscribe&lt;/a&gt; to get them as soon as they’re published. In the meantime, my blog’s source code is open, so you can learn from it and get some ideas through its &lt;a href=&quot;https://github.com/rplopes/ricardolopes.net&quot;&gt;Github project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href=&quot;/blog/setting-up-a-hackers-blog-with-jekyll-part-2/&quot;&gt;Part 2&lt;/a&gt; and &lt;a href=&quot;/blog/setting-up-a-hackers-blog-with-jekyll-part-3/&quot;&gt;Part 3&lt;/a&gt; now available.&lt;/p&gt;
</description>
        <pubDate>Sun, 01 Feb 2015 00:00:00 +0000</pubDate>
        <link>http://ricardolopes.net/blog/setting-up-a-hackers-blog-with-jekyll/</link>
        <guid isPermaLink="true">http://ricardolopes.net/blog/setting-up-a-hackers-blog-with-jekyll/</guid>
        
        <category>Jekyll</category>
        
        <category>Ruby</category>
        
        <category>blogging</category>
        
        <category>HTML</category>
        
        
        <category>tutorial</category>
        
      </item>
    
      <item>
        <title>What Windows 8 could have been</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; This blog post was first published on the 25th of November of 2012. This means that most of its content might no longer be up-to-date. This was published in my previous blog, which has &lt;a href=&quot;/blog/a-postmortem-of-my-wordpress-blog/&quot;&gt;met an unfortunate end&lt;/a&gt;, and is being reposted now as an attempt to resurface some of the most popular posts that have been lost. After the very recent announcement by Microsoft about the new Windows 10, this seems to be an interesting time to bring back this particular post.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2015-01-23-w8.png&quot; alt=&quot;Windows 8 screenshot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This post was supposed to be yet another Windows 8 review but, as I’ve gained experience with the latest Microsoft OS, I saw the potential for something a little more interesting. I’ve been using Windows 8 as the only OS in my main computer since it was officially released by Microsoft, so I might say I have some experience, now, to tell you a thing or two about it that you probably missed in other reviews. I’ve already used Windows, Mac and Linux as my primary OS (and I tend to change it quite frequently), and I find advantages and disadvantages in all of them. I’m pretty “agnostic” in most technology debates, and OSs aren’t an exception, so these thoughts aren’t distorted by fanboy opinions. I didn’t do a simple review not only because the Internet is full of it (really, I’m not even posting any links), but because my continuous usage of this new OS kept bugging me more and more about very specific details. So I’ll skip the typical suspense and just tell you my quick opinion about it, so I can discuss what I see as the most pressing issue: what Windows 8 could have been.&lt;/p&gt;

&lt;p&gt;Firstly, I know many people don’t agree with me, but I actually think Microsoft changed the game with Windows 8 and the Surface. The notion of converging the laptop and tablet experience seems almost intuitive to me. As you might already know, tablets are the latest revolution in computing and are slowly throwing laptops to oblivion as once laptops did to desktop PCs (OK, I know it’s not that simple, but when we look at market shares there’s no doubt the landscape is changing). Tablets are also more portable than the thinnest ultrabooks, have a more intuitive and friendly input, don’t have the dreaded noisy fans, have better communication options and so on (I could go on listing the advantages of tablets over any laptop, but I guess I made my point already). So isn’t it silly that we’re still using them just as consumption devices (read: overpriced toys)? Is the great revolution in computing really only worth it for browsing Facebook and throwing some birds at evil pigs?&lt;/p&gt;

&lt;p&gt;The answer, of course, is no. If these devices are so much better than their ancestors, then we must be able to switch and leave the old laptops behind. Some power users might not be able to do it, but that’s exactly what happened in the transition from desktop PCs to laptops anyway. Apple has been very careful in this matter: they have slowly improved iOS to meet more demands and updated Mac OS to be more iOS-like. They’re basically doing baby steps for converging the two OSs, cautious not to make a very risky move. I’m still very curious about what the conclusion of that convergence might look like. Microsoft, on the other hand, went all-in about the matter and evolved from a pure PC OS to a completely hybrid, both tablet-friendly and “traditional”.&lt;/p&gt;

&lt;p&gt;In my opinion, and this might be controversial, Microsoft decided, for a change, to be the innovator and to push to the market a concept that is probably ahead of its time. They were so proud of their concept, they even build their own tablet/laptop hybrid just so they could show the full picture of their envisioned game changer product. This move is as refreshing as it is unexpected. So, as you can see by now, Windows 8 and the tablet/laptop hybrids approach have really caught my eye and promise to be a welcome revolution brought by an unexpected player.&lt;/p&gt;

&lt;p&gt;So… what could possibly go wrong? Here are some of the details I’ve been struggling with lately.&lt;/p&gt;

&lt;h2 id=&quot;affordances&quot;&gt;Affordances&lt;/h2&gt;

&lt;p&gt;In interaction design, affordance is the quality of an element to display to a user how it is supposed to be used. Imagine a door with no signs and with equal handles on both sides. That’s an example of poor affordance, since you don’t know if you’re supposed to push it or pull it. A door with better affordance would have the handle only in the side where you needed to pull and probably a sign in each side displaying the correct action.&lt;/p&gt;

&lt;p&gt;The Modern UI design aka Windows Store design aka Metro style design is, in my opinion, a nice UI that makes Windows Phone 7 and 8 look much more fresh and lively than the big guys iOS and Android. However, I’m not so sure about it in tablets and specially on regular PCs. One of its major advantages, the flat UI that strips down the unnecessary and focuses on content, is also one of its major flaws, because you’re also losing some important elements that weren’t just there for decoration. Don’t agree?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2015-01-23-w8-settings.png&quot; alt=&quot;Windows 8 affordances example&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This image is showing two different elements from the same screen (not in their actual position, just next to each other in this picture for comparison). The one on the top is just a title with no action on click, and the one in the bottom is a button to a settings page (although we’re already in a settings panel, and another button in the same panel already points us to the Control Panel, another settings tool).&lt;/p&gt;

&lt;p&gt;I could add more examples, but I hope you got the idea. Cleaning the UI is a very good idea, but you must do it with caution. “Make it as simple as possible, but not simpler”.&lt;/p&gt;

&lt;h2 id=&quot;the-best-of-two-worlds&quot;&gt;The best of two worlds?&lt;/h2&gt;

&lt;p&gt;One of Windows 8′s most ambitious promises is the convergence of desktop and tablet experiences. As I said, I’m a big fan of that concept and I believe that’s a trend to follow. But a concept is one thing, execution is another. My ideal use case would be something like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I pick my tablet for working on the go. Since I don’t have paperwork nor a cumbersome laptop to carry, travelling with everything I need for work (just a tablet) is easier than ever. In those free times I can just turn on my tablet and browse my favourite websites, check my email and so on. When I get to my office I just link the Bluetooth keyboard and mouse and the HDMI display, start the traditional environment and fire up the MS Office suite, the IDE, etc.&lt;/p&gt;

  &lt;p&gt;Next day I decide to do some work at a coffee shop, so I just bring the tablet and a keyboard (a Surface keyboard would add no bulk to the pack, and a keyboard dock like what we see in Asus’s offerings would, in a worst case scenario, make me feel like I’m carrying a thin netbook).&lt;/p&gt;

  &lt;p&gt;When going to meetings, presentations or others I simply carry the tablet and use it with the onscreen keyboard, since I won’t be typing long sequences of text. In between, I think about my laptop and wonder when was the last time I used that heavy, noisy and awkward machine.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This use case is what I think when I see new hybrids in the market running full-blown OSs in a tablet form and when I hear Microsoft state how Windows 8 promises to deliver the best of both worlds. Unfortunately, that’s not what’s happening.&lt;/p&gt;

&lt;p&gt;Firstly, Windows RT, a dumbed-down version of Windows 8 developed to run on ARM processors, miserably fails to live up to that promise, as you won’t be able to run legacy apps in it (read: you can’t install typical desktop applications, like the ones you absolutely must have for your job).&lt;/p&gt;

&lt;p&gt;Also, when using a tablet with no mouse or keyboard, this ideal vision means not interacting with the traditional desktop and its windows, as they’re not the most touch friendly interfaces you’ll see. So it’s too bad that actions such as file management and configuring some settings have to be done in the desktop environment. I can’t help but think that Microsoft’s tight schedule for Windows 8 left many holes in the OS, and this lack of support for the continuous use of the tablet environment shows many of them.&lt;/p&gt;

&lt;p&gt;These holes in the OS aren’t an exclusive of the tablet interface. As an example, in the desktop mode hitting the Networks taskbar icon brings a panel in line with the new design, but hitting the Sound or Power taskbar icons still brings the old style popup. Also, when using the desktop environment, the Charms bar has close to no functionality (but it still shows up when hitting non-configurable hot corners). There are many more rough corners that still need to be polished if this is to look like a finished product.&lt;/p&gt;

&lt;p&gt;Finally, the integration of these two poorly-implemented worlds is nothing but disappointment. If you like a Metro application, you can’t run it as a window in the desktop environment (nor can you go full-screen in most desktop applications). If you open a file in one of the environments, the only way to move it to the other environment is to open it again manually using another application. The only way to see two Metro apps at once (or any Metro app while using the desktop interface) is by snapping one of them to the left or right of the screen. However, you have no control of the size of each app, and you can’t have two documents side by side, since the distributed space isn’t 50%-50%, but more like 75%-25%.&lt;/p&gt;

&lt;h2 id=&quot;apps-apps-apps&quot;&gt;Apps, apps, apps&lt;/h2&gt;

&lt;p&gt;At the end of the day, what really matters is the applications. That’s why most users prefer Mac OS or Linux over Windows, but when you look at market shares that’s not what it looks like. However, with this new OS Microsoft seems to be trying to get rid of its huge market advantage.&lt;/p&gt;

&lt;p&gt;As I’ve stated before, there’s not much integration between the two different environments of Windows 8. So, while you have a huge collection of legacy apps in the traditional one, you’ll feel the emptiness of options in the newest one. If desktop apps could integrate with the tablet mode this wouldn’t be such a big issue, because we’d have something to cover that emptiness while the new apps ecosystem was being developed. But we don’t, so if you’re like me you’ll probably want to make use of that awesome new environment, but will find no reason for it and eventually give up.&lt;/p&gt;

&lt;p&gt;Things get pretty ugly if you consider Windows RT instead of 8, because it also has a desktop mode but lacks the support for legacy apps. So yes, the market leader that has built its success on top of its huge apps ecosystem has just started a new one from scratch and one of the versions of its newest OS doesn’t even support the old one.&lt;/p&gt;

&lt;p&gt;Also, if this new desktop/tablet mix in the same OS serves as a “bridge” from the old ecosystem to the new, I can’t figure a simple reason for Microsoft to launch the Surface with RT before launching the Surface with 8. They basically launched a device with virtually no ecosystem and waited to later launch a similar device with support for all Windows applications. That’s like trying to build a whole village in a desert island and only later building a bridge to it. I wonder how much has Microsoft lost with this new, unpopulated village already.&lt;/p&gt;

&lt;p&gt;Finally, if we look to the Metro apps that come with the OS, there’s also some aspects that make me think this could have gone a totally different way. The built-in calendar app couldn’t import all calendars from my Google account (in fact, it could only import the personal one), so it’s useless for me. The messaging app can’t send new messages if I’m set as invisible, and can’t get them from contacts that show up as offline, so this one’s also useless for me. Thanks to the poor integration between the two environments, I can’t get a mini player of the XBox Music app (only a snapped panel from top to bottom that shrinks my horizontal desktop area). These are just some examples of the poor job that leave us early adopters with little incentive to keep trying the new environment.&lt;/p&gt;

&lt;h2 id=&quot;to-sum-up&quot;&gt;To sum up&lt;/h2&gt;

&lt;p&gt;Please don’t get me wrong: I love Windows 8′s concept and I share (more or less) Microsoft’s vision for the future of computers. If this was the typical review, I’d spend more time highlighting some good implementations and how I believe it’s the right direction. I might even have recommended the upgrade. However, my goal is to highlight what I find poorly implemented in such a great concept.&lt;/p&gt;

&lt;p&gt;Thanks to this whole notebook/tablet hybrid concept, I’ve started to look at the latest ultrabooks as kind of obsolete devices. They don’t have touch screens, it’s impossible to use them while walking without looking awkward, and so forth. The same goes for all Apple’s notebook options (that’s probably the reason why most Apple fans don’t agree with this vision). However, after quite some time with Windows 8, I fear we don’t have a strong alternative yet.  Yes, this is definitely an important step in that direction, but it’s still looking too immature, for now. Windows 8 seems to have suffered a lot from its tight schedule and, thanks to this incomplete effort, we now have a vision of what’s to come, but are left with a poor demo of it.&lt;/p&gt;

&lt;p&gt;All in all, this could have been a new revolution in the way we use our computers. As it stands, it’s nothing but a glimpse of what that revolution might look like. Maybe they’ll get it right in an hypothetical Windows 9. After all, Microsoft is known for releasing great versions of Windows after disappointing ones, and disappointing versions after great ones (and so far, this pattern seems unchanged). Or maybe Apple will get it right first.&lt;/p&gt;
</description>
        <pubDate>Fri, 23 Jan 2015 00:00:00 +0000</pubDate>
        <link>http://ricardolopes.net/blog/what-windows-8-could-have-been/</link>
        <guid isPermaLink="true">http://ricardolopes.net/blog/what-windows-8-could-have-been/</guid>
        
        <category>Windows</category>
        
        <category>Microsoft</category>
        
        <category>UX</category>
        
        
        <category>rant</category>
        
      </item>
    
  </channel>
</rss>
