timmesserschmidtDeveloper Relationshttps://timmesserschmidt.com/blog2016-09-08T15:00:00-07:00Tim MesserschmidtSecurity UI&#47;UX best practices with FirebaseUI Authhttps://timmesserschmidt.com/blog/2016/09/09/firebaseui-auth/2016-09-08T15:00:00-07:002017-02-28T07:07:06-08:00Tim Messerschmidt<p>In this post I’d like to cover a great open source library: FirebaseUI (for <a href="https://github.com/firebase/FirebaseUI-Android">Android</a> and <a href="https://github.com/firebase/FirebaseUI-iOS">iOS</a>). I’ve been <a href="http://www.slideshare.net/TimMesserschmidt/death-to-passwords-sxsw">pretty vocal</a> about the need to come up with better patterns around dealing with passwords or even ideally getting completely rid of them by using better alternatives and I feel like Firebase’s approach towards authentication is very much in line with what I’ve been demanding.</p>
<h2 id="what-is-firebaseui-auth">What is FirebaseUI Auth?</h2>
<p>FirebaseUI Auth is a collection of UI bindings for Firebase that allows to handle presenting data from Firebase (FirebaseUI Database) and offers a beautiful drop-in solution to handle user authentication (FirebaseUI Auth) in your Android or iOS application. It comes with support for <a href="https://get.google.com/smartlock/">Smart Lock</a>, integrates with the most common identity providers (such as Facebook, Twitter, and Google) and allows to customize it’s UI by simply providing a theme on Android or subclassing <code>FIRAuthPickerViewController</code> on iOS.</p>
<h2 id="why-is-it-useful">Why is it useful?</h2>
<p>The team took a look at implementing several security best practices - such as suggesting a user’s frequently used email addresses (via <a href="https://developers.google.com/identity/smartlock-passwords/android/retrieve-hints">Smart Lock HintRequest</a>), creating new accounts or linking multiple accounts to the same user. This sounds very easy in theory but looking at the variety of possible cases this suddenly becomes a behemoth that isn’t all that easy to handle (picture taken from the FirebaseUI Auth <a href="https://github.com/firebase/FirebaseUI-Android/blob/master/auth/README.md">documentation</a>):</p>
<p><img src="/public/img/posts/auth_flow.png" alt="ssl" class="img-responsive" /></p>
<p>Not having to work on solving all these different (edge) cases and instead focussing on a great user experience (and your own application) sounds like a great proposition for me. This is why I’d love to encourage you to give FirebaseUI a try and provide me or the team itself (via <a href="https://twitter.com/firebase">Twitter</a> or <a href="https://github.com/firebase/FirebaseUI-Android/issues">GitHub</a>) with any feedback you might have.</p>
<h2 id="how-can-i-use-it">How can I use it?</h2>
<p>Installation is as easy as using either Gradle or CocoaPods in order to resolve the right dependencies. The team has split up FirebaseUI into multiple modules/subspecs in order to allow you to select the most minimal feature set you’re interested in. There are great samples - like the FirebaseUI Chat Demo for <a href="https://github.com/firebase/FirebaseUI-iOS/tree/master/examples/FirebaseUIChat">iOS</a> or the sample application for <a href="https://github.com/firebase/FirebaseUI-Android#sample-app">Android</a> that outline the steps needed to get the library integrated.</p>
<p>I’ll be giving a talk at <a href="https://droidcon.at/schedule/#session-117">Droidcon Vienna</a> next weekend and am looking forward to discussing current authentication UI/UX best practices with the attendees!</p>
Hosting Static Web Apps with Firebasehttps://timmesserschmidt.com/blog/2016/05/25/hosting-with-firebase/2016-05-24T15:00:00-07:002017-02-28T07:07:06-08:00Tim Messerschmidt<p>Amongst the major announcements of last week’s I/O, Google’s annual developer conference, was the release of the new (&amp; awesome) Firebase. Firebase is renowned for it’s realtime database that allows for instantly synchronizing entries between mobile clients (Android &amp; iOS) and the web. One feature that is lesser known will be the focus of this post: the ability to host static sites and web apps.</p>
<p>Last Saturday I gave Firebase’s hosting feature a try and <a href="http://twitter.com/SeraAndroid/status/734145833600319489">shared my experience</a>. The response from the developer community was overwhelming and very positive; people were interested in reasons why to choose Firebase and what features it allows to use.</p>
<center>
<blockquote class="twitter-tweet" data-cards="hidden" data-lang="en"><p lang="en" dir="ltr">Just deployed my blog with <a href="https://twitter.com/Firebase">@Firebase</a> in less than 2 minutes. Highly impressed and deeply in love! <a href="https://t.co/bvCvJDKWfI">pic.twitter.com/bvCvJDKWfI</a></p>&mdash; Tim Messerschmidt (@SeraAndroid) <a href="https://twitter.com/SeraAndroid/status/734145833600319489">May 21, 2016</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</center>
<h2 id="the-upsides-and-downsides-of-gh-pages">The upsides and downsides of GH Pages</h2>
<p>As a quick reminder: I’ve been using <a href="http://pages.github.com">GitHub Pages</a> as a comfortable way to host my blog (and a variety of side-projects) for a couple of years. GH Pages is fantastic when it comes to quickly deploying your site, offers native support for Jekyll, comes with GitHub’s own SSL certificate for sites that run on their domain (github.io) and even allows for quickly editing your project <a href="http://help.github.com/articles/editing-files-in-your-repository">directly in the browser</a>.</p>
<p>Sadly GH pages doesn’t allow for configuring your site’s HTTP headers (like setting the <code>Cache-Control</code> header) to optimize performance and your application’s behavior. When using custom domains (ergo your own domain) with GitHub Pages you loose the convenience of SSL protection.</p>
<h2 id="my-move-to-firebase">My move to Firebase</h2>
<p>Amongst the features that come per default with <a href="http://firebase.google.com/docs/hosting/">Firebase Hosting</a> are an amazing CDN, SSL per default, one-click rollbacks and a really fun CLI that allows for easy configuration and deployment of your project.</p>
<p>My project, this blog, consists of three folders - <code>data</code> (static json files that I use to manage certain resources such as my blog’s <a href="http://timmesserschmidt.com/events">events page</a>, <code>source</code> (this is where my Ruby code, my posts, and my blog’s templates reside) and <code>build</code> (you see the result here); for this kind of project it’s only relevant to deploy the content of <code>build</code>; Firebase allows for configuring your project’s <code>public</code> folder in the <code>firebase.json</code> (<a href="http://firebase.google.com/docs/hosting/deploying#section-firebase-json">check out the docs</a> for more information).</p>
<p>In addition to that, you can also define URL rewrites to clean-up your application’s URLs (for example: remove trailing slashes or redirect certain pages) and customize your application’s <a href="http://firebase.google.com/docs/hosting/url-redirects-rewrites#section-headers">headers</a> based on file specific <a href="http://firebase.google.com/docs/hosting/full-config#section-glob">glob notation</a>. This is useful for optimizing your page’s performance by tweaking the default caching behavior (check out <a href="http://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en#cache-control">this great doc</a> on the <code>Cache-Control</code> header) or setting up <a href="http://en.wikipedia.org/wiki/Cross-origin_resource_sharing">Cross-origin Resource Sharing</a>.</p>
<h2 id="your-thoughts">Your thoughts</h2>
<p>I hope this post helps clarifying some of the questions I’ve received around hosting static web applications with Firebase and I’d be happy to hear your thoughts! Please feel free to contact me via <a href="http://twitter.com/seraandroid">Twitter</a> or <a href="http://plus.google.com/+TimMesserschmidt">G+</a>!</p>
Service Worker Precache for Middlemanhttps://timmesserschmidt.com/blog/2016/05/15/sw-precache/2016-05-14T15:00:00-07:002017-02-28T07:07:06-08:00Tim Messerschmidt<p>After we’ve taken the time to explore the basic functionality of Service Worker in my <a href="/blog/2016/05/10/service-worker/">most recent post</a>, I’d like to expand on this topic by covering <a href="http://github.com/GoogleChrome/sw-precache">sw-precache</a> (a module for generating a worker that handles precaching of your application’s resources) and how to use it with Middleman.</p>
<p>As a quick reminder, Service Worker is a feature of Progressive Web Apps, that handles fetching and caching of resources and greatly increases application’s performance.</p>
<p>The Chrome team has released a module called sw-precache that applies best practices around handling your application’s workers and ensuring that your client always serve the newest version of your resources. In order to achieve this, sw-precache generates MD5 hashes of all your application’s resources and stores them in the worker’s file:</p>
<pre class="highlight javascript"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre><span class="kd">var</span> <span class="nx">PrecacheConfig</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">[</span><span class="s2">"about/index.html"</span><span class="p">,</span><span class="s2">"10def4949ab13adf7f1e81dd4a201a01"</span><span class="p">],</span>
<span class="p">[</span><span class="s2">"assets/bootstrap/dist/fonts/glyphicons-halflings-regular.eot"</span><span class="p">,</span><span class="s2">"f4769f9db7466be65088239c12046"</span><span class="p">],</span>
<span class="p">...</span>
<span class="p">];</span>
</pre></td></tr></tbody></table>
</code></pre>
<p>Whenever a file’s size changes the related MD5 hash changes, too, and the Service Worker can update your application’s cache.</p>
<h2 id="running-sw-precache-automatically">Running sw-precache automatically</h2>
<p>sw-precache works in harmony with Grunt and can be defined as a task in your application’s build process. Sadly Grunt is not native to the world of Ruby and therefore we’ll have to deal with Rake. Since I publish my site on GitHub pages I make use of <code>middleman-gh-pages</code> - this gem handles pushing the built source to the <code>master</code> branch while the actual source code resides in <code>source</code>.</p>
<p>The perfect hook for using sw-precache would be the <code>publish</code> task - <a href="http://github.com/edgecase/middleman-gh-pages/blob/master/lib/middleman-gh-pages/tasks/gh-pages.rake#L85">as defined here</a> - which ensures that there are no dirty builds, (re-)syncs the directory, builds the project and then handles pushing the source code.</p>
<pre class="highlight ruby"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="n">task</span> <span class="ss">:publish</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="ss">:prevent_dirty_builds</span><span class="p">,</span> <span class="ss">:sync_build_dir</span><span class="p">,</span> <span class="ss">:build</span><span class="p">]</span> <span class="k">do</span>
<span class="c1"># Fancy Ruby magic</span>
<span class="k">end</span>
</pre></td></tr></tbody></table>
</code></pre>
<p>Next to sw-precache’s ability to be used as Grunt task, you can also use the Node executable <a href="http://github.com/GoogleChrome/sw-precache#command-line-interface">via a CLI</a> to run it on it’s own. We can use this to our advantage and define a new task in our project’s Rakefile:</p>
<pre class="highlight ruby"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="n">desc</span> <span class="s2">"Runs sw-precache from the build directory"</span>
<span class="n">task</span> <span class="ss">:sw</span> <span class="k">do</span>
<span class="n">sh</span> <span class="s2">"cd build &amp;&amp; sw-precache"</span>
<span class="k">end</span>
</pre></td></tr></tbody></table>
</code></pre>
<p>During the build process Middleman creates a new directory called <code>build</code> in your project’s root folder - this is where we want to run sw-precache before the code gets published.</p>
<p>The last bit that needs to be done is overriding the publish task. In Rake lingo we <em>enhance</em> the task by adding another prerequisite to the task:</p>
<pre class="highlight ruby"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="n">task</span> <span class="ss">:publish</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="ss">:prevent_dirty_builds</span><span class="p">,</span> <span class="ss">:sync_build_dir</span><span class="p">,</span> <span class="ss">:build</span><span class="p">,</span> <span class="ss">:sw</span><span class="p">]</span>
</pre></td></tr></tbody></table>
</code></pre>
<p>Once the Rake file has been modified, running <code>rake publish</code> leads to building the source, generating the service-worker.js file in your project’s build folder and publishing the code to GitHub.</p>
<p>I hope this proves to be useful to some of you out there - I’d be more than happy to hear your thoughts!</p>
Using the Power of the Service Workerhttps://timmesserschmidt.com/blog/2016/05/10/service-worker/2016-05-09T15:00:00-07:002017-02-28T07:07:06-08:00Tim Messerschmidt<p>In today’s blog post I’d like to write about an essential component of <a href="http://developers.google.com/web/progressive-web-apps?hl=en">Progressive Web Apps</a>: the <a href="http://slightlyoff.github.io/ServiceWorker/spec/service_worker/">Service Worker</a> - an event-driven background processing tool that enables fetching resources and managing your application’s cache. The result is a gain in reliable performance; connection quality and network performance loose in importance when it comes to enjoying your application.</p>
<p>Service Worker got introduced as feature with Chrome 40 and since then made it into a number of other browsers such as Firefox, Opera, Edge (currently in the works) and hopefully soon Safari, too. You can find a complete overview about <a href="http://jakearchibald.github.io/isserviceworkerready/">browser support for Service Workers here</a>. A requirement for making use of Service Worker is HTTPs - this prevents things like injecting malicious code into a site that persists due to being cached.</p>
<h2 id="putting-the-service-worker-to-work">Putting the Service Worker to work</h2>
<p>As I’ve mentioned in this post’s introduction, a Service Worker can handle fetching resources, application caching and much more. In order to make this happen Service Workers rely on ES2015’s <a href="http://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise#Description">Promises</a> - a new (and awesomely efficient) way to handle asynchronous requests.</p>
<p>First of all we’ll need to start adding event listener’s that subscribe to a number of important events (namely <code>install</code>, <code>activate</code> &amp; <code>fetch</code>). There are a <a href="http://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Basic_architecture">few more events</a> that can add additional functionality but we’ll ignore them for now.</p>
<p><code>install</code> is fired after <code>navigator.serviceWorker.register()</code> ran successfully - this is where we want to define which files to cache. You’ll noticed that I’ve provided my domain <code>tme.coffee</code> as the cache’s name. You can choose whatever works best (and hopefully is somehow unique) here.</p>
<pre class="highlight javascript"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre><span class="kd">var</span> <span class="nx">toCache</span> <span class="o">=</span> <span class="p">[</span>
<span class="s1">'/'</span><span class="p">,</span>
<span class="s1">'/public/css/site.css'</span><span class="p">,</span>
<span class="s1">'/public/js/bootstrap.min.js'</span>
<span class="p">];</span>
<span class="nx">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'install'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">e</span><span class="p">.</span><span class="nx">waitUntil</span><span class="p">(</span>
<span class="nx">caches</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="s1">'tme.coffee'</span><span class="p">).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">cache</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">addAll</span><span class="p">(</span><span class="nx">toCache</span><span class="p">).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">self</span><span class="p">.</span><span class="nx">skipWaiting</span><span class="p">();</span>
<span class="p">});</span>
<span class="p">})</span>
<span class="p">);</span>
<span class="p">});</span>
</pre></td></tr></tbody></table>
</code></pre>
<p>In my case I choose to cache my page’s CSS and Bootstrap. This saves valuable time and resources when (re-)visiting this blog, resulting in a performance gain. To force an update you’ll need to modify the Service Worker’s file - a simple trick to force an update is bumping a version number:</p>
<pre class="highlight javascript"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="kd">var</span> <span class="nx">version</span> <span class="o">=</span> <span class="s1">'0.0.1'</span><span class="p">;</span> <span class="c1">// increment in order to force a cache update</span>
</pre></td></tr></tbody></table>
</code></pre>
<p>Depending on your site’s <code>cache-control</code> headers the update might actually not happen directly.</p>
<p>You’ll notice the usage of <code>skipWaiting()</code> while handling the <code>install</code> event; this method works in relation to <code>clients.claim()</code> and ensures that updates to the worker take immediate effect on all clients.</p>
<p>The next event, <code>activate</code>, can be used to handle tasks like cache management. In this basic example we use <code>self.clients.claim()</code> to set our Service Worker as the client page’s active worker:</p>
<pre class="highlight javascript"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="nx">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'activate'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">event</span><span class="p">.</span><span class="nx">waitUntil</span><span class="p">(</span><span class="nx">self</span><span class="p">.</span><span class="nx">clients</span><span class="p">.</span><span class="nx">claim</span><span class="p">());</span>
<span class="p">});</span>
</pre></td></tr></tbody></table>
</code></pre>
<p>The final event we’ll explore is <code>fetch</code>. This is where we can decide if a resource should be returned from the application’s cache or should be fetched and provided to the client:</p>
<pre class="highlight javascript"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre><span class="nx">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'fetch'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">event</span><span class="p">.</span><span class="nx">respondWith</span><span class="p">(</span>
<span class="nx">caches</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">response</span> <span class="o">||</span> <span class="nx">fetch</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">);</span>
<span class="p">})</span>
<span class="p">);</span>
<span class="p">});</span>
</pre></td></tr></tbody></table>
</code></pre>
<h3 id="adding-the-service-worker">Adding the Service Worker</h3>
<p>In this last section we’ll go through the needed code in order to load the worker we’ve defined above. In my case the Service Worker resides in a file called <code>sw.js</code> in my project’s root folder. The following snippet ends up enclosed by a <code>&lt;script&gt;</code>-tag in your layout’s body. As with most resources that end up being loaded when opening up your page I’d recommend moving this code at the bottom of your document in order to ensure that your file renders other information (such as your minimum required CSS and the document itself) before:</p>
<pre class="highlight javascript"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre><span class="k">if</span><span class="p">(</span><span class="s1">'serviceWorker'</span> <span class="k">in</span> <span class="nx">navigator</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">navigator</span><span class="p">.</span><span class="nx">serviceWorker</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="s1">'/sw.js'</span><span class="p">,</span> <span class="p">{</span> <span class="na">scope</span><span class="p">:</span> <span class="s1">'/'</span> <span class="p">}).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">registration</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"SW registered"</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">navigator</span><span class="p">.</span><span class="nx">serviceWorker</span><span class="p">.</span><span class="nx">ready</span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">registration</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"SW ready"</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
</pre></td></tr></tbody></table>
</code></pre>
<p>The beauty is that the snippet doesn’t cause any harm when Service Worker is not available. We don’t break anything and the worker is simply ignored.</p>
<p>Congratulations! If you’ve followed this post (and adjusted the code to your needs) you should’ve Service Worker-enabled your application. You can check if everything works as intended by navigating to <code>chrome://serviceworker-internals</code>.</p>
kramdown instead of Redcarpethttps://timmesserschmidt.com/blog/2016/04/07/kramdown-redcarpet/2016-04-06T15:00:00-07:002017-02-28T07:07:06-08:00Tim Messerschmidt<p>Since <a href="/blog/2016/03/14/a-new-blog-using-middleman/">my switch to Middleman</a> I’ve been using <a href="http://github.com/vmg/redcarpet">Redcarpet</a> as Markdown engine. The rendering engine itself ran fine but sadly doesn’t offer a way to specify custom classes for elements - a shame when you’re looking for a way to declare a certain image as <code>img-responsive</code> for Bootstrap et cetera.</p>
<p>Middleman gladly supports a variety of engines (including <a href="http://kramdown.gettalong.org/">kramdown</a>) and I figured it might be worth switching in order to obtain that extra bit of flexibility. kramdown comes with a non-standard syntax for CSS-classes:</p>
<pre class="highlight markdown"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="p">![</span><span class="nv">an-image-description</span><span class="p">](</span><span class="sx">someimage.png</span><span class="p">)</span>{: .img-responsive }
<span class="p">![</span><span class="nv">another-image-description</span><span class="p">](</span><span class="sx">anotherimage.png</span><span class="p">)</span>{: .img-responsive .round }
<span class="p">![</span><span class="nv">an-image-with-id</span><span class="p">](</span><span class="sx">imagewithid.png</span><span class="p">)</span>{: #banner .img-responsive }
</pre></td></tr></tbody></table>
</code></pre>
<p>When you’re looking into switching your Markdown engine you’ll have to set the following line in your <code>config.rb</code>:</p>
<pre class="highlight ruby"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="n">set</span> <span class="ss">:markdown_engine</span><span class="p">,</span> <span class="ss">:kramdown</span>
</pre></td></tr></tbody></table>
</code></pre>
<p>Another engine that allows using custom CSS-classes via attribute lists is <a href="http://maruku.rubyforge.org/proposal.html#attribute_lists">Maruku</a>. Feature-wise it looks quite similar to kramdown but there has been little activity in <a href="http://github.com/bhollis/maruku">it’s GitHub repository</a>.</p>
<p>I hope this short post helps a few of you,<br />
Tim</p>
Let's Encrypt for GitHub Pageshttps://timmesserschmidt.com/blog/2016/03/18/lets-encrypt-gh-pages/2016-03-17T16:00:00-07:002017-02-28T07:07:06-08:00Tim Messerschmidt<p>In my <a href="/blog/2016/03/14/a-new-blog-using-middleman/">most recent post</a> I wrote about rewriting my blog from scratch and my attempts at improving it’s performance, reliability and ease of use. While exploring possible options I also investigated if it makes sense - and if it’s worth the hassle - to enable HTTPS for this site.</p>
<p>While searching for possible solution a GitHub issue came up that asked GitHub to start supporting HTTPS for GitHub through SSL certificates provided by Let’s Encrypt. To me it seemed like the discussion was worthwhile to follow-up with; the plan was to go back within the next few days and see if an elegant solution has been proposed.</p>
<h3 id="lets-encrypt-amp-kloudsec">Let’s Encrypt &amp; Kloudsec</h3>
<p><a href="http://letsencrypt.org">Let’s Encrypt</a> is a relatively new Certificate Authority (sponsored by prominent companies and teams such as Mozilla, the Google Chrome team and Facebook), that aims at securing internet traffic by issuing free SSL certificates.</p>
<p>An amazing startup from Singapore, <a href="http://kloudsec.com">Kloudsec</a>, tackled the issue by creating a CDN that works directly with Let’s Encrypt and offers SSL protection - plus a few <a href="http://kloudsec.com/#/features">other optimizations</a> - with very little configuration effort. The whole procedure involved changing merely 3 DNS records and after a few minutes my SSL certificate was issued.</p>
<p><img src="/public/img/posts/ssl.png" alt="ssl" class="img-responsive" /></p>
<p>I’m pretty happy with this solution and am keen to see what else they come up with.</p>