<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[A blog by G.C. Marty]]></title><description><![CDATA[A blog about JavaScript, HTML, the web platform, NLP and to how optimise them all!]]></description><link>https://gu.illau.me</link><generator>RSS for Node</generator><lastBuildDate>Thu, 03 May 2018 13:54:59 GMT</lastBuildDate><atom:link href="https://gu.illau.me/feed.xml" rel="self" type="application/rss+xml"/><author><![CDATA[G.C. Marty]]></author><pubDate>Thu, 03 May 2018 13:54:59 GMT</pubDate><copyright><![CDATA[2018 G.C. Marty]]></copyright><language><![CDATA[en]]></language><managingEditor><![CDATA[G.C. Marty]]></managingEditor><webMaster><![CDATA[G.C. Marty]]></webMaster><ttl>60</ttl><item><title><![CDATA[How to organise a meetup?]]></title><description><![CDATA[<p>Organising a meetup is a great way to connect with like-minded people and exchange on topics you&#39;re passionate about. In this post I gathered some tips based on my experience organisation meetups in the last few years.</p>
<h2><a name="finding-speakers" class="anchor" href="#finding-speakers"><span class="header-link"></span></a>Finding speakers</h2>
<p>Probably the most tricky part of organising meetups, specially when you get started.</p>
<p>Make sure to leverage your network. Some of your friends, colleagues, Twitter followers may not have considered giving a talk before. Give them a chance!</p>
<p>If you struggle to find speakers, you can be creative and maybe ask a remote speaker to speak through Skype or similar. There are also other things you can do like hands-on sessions, lightning talks or discussion panels.</p>
<p>I also enjoyed giving under-represented people (students...) a platform to talk, to foster a culture of diversity. I even hard-coded this principle in the rule of conduct of the last meetup I organised.</p>
<h2><a name="getting-a-venue" class="anchor" href="#getting-a-venue"><span class="header-link"></span></a>Getting a venue</h2>
<p>If you&#39;re in London and your meetup aligns somehow with <a href="https://www.mozilla.org/en-GB/mission/">Mozilla mission</a> and <a href="https://www.mozilla.org/en-GB/about/manifesto/">manifesto</a>, why not hold it at Mozilla office? You&#39;ll need to have an employee to sponsor you and make the requests on your behalf.</p>
<p>For other places or other topics I unfortunately don&#39;t have much experience, but you can try to contact the venues where you have attended meetups in the past. Here again, use your network!</p>
<h2><a name="drink-and-snack-sponsoring" class="anchor" href="#drink-and-snack-sponsoring"><span class="header-link"></span></a>Drink and snack sponsoring</h2>
<p>it&#39;s nice if possible to offer snacks and drinks to provide the attendees with the best experience possible. </p>
<p>I don&#39;t have much experience in finding sponsor but you can try to contact hiring companies in industries closely related to your meetup. They&#39;ll be happy to sponsor your event in exchange of a way to get in touch with local talents and potential users.</p>
<p>Another possibility depending on the number of attendees is to buy and bring snacks and drinks for yourself. Some big meetups don&#39;t offer such amenities so don&#39;t feel bad if you don&#39;t.</p>
<h2><a name="av" class="anchor" href="#av"><span class="header-link"></span></a>AV</h2>
<p>Do you need any specific Audio/Video support? Some venues can accommodate all sorts of A/V needs (recording, live streaming...). At the very least you&#39;ll need an internet connection and a monitor to show slides and demos. Make sure you know your needs and clear any assumptions with both the speakers and the venue beforehand.</p>
<h2><a name="planning" class="anchor" href="#planning"><span class="header-link"></span></a>Planning</h2>
<p>When everything is ready, it&#39;s good to prepare a detailed plan. That will help on the day of your meetup to make sure speakers or Q&amp;A sessions don&#39;t overrun. It&#39;s also good to start on time specially if you&#39;re live streaming the event. That said, you must also keep in mind that some attendees may be late so allow a few minutes for everybody to show up before starting.</p>
<h2><a name="promotion" class="anchor" href="#promotion"><span class="header-link"></span></a>Promotion</h2>
<p>To advertise your meetup is critical to its success. Make sure your communicate it on social media and ask, for example, your speakers to help with spreading the word.</p>
<p>After your event it&#39;s also nice to engage with your participants and send a feedback form to help you make the next edition even better!</p>
<h2><a name="organisation" class="anchor" href="#organisation"><span class="header-link"></span></a>Organisation</h2>
<p>The big day has arrived! Make sure there is at least another person to help with the organisation. You&#39;ll be busy making sure everything is ready and the attendees are feeling welcome. Some support from someone who is up to date with the organisation will provide invaluable help.</p>
<p>That&#39;s it! Many other aspects such as using <a href="https://www.meetup.com/">meetup.com</a>, writing a good code of conduct or charging for attendance are not covered in this guide to keep it quick and easy. I hope the points above will decide you to get started with organising your very own meetup. Feel free to leave a comment below if you have more specific questions.</p>
]]></description><link>https://gu.illau.me/posts/how-to-organise-a-meetup/</link><guid isPermaLink="true">https://gu.illau.me/posts/how-to-organise-a-meetup/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Fri, 17 Mar 2017 00:00:00 GMT</pubDate></item><item><title><![CDATA[Augmented reality & computer vision]]></title><description><![CDATA[<blockquote>
<p><strong>tl;dr:</strong> Media capture, object detection and WebGL can be combined to hack a simple augmented reality experience. See my demo called <a href="https://gmarty.github.io/all-saints-ar/">we are all Saints</a>.</p>
</blockquote>
<p>To simplify things, augmented reality is based mainly on 2 technologies:</p>
<ul>
<li>Sensors to track the position and orientation of the user field of view (FOV)</li>
<li>Computer vision to detect objects in the user FOV</li>
</ul>
<p>Of course modern AR headsets like Hololens combine both to create the best experience possible. I explored using common devices with web technologies to create a simple AR experience. I decided to go for computer vision applied to media capture.</p>
<p><img src="https://raw.githubusercontent.com/gmarty/all-saints-ar/gh-pages/demo.jpg" alt="Screenshot of the demo"></p>
<h2><a name="object-detection" class="anchor" href="#object-detection"><span class="header-link"></span></a>Object detection</h2>
<p>There are few different libraries to detect objects in an image. Most of them seem to be based on <a href="https://en.wikipedia.org/wiki/OpenCV">OpenCV</a>, ported to JavaScript via emscripten.
I didn&#39;t spend too much time looking for a library and quickly settled for <a href="https://github.com/mtschirs/js-objectdetect">js-objectdetect</a>. It&#39;s hand-written (as opposed to converted via emscripten) so it makes easy to read, understand and debug if needed. It can detect different types of objects but I used human faces here.</p>
<p>Once set up properly, <code>js-objectdetect</code> accepts a video element as an input, so I just pass to it the one that displays the camera feed I got from <code>getUserMedia</code>.</p>
<p>It return the coordinates in pixel of the faces detected (left, top, width and height).</p>
<h2><a name="recreating-a-virtual-3d-space" class="anchor" href="#recreating-a-virtual-3d-space"><span class="header-link"></span></a>Recreating a virtual 3D space</h2>
<p>Next step is to place the faces detected in the image in a virtual 3D space by estimating their respective positions. I used A-Frame to create the 3D world because this framework is easy to use.</p>
<p>Positioning an element on the <code>x</code> and <code>y</code> axes is really easy. We need to convert the position in the (-1, 1) range, more about that later. For example a point centred in the image will have both its <code>x</code> and <code>y</code> values set to <code>0</code>. Knowing the position in pixels and the size of the video the values are easy to get (Also the <code>y</code> axis direction is reverse in the web and WebGL). For the <code>x</code> axis, half the width needs to be added so that the element is horizontally centred on the face.</p>
<p>The <code>z</code> axis is a bit trickier. It needs to get estimated and calibrated. I used the height value. I noticed that once detected my face takes at most 80% of the image height when I stand at about 50cm from the camera. The further I step back, say about 2m, the smaller my face gets, to take about 30% of the screen height.</p>
<p>I used these distances as the values for the camera frustum near and far clipping planes (<code>near</code> and <code>far</code> attributes on the <code>&lt;a-camera&gt;</code> element).</p>
<p>Then I only need to convert and clamp the height of the face detected between the % values of image height that I determined above. Once converted to the (-1, 1) range, they&#39;ll vary proportionally between 50cm and 2m. That gives me a good enough approximation of where my face is located in respect to the camera.</p>
<p>I also used the detected height to position the virtual element a few apparent centimetres on top the faces.</p>
<h2><a name="overlaying" class="anchor" href="#overlaying"><span class="header-link"></span></a>Overlaying</h2>
<p> A-Frame uses Three.js under the hood. That&#39;s what I&#39;m using to perform computations.</p>
<p>Now that I&#39;ve got the x, y and z position in the (-1, 1) range I need to unproject this vector along the active camera. That is not as complicated as it sounds:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="kr">const</span> <span class="nx">pos</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">THREE</span><span class="p">.</span><span class="nx">Vector3</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">,</span> <span class="nx">z</span><span class="p">).</span><span class="nx">unproject</span><span class="p">(</span><span class="nx">camera</span><span class="p">);</span>
</pre></div>
</code></pre>
<p>This returns a vector corresponding to the position in space of the object given the current FOV (i.e. camera).</p>
<p>Finally I can set the position of the A-Frame element in the virtual space that I want to super impose over faces:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="nx">element</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;position&#39;</span><span class="p">,</span> <span class="nx">pos</span><span class="p">);</span>
</pre></div>
</code></pre>
<h2><a name="conclusion" class="anchor" href="#conclusion"><span class="header-link"></span></a>Conclusion</h2>
<p>This experiment wasn&#39;t as hard as it sounded at first and the result is quite convincing. I learnt a lot about projection and unprojection in the process. As usual the code is on GitHub as <a href="https://github.com/gmarty/all-saints-ar">all-saints-ar</a> because we are all saints!</p>
]]></description><link>https://gu.illau.me/posts/augmented-reality-computer-vision/</link><guid isPermaLink="true">https://gu.illau.me/posts/augmented-reality-computer-vision/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Wed, 15 Feb 2017 00:00:00 GMT</pubDate></item><item><title><![CDATA[Experimenting with VR]]></title><description><![CDATA[<p>I just finished a short series of <a href="https://gmarty.github.io/VR-diary/">experimentations about virtual reality called VR Diary</a>. Here&#39;s a brief summary of why and how.</p>
<h2><a name="vr-but-what-for" class="anchor" href="#vr-but-what-for"><span class="header-link"></span></a>VR, but what for?</h2>
<p>Creating content for virtual reality is easy. <a href="https://aframe.io/">A-Frame</a> is probably the easiest way to get started. It&#39;s entirely free and open-source and only requires a basic of HTML programming. On other projects, I used <a href="https://developers.google.com/vr/unity/">Google VR SDK for Unity</a> and the graphic UI of Unity allows you to create content without even typing a single line of code.</p>
<p>So now the real question is what are we going to use VR for? VR is just a medium and in itself has no value.</p>
<p>This is what I explored in this project. VR is an immersive and engaging platform so I decided to use it to share personal experiences with the readers.</p>
<p>It took a direction towards philosophical questioning and reality challenging that I hadn&#39;t expected. But overall it&#39;s been successful from a personal standpoint: the experiments are consistent (except maybe the first one) and I&#39;ve been able to go through the 6 days.</p>
<h2><a name="working-as-a-hobby" class="anchor" href="#working-as-a-hobby"><span class="header-link"></span></a>Working as a hobby</h2>
<p>An essential aspect to this experiment is being on holiday with a lot of free time. I dedicated about 2 or 3 hours a day actively working on the VR experiment and writing the post. The rest of the day was spent thinking passively about what to do next.</p>
<p>This liberty was essential to generate new ideas to experiment. Creative people know you can&#39;t just sit at a desk and expect to get new ideas. That&#39;s when you go out for a walk, sit in the grass, spend some time in a zoo or a museum that you release the most of your creative potential.</p>
<p>I thoroughly enjoy this lifestyle of working actively a few hours in the morning and passively for the rest of the day. Maybe that&#39;s how life should be: dedicating most of your time to creativity and self-expression and work only for how long is necessary. This is something I want to explore more in the future.</p>
]]></description><link>https://gu.illau.me/posts/experimenting-with-vr/</link><guid isPermaLink="true">https://gu.illau.me/posts/experimenting-with-vr/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Wed, 07 Dec 2016 00:00:00 GMT</pubDate></item><item><title><![CDATA[Mozilla IOT Meetup London October 2016]]></title><description><![CDATA[<p>On Wednesday 12, October (2 days ago) the first <a href="https://www.meetup.com/Mozilla-IOT/">Mozilla IOT London meetup</a> took place at the Mozilla Common Space near London Bridge.</p>
<h2><a name="a-bit-of-history" class="anchor" href="#a-bit-of-history"><span class="header-link"></span></a>A bit of history</h2>
<p>The meetup was rebranded from the previous Firefox OS meetup group. A lot happened at Mozilla this year. The Firefox OS project was turned into a community project and the Connected Devices team was created.</p>
<p>Now that things got more stable we decided it was a good time to resume a series of meetups.</p>
<p>This was the first session so we&#39;re still learning and experimenting, but we&#39;re planning on doing monthly or bimonthly meetups. This first session was not recorded, but the plan is to record or stream the next ones.</p>
<h2><a name="the-first-session" class="anchor" href="#the-first-session"><span class="header-link"></span></a>The first session</h2>
<p>Meetups are and should always be about meeting people so we want to emphasise the social aspect of it and making a place where ideas are shared and discussions happen naturally.</p>
<p><img src="http://gu.illau.me/img/posts/mozilla-iot-meetup-london-october-2016/francisco-on-mozilla-connected-devices.jpg" alt="Francisco speaking about the creation of the Connected Devices team." title="Francisco speaking about the creation of the Connected Devices team."></p>
<p>For this first session, we had a nice lineup of speakers:</p>
<ul>
<li><a href="https://twitter.com/mepartoconmigo">Francisco Jordano</a> on <a href="https://docs.google.com/presentation/d/1cJXpLvk2qQ7MIEbcTjNn3uq67OuA_0kkxewZulajGvI/present">introducing Mozilla IOT meetup</a></li>
<li><a href="https://twitter.com/marcwalsh">Marc Walsh</a> on what to expect in the <a href="https://vimeo.com/154774646">IOT space</a> at <a href="http://mozillafestival.org/">MozFest 2016</a></li>
<li><a href="https://twitter.com/SamuelGiles_">Sam Giles</a> on <a href="https://docs.google.com/presentation/d/1ErECQTzBgirwN-qMXtE3hnPU1l6aYt5xc5SPD8z7i-0/present">the physical web and Project Magnet</a></li>
<li><a href="https://twitter.com/RebeccaAJones">Becky Jones</a> with just like magic - Design thinking meets the Internet of Things</li>
</ul>
<p>In addition to the amazing speakers above I wanted to thank <a href="https://twitter.com/Mandyc0907">Mandy</a> for the coordination, <a href="https://twitter.com/dietrich">Dietrich</a> and the devrel team for sponsoring the meetup and all the attendees.</p>
<h2><a name="whats-next" class="anchor" href="#whats-next"><span class="header-link"></span></a>What&#39;s next?</h2>
<p>We&#39;re super happy to receive feedback from the participants. If you happen to be in London during one our of next sessions, make sure you&#39;re attending and let us know what would you like this meetup to be?</p>
<p><img src="http://gu.illau.me/img/posts/mozilla-iot-meetup-london-october-2016/becky-jones-inspiring-talk.jpg" alt="The talented Becky Jones delivering an inspiring talk." title="The talented Becky Jones delivering an inspiring talk."></p>
<p>See you soon!</p>
]]></description><link>https://gu.illau.me/posts/mozilla-iot-meetup-london-october-2016/</link><guid isPermaLink="true">https://gu.illau.me/posts/mozilla-iot-meetup-london-october-2016/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Fri, 14 Oct 2016 00:00:00 GMT</pubDate></item><item><title><![CDATA[Landscapes in Virtual Reality]]></title><description><![CDATA[<p>Lately I experimented with virtual reality (VR) using <a href="https://vr.google.com/cardboard/">Google Cardboard</a>, my mobile phone and the amazing <a href="https://aframe.io/">A-Frame</a> library.</p>
<p>I gave it a try at drawing myself VR landscapes. It turns out VR textures are a form of <a href="https://en.wikipedia.org/wiki/Anamorphosis">anamorphosis</a>. Some artists like Dali drew such projections. To reconstitute a normal image, you need a special device, in our case a VR environment.</p>
<h2><a name="what-i-learnt" class="anchor" href="#what-i-learnt"><span class="header-link"></span></a>What I learnt</h2>
<p>VR is an immersive technology. To feel yourself part of a VR landscape, we apply a texture to the sky (see the <code>&lt;a-sky&gt;</code> element in A-Frame). A texture is a simple image that is distorted to the inside of a sphere.</p>
<p>Drawing a landscape for such a projection is really counter-intuitive, but here are some of my findings.</p>
<h2><a name="equirectangular-projection" class="anchor" href="#equirectangular-projection"><span class="header-link"></span></a>Equirectangular projection</h2>
<p>The easiest way to get started with drawing your own landscapes for VR is to start with a image (or paper, canvas...) twice as large than high (once scanned, 4096 × 2048 works pretty well).</p>
<p>In an <a href="https://en.wikipedia.org/wiki/Equirectangular_projection">equirectangular projection</a>, the top line of the image is distorted in such a way that it&#39;s merged in a single point. The same apply to the bottom. This means that the closer to the top or bottom an object is the smaller it will be rendered in the VR scene. its width will be squeezed.</p>
<p>The left and right sides of the image are merged together. To make it feel seamless, be sure to draw something that looks the same on both lateral sides or stitch lines may appear.</p>
<p><img src="http://gu.illau.me/img/posts/landscapes-in-virtual-reality/ratio.jpg" alt="The ideal ratio for a VR landscape texture"></p>
<h2><a name="the-horizon-line" class="anchor" href="#the-horizon-line"><span class="header-link"></span></a>The horizon line</h2>
<p>If you draw a horizontal line right in the middle of the image, this is going to be rendered as your horizon line when you place the camera in the centre of the sphere.</p>
<p>You can play with it. Make it slightly higher and the user will feel that they&#39;re trapped in the group (or maybe surrounded by mountains), making the final result a bit suffocating.</p>
<p>If you lower the horizon line, the user will think they&#39;re flying.</p>
<p><img src="http://gu.illau.me/img/posts/landscapes-in-virtual-reality/horizon-line.jpg" alt="The horizon line in VR"></p>
<h2><a name="4-sides" class="anchor" href="#4-sides"><span class="header-link"></span></a>4 sides</h2>
<p>Your field of view fits in roughly 1/4 of the image width. If you draw a single element larger than 1/4 of the width, it will force the user to look left and right to see it entirely, without being able to see it completely at once.</p>
<p>Be creative with it. Big elements like monuments or mountains should be larger than 1/4 of the width. Smaller elements like vehicles or trees should be much smaller.</p>
<p><img src="http://gu.illau.me/img/posts/landscapes-in-virtual-reality/4-sides.jpg" alt="The 4 sides of the user"></p>
<h2><a name="sphere-in-the-sky" class="anchor" href="#sphere-in-the-sky"><span class="header-link"></span></a>Sphere in the sky</h2>
<p>As explained above, the equirectangular projection will merge the top of the image to a single point. If you want to draw a circular object right above the user, draw a stripe going from the top of the image on a small fraction of the height. This will render as a perfect circle if the line is parallel to the top of the image.</p>
<p>Of course this principle applies to the bottom of the image too.</p>
<p><img src="http://gu.illau.me/img/posts/landscapes-in-virtual-reality/sun.jpg" alt="Drawing a sun in a virtual reality environment"></p>
<h2><a name="the-result" class="anchor" href="#the-result"><span class="header-link"></span></a>The result</h2>
<p>I uploaded my experiments. On your mobile, go to:
<a href="https://gmarty.github.io/vr-landscapes/">gmarty.github.io/vr-landscapes/</a>
Grab a Google Cardboard and insert your phone. You can change the landscape with the click button.</p>
<p><img src="http://gu.illau.me/img/posts/landscapes-in-virtual-reality/drawings.jpg" alt="My drawings"></p>
<p>Drawing for an equirectangular projection leads to results that are hard to predict. Another technique is to draw on the 6 sides of a cube and use a software to turn this cubic texture into an equirectangular projection, but I haven&#39;t tried myself.</p>
<p>If you want to give it a go, you can reuse the <a href="https://github.com/gmarty/vr-landscapes">code on Github</a>. Just replace the images by yours. Then, share your creations and ideas in the comments section below.</p>
]]></description><link>https://gu.illau.me/posts/landscapes-in-virtual-reality/</link><guid isPermaLink="true">https://gu.illau.me/posts/landscapes-in-virtual-reality/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Fri, 23 Sep 2016 00:00:00 GMT</pubDate></item><item><title><![CDATA[Building a Voice Assistant in JavaScript]]></title><description><![CDATA[<blockquote>
<p><strong>tl;dr:</strong> You can build a voice assistant in JavaScript with existing open source libraries but the result sucks.</p>
</blockquote>
<p>In the last couple of days, I explored the voice in the browser. Here are my findings.</p>
<h2><a name="whats-available" class="anchor" href="#whats-available"><span class="header-link"></span></a>What&#39;s available</h2>
<p>Most of the voice related libraries in  JavaScript that I found are simple wrappers around the <a href="https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html">Web Speech API</a>. Under the hood browsers use external services so I ruled out these libraries immediately as I wanted something that works offline.</p>
<p>What I found:</p>
<ul>
<li><a href="https://github.com/syl22-00/pocketsphinx.js">pocketsphinx.js</a> for voice recognition</li>
<li><a href="https://github.com/kripken/speak.js/">speak.js</a> for voice synthesis (several forks available)</li>
</ul>
<p>Both these projects are brought to the web thanks to Emscripten and asm.js.</p>
<h2><a name="building-a-not-so-intelligent-voice-assistant" class="anchor" href="#building-a-not-so-intelligent-voice-assistant"><span class="header-link"></span></a>Building a (not so) intelligent voice assistant</h2>
<p>Thanks to a discussion with my friend <a href="https://twitter.com/oncletom">Thomas</a> this weekend, <a href="http://cenode.io/">CENode.js</a> was brought to my attention. It&#39;s an open source project to enable human-machine conversation based on a human-friendly format. It can be used to simulate intelligence.</p>
<p>I had all the elements at hand to build a browser-based, offline voice assistant (Think Siri, OK Google, Amazon Echo...).</p>
<h2><a name="coding-or-rather-gluing" class="anchor" href="#coding-or-rather-gluing"><span class="header-link"></span></a>Coding (or rather gluing)</h2>
<p>Gluing all parts together was unsurprisingly easy. Pocketsphinx.js calls a function when the web worker has a final hypothesis:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="nx">worker</span><span class="p">.</span><span class="nx">onmessage</span> <span class="o">=</span> <span class="p">(</span><span class="nx">evt</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">evt</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">hyp</span> <span class="o">!==</span> <span class="kc">undefined</span> <span class="o">&amp;&amp;</span> <span class="nx">evt</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="kr">final</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">gotHypothesis</span><span class="p">(</span><span class="nx">evt</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">hyp</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">};</span>
</pre></div>
</code></pre>
<p>I can feed this hypothesis to CENode.js by creating a new card:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">gotHypothesis</span><span class="p">(</span><span class="nx">hypothesis</span><span class="p">)</span> <span class="p">{</span>
  <span class="kr">const</span> <span class="nx">card</span> <span class="o">=</span> <span class="s2">&quot;there is a nl card named &#39;{uid}&#39; that is to the agent &#39;agent1&#39; and is from the individual &#39;User&#39; and has the timestamp &#39;{now}&#39; as timestamp and has &#39;&quot;</span> <span class="o">+</span> <span class="nx">hypothesis</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/&#39;/g</span><span class="p">,</span> <span class="s2">&quot;\\&#39;&quot;</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;&#39; as content.&quot;</span><span class="p">;</span>
  <span class="nx">node</span><span class="p">.</span><span class="nx">add_sentence</span><span class="p">(</span><span class="nx">card</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</code></pre>
<p>Then I just have to wait until the deck is polled for new cards to my attention (my name is <code>User</code>). The new card contains the answer to my request and I can just do:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="nx">speak</span><span class="p">(</span><span class="nx">card</span><span class="p">.</span><span class="nx">content</span><span class="p">);</span>
</pre></div>
</code></pre>
<p>The function <code>speak</code> will call <code>espeak.synth()</code> of speak.js.</p>
<h2><a name="adding-a-grammar" class="anchor" href="#adding-a-grammar"><span class="header-link"></span></a>Adding a grammar</h2>
<p>This is it for the JavaScript code. But an important part is still missing. Pocketsphinx.js needs to be fed with a grammar and the pronunciation of all the words used in the grammar. This is used to reduce the scope of detected phrases. So I&#39;ll conveniently reuse all the possible requests supported by CENode.js.</p>
<p>Considering the <a href="http://cenode.io/demo/">CENode.js demo</a> about astronomy, here&#39;s a list of some requests that it can understand (let me know if I missed any):</p>
<pre><code><div class="highlight"><pre><span class="nx">What</span> <span class="nx">orbits</span> <span class="nx">Mars</span><span class="o">?</span>
<span class="nx">What</span> <span class="nx">does</span> <span class="nx">Titan</span> <span class="nx">orbit</span><span class="o">?</span>
<span class="nx">What</span> <span class="nx">is</span> <span class="nx">Saturn</span><span class="o">?</span>
<span class="nx">What</span> <span class="nx">is</span> <span class="nx">a</span> <span class="nx">star</span><span class="o">?</span>
<span class="nx">List</span> <span class="nx">instances</span> <span class="nx">of</span> <span class="nx">type</span> <span class="nx">planet</span>
</pre></div>
</code></pre>
<p>The first step is to compute all the possible permutations that make sense in English and that CENode.js will understand. I found 124 of them. This is the corpus I&#39;ll use in the next steps.</p>
<p>The grammar used by pocketsphinx.js is a Finite State Grammar. Think of a finite state machine where each state adds a word to the phrase:</p>
<pre><code><div class="highlight"><pre><span class="nx">s</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1">// s is the state with initial value 0.</span>

<span class="p">[]</span>    <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">What</span><span class="p">]</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">does</span><span class="p">]</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">Titan</span><span class="p">]</span> <span class="o">-&gt;</span> <span class="nx">orbit</span><span class="o">?</span>
<span class="nx">s</span> <span class="o">=</span> <span class="mi">0</span>    <span class="nx">s</span> <span class="o">=</span> <span class="mi">1</span>     <span class="nx">s</span> <span class="o">=</span> <span class="mi">2</span>     <span class="nx">s</span> <span class="o">=</span> <span class="mi">3</span>      <span class="nx">s</span> <span class="o">=</span> <span class="mi">4</span>
</pre></div>
</code></pre>
<p>The grammar for this simple phrase is:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="kr">const</span> <span class="nx">grammar</span> <span class="o">=</span> <span class="p">{</span>
  <span class="nx">numStates</span><span class="o">:</span> <span class="mi">5</span><span class="p">,</span>
  <span class="nx">start</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
  <span class="nx">end</span><span class="o">:</span> <span class="mi">4</span><span class="p">,</span>
  <span class="nx">transitions</span><span class="o">:</span> <span class="p">[</span>
    <span class="p">{</span> <span class="nx">from</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">to</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">word</span><span class="o">:</span> <span class="s2">&quot;WHAT&quot;</span> <span class="p">},</span>
    <span class="p">{</span> <span class="nx">from</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">to</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">word</span><span class="o">:</span> <span class="s2">&quot;DOES&quot;</span> <span class="p">},</span>
    <span class="p">{</span> <span class="nx">from</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">to</span><span class="o">:</span> <span class="mi">3</span><span class="p">,</span> <span class="nx">word</span><span class="o">:</span> <span class="s2">&quot;TITAN&quot;</span> <span class="p">},</span>
    <span class="p">{</span> <span class="nx">from</span><span class="o">:</span> <span class="mi">3</span><span class="p">,</span> <span class="nx">to</span><span class="o">:</span> <span class="mi">4</span><span class="p">,</span> <span class="nx">word</span><span class="o">:</span> <span class="s2">&quot;ORBIT&quot;</span> <span class="p">},</span>
    <span class="p">{</span> <span class="nx">from</span><span class="o">:</span> <span class="mi">4</span><span class="p">,</span> <span class="nx">to</span><span class="o">:</span> <span class="mi">4</span><span class="p">,</span> <span class="nx">word</span><span class="o">:</span> <span class="s2">&quot;&lt;sil&gt;&quot;</span> <span class="p">}</span>
  <span class="p">]</span>
<span class="p">};</span>
</pre></div>
</code></pre>
<p>The more phrases you add, the more complex it gets. For each state, pocketsphinx.js uses the grammar to figure out what is a possible next step. If your grammar is correct, you cannot end up with meaningless sentences.</p>
<p>I wrote a small script to build grammars from a corpus of phrases that I may publish if anyone is interested.</p>
<h2><a name="adding-pronunciation" class="anchor" href="#adding-pronunciation"><span class="header-link"></span></a>Adding pronunciation</h2>
<p>For each word in the corpus, pocketsphinx.js needs to know how to pronounce it.</p>
<p>I fed my corpus to <a href="http://www.speech.cs.cmu.edu/tools/lmtool-new.html">Sphinx Knowledge Base Tool</a>. I simply took the <code>*.dic</code> file from the gz archive, split it on line breaks and split again each line on tabs and I got something like:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="kr">const</span> <span class="nx">wordList</span> <span class="o">=</span> <span class="p">[</span>
  <span class="p">[</span><span class="s2">&quot;WHAT&quot;</span><span class="p">,</span><span class="s2">&quot;W AH T&quot;</span><span class="p">],</span>
  <span class="p">[</span><span class="s2">&quot;WHAT(2)&quot;</span><span class="p">,</span><span class="s2">&quot;HH W AH T&quot;</span><span class="p">],</span>
  <span class="p">[</span><span class="s2">&quot;ORBIT&quot;</span><span class="p">,</span><span class="s2">&quot;AO R B AH T&quot;</span><span class="p">],</span>
  <span class="p">[</span><span class="s2">&quot;MARS&quot;</span><span class="p">,</span><span class="s2">&quot;M AA R Z&quot;</span><span class="p">],</span>
  <span class="p">...</span>
</pre></div>
</code></pre>
<h2><a name="the-result" class="anchor" href="#the-result"><span class="header-link"></span></a>The result</h2>
<p>Et voila ! That&#39;s all I needed to get an astronomy centred voice assistant that can tell me what satellites orbit around what planets and other detailed infos. I have to say it&#39;s pretty cool, specially because I&#39;m a big fan of astronomy and I got this project done in under 2 days.</p>
<p>As a side note I tested it only on Firefox Nightly on my laptop. Results may differ on Chrome or on mobile devices.</p>
<p>The result though is not really convincing. First of all pocketsphinx.js voice recognition is bad. I can probably blame it on  my accent (I&#39;m French, remember), but it&#39;s so frustrating to say &quot;What orbits Saturn?&quot; hundreds of time with no results while my colleague got understood at the first try! The good thing at least is it can&#39;t return phrases out of the grammar, so it will always output something that makes sense.</p>
<p>CENode.js is also super limited and I don&#39;t really know how to improve it beyond the example provided (the format is well documented though). Some simple phrases, outside of the understanding scope, fail miserably:</p>
<pre><code><div class="highlight"><pre><span class="nx">What</span> <span class="nx">is</span> <span class="nx">orbited</span> <span class="nx">by</span> <span class="nx">Titan</span><span class="o">?</span> <span class="o">--&gt;</span> <span class="nx">fails</span>
<span class="nx">What</span> <span class="nx">does</span> <span class="nx">Titan</span> <span class="nx">orbit</span><span class="o">?</span>    <span class="o">--&gt;</span> <span class="nx">succeeds</span>
</pre></div>
</code></pre>
<p>But if you ask &quot;What is Saturn?&quot;, you get:</p>
<pre><code><div class="highlight"><pre><span class="nx">Saturn</span> <span class="nx">is</span> <span class="nx">a</span> <span class="nx">planet</span><span class="p">.</span> <span class="nx">Saturn</span> <span class="nx">orbits</span> <span class="nx">the</span> <span class="nx">star</span> <span class="s1">&#39;sun&#39;</span> <span class="nx">and</span> <span class="nx">is</span> <span class="nx">orbited</span> <span class="nx">by</span> <span class="nx">the</span> <span class="nx">moon</span> <span class="s1">&#39;Titan&#39;</span><span class="p">...</span>
</pre></div>
</code></pre>
<p>The passive voice does not seem to be supported in requests.</p>
<p>Finally, what is output by speak.js is pretty terrifying. Whatever the voice you choose, they all sound robotic. They have a cool retro feeling if that&#39;s what you&#39;re after (and you can argue that it works better for something related to astronomy and space), but they&#39;re far from the quality of commercial products.</p>
<h2><a name="going-further" class="anchor" href="#going-further"><span class="header-link"></span></a>Going further</h2>
<p>This experimentation was limited in time so I didn&#39;t want to spend too much on it, but if I had had a real project to build, I&#39;d had seriously looked at:</p>
<ul>
<li>Finding better language packages for pocketsphinx.js.</li>
<li>Building better grammar files for pocketsphinx.js.</li>
<li>Using CENode.js&#39; advanced features.</li>
<li>Using better voice packages in espeak.js.</li>
<li>Supporting more languages outside of English</li>
</ul>
<p>I don&#39;t think it&#39;s worth sharing the code that&#39;s messy and I&#39;ll leave it as an exercise to the reader, unless somebody is really interested.</p>
<p>What I can share though is the FSG generator from a corpus. It needs some cleaning but the code can run on node or in the browser.</p>
<p>There&#39;s probably tons of mistakes and approximations in this post, I&#39;m by no means a voice expert, so please correct me if need be. Also if you have any ideas on how to improve it or if I missed an existing library, please do let me know in the comments. Thanks!</p>
]]></description><link>https://gu.illau.me/posts/building-a-voice-assistant-in-javascript/</link><guid isPermaLink="true">https://gu.illau.me/posts/building-a-voice-assistant-in-javascript/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Tue, 17 May 2016 00:00:00 GMT</pubDate></item><item><title><![CDATA[Welsh keyboard for Firefox OS]]></title><description><![CDATA[<p>I recently worked on a way to automatise the <a href="https://github.com/gmarty/wordlist-generator">creation of dictionaries for word suggestions when typing in Firefox OS</a> (More on that one day, hopefully). As a test case, I generated a Welsh keyboard, as it is one of the few languages I know a little that didn&#39;t have a keyboard in Firefox OS (<a href="http://gu.illau.me/posts/japanese-keyboard-for-firefox-os/">Japanese keyboard</a> is another exception though). Typing on a mobile is hard enough, so word suggestions and autocorrect are keys for a better experience.
If you speak Welsh, even a little, and use Firefox OS on the master branch, please help us to test the keyboard and assess its quality.</p>
<h2><a name="install-and-activate-the-welsh-keyboard" class="anchor" href="#install-and-activate-the-welsh-keyboard"><span class="header-link"></span></a>Install and activate the Welsh keyboard</h2>
<p>Make sure you are using the latest version of B2G. If your device is a Flame or a Sony Z3C running Firefox OS, then you should get new updates automatically. Otherwise, you&#39;ll want to flash the latest version.</p>
<p>Here&#39;s a quick demo of how to install it on your device.</p>
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/MWlPnWrX7AE?rel=0&amp;showinfo=0" frameborder="0" allowfullscreen></iframe>

<h2><a name="test-the-keyboard" class="anchor" href="#test-the-keyboard"><span class="header-link"></span></a>Test the keyboard</h2>
<p>The dictionary builtin in the keyboard is based on <a href="https://cy.wikipedia.org/wiki/Hafan">Wikipedia in Welsh</a>, which has, I believe, a <a href="https://en.wikipedia.org/wiki/List_of_Wikipedias">decent number of pages</a> (around 64,000 articles, ranking it 64th biggest language out of 290).</p>
<p>From my experience, the results is very satisfying. I found the words suggested by this keyboard very useful. But my knowledge of Welsh is very limited, so it may not be completely helpful to a fluent speaker (or writer rather). In particular, I&#39;m afraid that it may be too formal or lack slang or colloquial expressions, frequently used in SMS or social networks.</p>
<h2><a name="we-need-you" class="anchor" href="#we-need-you"><span class="header-link"></span></a>We need you!</h2>
<p>If you speak Welsh, please, try it for yourself. I&#39;d love to hear your feedback and if you have any comments, please use the field below, or reach me on Twitter at <a href="https://twitter.com/g_marty">@g_marty</a>. If this method is proved to give good results, I&#39;d love to give it a go at producing dictionary in more languages.</p>
<p><em>Diolch!</em></p>
]]></description><link>https://gu.illau.me/posts/welsh-keyboard-for-firefox-os/</link><guid isPermaLink="true">https://gu.illau.me/posts/welsh-keyboard-for-firefox-os/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Wed, 22 Jul 2015 00:00:00 GMT</pubDate></item><item><title><![CDATA[Japanese keyboard for Firefox OS]]></title><description><![CDATA[<blockquote>
<p><strong>tl;dr:</strong> You can&#39;t efficiently type in Japanese on a Firefox OS device, unless you buy a fx0 device or you build Gaia yourself and are very patient!</p>
</blockquote>
<p>Firefox OS is targeting a global audience. You can set your interface in 90 different languages and there are over 70 language specific keyboards!
But developing a keyboard is more challenging for some languages than others and Japanese is one of them.</p>
<p>I won&#39;t give much details about why is a Japanese IME hard to implement, but the main reason is that there is a massive amount of  suggestions that need to be stored on the device somehow. In Japanese, any word can be usually written in several different ways. Storing such a dictionary can cause serious issues on low-end devices with limited memory and processing power.</p>
<p>But that&#39;s not a reason to just giving up typing in Japanese on Firefox OS.</p>
<h2><a name="fx0" class="anchor" href="#fx0"><span class="header-link"></span></a>fx0</h2>
<p>Earlier this year, KDDI released the <a href="http://au-fx.kddi.com/products/">fx0</a>, a Firefox OS powered device, on the Japanese market. This phone comes with a Japanese keyboard called <a href="http://www.omronsoft.co.jp/product_text/iwnn-ime-for-firefox-os/">iWnn IME</a> and developed by Omron Software.</p>
<p>The implementation is efficient and powerful. It comes with many options to configure the keyboard to perfectly suit your needs and habits. Such a high quality is not really surprising as the same keyboard is already available on other platforms (Android notably).</p>
<p>This keyboard has been open sourced in the <a href="https://github.com/mozilla-japan/iwnn-ime-sample">iwnn-ime-sample</a> Github repo. However the licence is expiring on 30th September 2015 (not sure what&#39;s happening afterwards).</p>
<p>The readme file claims it&#39;s possible to flash it on a Flame running Firefox OS v2.0. So I tried and everything is working, except for the core feature: the words suggestion. To achieve this in an optimised way, a local server running on the device is used to query words. This part doesn&#39;t work. The keyboard however can still be used to input kana, but you won&#39;t get any word suggestions.</p>
<p>I then flashed it on a master (tried both on a Flame and Sony Z3C). I encountered the same issue with the words suggestion together with other few minor bugs. But if you use it as a kana only keyboard, then this is probably acceptable.</p>
<p>Drop me a comment below if you need help on how to install it.</p>
<p><img src="https://lh3.googleusercontent.com/LdqNqF5ny4xMumE8m9jSZQMrujhFDIGZBA1SUoxYAU0u=s0" alt="iWnn IME for Firefox OS" title="iWnn IME for Firefox OS"></p>
<h2><a name="gaia-jp-kanji-keyboard" class="anchor" href="#gaia-jp-kanji-keyboard"><span class="header-link"></span></a>Gaia <code>jp-kanji</code> keyboard</h2>
<p>There is already a <a href="https://github.com/mozilla-b2g/gaia/tree/master/apps/keyboard/js/imes/jskanji">Japanese keyboard in Gaia</a>. To install it, you must build Gaia yourself and flash your device. Here is the suggested command line:</p>
<pre><code class="lang-bash"><div class="highlight"><pre><span class="nv">$ GAIA_KEYBOARD_LAYOUTS</span><span class="o">=</span>en,jp-kanji make reset-gaia
</pre></div>
</code></pre>
<p>Once flashed, you must enable the new keyboard in <code>Settings</code> &gt; <code>Keyboards</code>  &gt; <code>Select keyboards</code>.</p>
<p>This IME comes with words suggestion, but it is neither as user-friendly nor as fast as the iWnn IME one.
That is the reason why it is not available to current builds. I love how the design fits in the Firefox OS UI though.</p>
<p>There are plans to build a better Japanese keyboard for Firefox OS, but nothing has happened yet.</p>
<p><img src="https://lh3.googleusercontent.com/HZ53_An9tjhWPoveJ4XCbOLdQ-DKCwOxY1hTrcneicTH=s0" alt="Gaia jp-kanji Keyboard" title="Gaia jp-kanji Keyboard"></p>
<p>So unfortunately, there is no easy way to install a Japanese keyboard on Firefox OS, but we&#39;re working on it!
If you&#39;re wondering what I&#39;m doing with my device, I use the iWnn IME keyboard, but because of its limitations, I avoid typing in Japanese on my mobile whenever I can :-)</p>
]]></description><link>https://gu.illau.me/posts/japanese-keyboard-for-firefox-os/</link><guid isPermaLink="true">https://gu.illau.me/posts/japanese-keyboard-for-firefox-os/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Mon, 29 Jun 2015 00:00:00 GMT</pubDate></item><item><title><![CDATA[The Physical Web]]></title><description><![CDATA[<p>&quot;Walk up and use anything&quot; is the promise of the <a href="http://google.github.io/physical-web/">Physical Web</a>.
It is an open source project started by Google that allows you to access to online resource via physical objects.</p>
<h2><a name="the-concept" class="anchor" href="#the-concept"><span class="header-link"></span></a>The concept</h2>
<p>The physical web is based on hardware beacons that broadcast data using Bluetooth Low Energy (BLE) without the need to pair the device. In this case, the data is an URL. For now, it requires you to install an app on your mobile device. This app will scan in the background the surroundings for beacons and will inform you whenever you come across one. You&#39;ll then be presented with a list of URL, one per beacon. If the project is successful, this feature may be built-in your mobile OS in the future, thus removing the need for an external app.</p>
<p>There are already some beacons available. I bought a <a href="https://www.blesh.com/product/blesh-pack-3-beacons/">physical web pack from Blesh</a>, but there are more <a href="http://store.twocanoes.com/collections/physical-web-beacons">providers</a>. You can also turn your laptop or other devices into beacons using the <a href="https://github.com/google/uribeacon/blob/master/beacons/README.md">projects listed here</a>. There&#39;s even an implementation for Node.js.</p>
<p><img src="https://lh3.googleusercontent.com/THMrcnE8cMC3H8ymn_HVIp1uyGZ7I58PcEiJfndWy9Ci=s600" alt="The Physical Web beacons by Blesh" title="The Physical Web beacons by Blesh"></p>
<p>These projects allow you do to both reading and advertising. The app required to read physical web beacons is available on Android and iOS.</p>
<h2><a name="mdns-support" class="anchor" href="#mdns-support"><span class="header-link"></span></a>mDNS support</h2>
<p>Advertising URL on a local network is also supported thanks to <a href="https://github.com/google/physical-web/blob/master/documentation/mDNS_Support.md">mDNS</a>. It works essentially by using a <code>_http._tcp</code> service with an optional TXT record for the path.
As noted on the website, the advantage over BLE is that reading is limited to the devices connected to the local network and won&#39;t leak to unauthorised people. It also enables broadcasting longer URLs.</p>
<h2><a name="criticism" class="anchor" href="#criticism"><span class="header-link"></span></a>Criticism</h2>
<p>This project is really interesting because it helps discovering content useful locally using the P2P web.
Unfortunately I wish the concept had been taken further and instead of advertising URL that requires an Internet connection to be visited, it could have advertised content stored locally, on a embedded server. You can always advertise URL from a local network using mDNS, but how to make sure the visitors are connected to the correct local network if you use BLE?
I understand it is probably in Google&#39;s own interest to promote Internet and force users to remain connected at all time. They&#39;re not making money on local content completely disconnected from the Internet.</p>
<p>Also it looks like the main use case is to advertise products and services. I strongly think the web and the Internet of things shouldn&#39;t be about consumption and profit only. The P2P Web should reinforce local communities and make people to help each other. It should enable you to connect with local people (It sounds cheesy, I know...).
Anyway, the web being what you make of it, I still think the physical web is an interesting project.</p>
<h2><a name="next-step" class="anchor" href="#next-step"><span class="header-link"></span></a>Next step</h2>
<p>I&#39;ve started building an app to implement the <a href="https://github.com/gmarty/fxos-physical-web">Physical Web on Firefox OS</a>. It will allow you to read and act as a physical web beacons. At the moment BLE is not implemented on B2G, but it&#39;s coming to v3, later this year. So in the meantime, I&#39;m relaying on mDNS.</p>
<p>I&#39;ve set up one of the physical web beacons to advertise the URL of this blog. I&#39;m carrying this beacon with me most of the time. So if you come across it in the streets of London, you&#39;ll know I&#39;m not far away!</p>
]]></description><link>https://gu.illau.me/posts/the-physical-web/</link><guid isPermaLink="true">https://gu.illau.me/posts/the-physical-web/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Wed, 11 Mar 2015 00:00:00 GMT</pubDate></item><item><title><![CDATA[Privacy and Google Analytics]]></title><description><![CDATA[<h2><a name="the-problem" class="anchor" href="#the-problem"><span class="header-link"></span></a>The problem</h2>
<p>After reading a post comparing analytics solutions, I realised most people ignore that Google Analytics can be fine tuned to comply with stricter privacy policies. In this post, I&#39;ll share the solutions I implemented to keep using Google Analytics without compromising my visitors (a.k.a. yourself) privacy.</p>
<p>Please note that the code only relates to the latest <code>analytics.js</code> API. Look for support pages for older versions of Google Analytics.</p>
<h2><a name="the-solutions" class="anchor" href="#the-solutions"><span class="header-link"></span></a>The solutions</h2>
<h3><a name="disable-data-sharing" class="anchor" href="#disable-data-sharing"><span class="header-link"></span></a>Disable data sharing</h3>
<p>By default, the data collected from Google Analytics are shared across several services like:</p>
<ul>
<li>Other Google products like AdWords</li>
<li>Industries aggregate trends that allow comparing your result with web sites in the same sector</li>
<li>Technical support...</li>
</ul>
<p>Though this data sharing should be harmless most of the time, you can disable it in your account settings. You can read more about it on the <a href="https://support.google.com/analytics/answer/1011397?hl=en">data sharing settings</a> support page.</p>
<h3><a name="anonymise-ip-address" class="anchor" href="#anonymise-ip-address"><span class="header-link"></span></a>Anonymise IP address</h3>
<p>Google Analytics has a built-in feature to anonymise IP address (see this <a href="https://support.google.com/analytics/answer/2763052?hl=en">help page</a> for details). When enabled, the last few digits of the visitor&#39;s IP address are set to 0 (IPv6 is supported).
In theory it is not possible for Google to map an anonymised IP address to a specific user. Also, according to their documentation, the complete IP address is never logged.</p>
<p>However, I read the relevant document carefully and noticed it&#39;s not very clear to me if Google logs the IP address when the <code>analytics.js</code> file is requested from their server. If you&#39;re a bit paranoid, you may decide not to trust Google here. In such case, you&#39;ll want to proxy it on your own domain and refresh it as often as possible. I haven&#39;t tried myself, but if you&#39;re doing that, let me know as I&#39;d love to read more.</p>
<p>Obviously, the down side of this setting is you get a less accurate geographic report as it is based on the IP address. But who needs a granularity to the level of a city?</p>
<h3><a name="implement-an-opt-out-mechanism" class="anchor" href="#implement-an-opt-out-mechanism"><span class="header-link"></span></a>Implement an opt-out mechanism</h3>
<p>You can easily give your users the ability to deactivate tracking. Just create a setting in your app that sets the following property to <code>true</code>:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="nb">window</span><span class="p">[</span><span class="s1">&#39;ga-disable-UA-XXXXXX-Y&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span> <span class="c1">// Replace UA-XXXXXX-Y by your Google Analytics ID</span>
</pre></div>
</code></pre>
<p>You can persist this setting in your user account, so that her preference is is kept whatever the device she&#39;s using to access your website. But for performance reason, I recommend not to load Google Analytics at all when your user has opted out.
You can read more about <a href="https://developers.google.com/analytics/devguides/collection/analyticsjs/advanced#optout">user opt-out</a> in the help pages.</p>
<h3><a name="dont-use-cookies" class="anchor" href="#dont-use-cookies"><span class="header-link"></span></a>Don&#39;t use cookies</h3>
<p>Though not directly related to privacy, not setting cookies is likely to increase your visitors confidence while removing the need to display a message related to the <a href="https://en.wikipedia.org/wiki/HTTP_cookie#EU_cookie_directive">EU cookie directive</a>.</p>
<p>Instead of cookies, use local storage for storing the visitor identifier used by Google Analytics, the so called <code>clientId</code> parameter. This technique has a beneficial aspect on performance as well. The browser won&#39;t send all the cookie detail with every request made to an asset located in the same domain as the page.</p>
<p>Here is the code used in this blog:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="nx">ga</span><span class="p">(</span><span class="s1">&#39;create&#39;</span><span class="p">,</span> <span class="s1">&#39;UA-XXXXXX-Y&#39;</span><span class="p">,</span> <span class="p">{</span> <span class="c1">// Use your own ID!</span>
  <span class="s1">&#39;storage&#39;</span><span class="o">:</span> <span class="s1">&#39;none&#39;</span><span class="p">,</span>
  <span class="s1">&#39;clientId&#39;</span><span class="o">:</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">&#39;gaClientId&#39;</span><span class="p">)</span>
<span class="p">});</span>
<span class="nx">ga</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">tracker</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">&#39;gaClientId&#39;</span><span class="p">,</span> <span class="nx">tracker</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;clientId&#39;</span><span class="p">));</span>
<span class="p">});</span>
<span class="nx">ga</span><span class="p">(</span><span class="s1">&#39;send&#39;</span><span class="p">,</span><span class="s1">&#39;pageview&#39;</span><span class="p">)</span>
</pre></div>
</code></pre>
<h3><a name="comply-with-do-not-track" class="anchor" href="#comply-with-do-not-track"><span class="header-link"></span></a>Comply with Do Not Track</h3>
<p>The DNT is not only exposed to the client as a HTTP header but also as a property on the <code>navigator</code> object: <code>navigator.doNotTrack</code>. This returns:</p>
<ul>
<li><code>&#39;1&#39;</code> (the visitor does not want to be tracked)</li>
<li><code>&#39;0&#39;</code> (the visitor wants to be tracked)</li>
<li><code>null</code> or <code>&#39;unspecified&#39;</code> (the visitor tells nothing about her preference)</li>
</ul>
<p>You can wrap the code responsible for loading Google Analytics in a <code>if</code> statement like I do in this blog (examine the source for yourself if you don&#39;t believe me!):</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="k">if</span> <span class="p">(</span><span class="nx">navigator</span><span class="p">.</span><span class="nx">doNotTrack</span> <span class="o">!==</span> <span class="s1">&#39;1&#39;</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// Load Google Analytics and track user.</span>
<span class="p">}</span>
</pre></div>
</code></pre>
<h3><a name="force-ssl" class="anchor" href="#force-ssl"><span class="header-link"></span></a>Force SSL</h3>
<p>This blog is hosted on Github pages. Unfortunately, https is not (yet?) supported. The least I could do was to force the <code>analytics.js</code> file and the beacon to be respectively received and sent encrypted.
More info about the <a href="https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#forceSSL"><code>forceSSL</code> setting</a> is available.</p>
<h2><a name="the-challenge" class="anchor" href="#the-challenge"><span class="header-link"></span></a>The challenge</h2>
<p>Some of the solutions presented here depend on your level of trust. I decided to trust Google even if I can never have the certitude that they really do what they say they do.
So after all, your trust level may be different and you can decide whether to apply the solutions mentioned above or turn to other analytics services, like <a href="http://piwik.org/">Piwik</a>.</p>
<p>Also, I would have loved to see Google making some of these options easier. For example, support of DNT could have been made an option in the account settings. Also, we can&#39;t create a custom IP masking function to push anonymisation even further.</p>
<p>Google Analytics offer some very basic privacy aware options, but they should offer more!</p>
]]></description><link>https://gu.illau.me/posts/privacy-and-google-analytics/</link><guid isPermaLink="true">https://gu.illau.me/posts/privacy-and-google-analytics/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Mon, 08 Dec 2014 00:00:00 GMT</pubDate></item><item><title><![CDATA[Experimenting with serverless apps]]></title><description><![CDATA[<p>Servers are inherent to the web. The recent <a href="https://unhosted.org/">unhosted</a> movement tends to reduce their importance to give the power back to the client applications.</p>
<p>But is a completely serverless web really achievable?</p>
<p>Let&#39;s stay very basic for now and let&#39;s not consider issues like security or version update.</p>
<p>(Note: the content of this post was inspired and developed during an <a href="http://lanyrd.com/2014/decentralizejs/">event</a> and a <a href="http://www.meetup.com/ORG-London/events/202557812/">hack day</a> I attended recently.)</p>
<h2><a name="a-dystopian-example" class="anchor" href="#a-dystopian-example"><span class="header-link"></span></a>A dystopian example</h2>
<p>Imagine you are demonstrating against the government in place in your country. They are powerful and control the communication. In order to slow and confuse you they cut all network. Without internet you can&#39;t communicate with your peers and can&#39;t organise the movement.</p>
<p>You want to be able to send and receive information. How can you do that when all you have is a web enabled device and no network?</p>
<h2><a name="distribute-serverless-apps" class="anchor" href="#distribute-serverless-apps"><span class="header-link"></span></a>Distribute serverless apps</h2>
<p>Let&#39;s see if it&#39;s possible to distribute apps from device to device, using web technologies only but without servers.</p>
<h3><a name="file-uri-scheme" class="anchor" href="#file-uri-scheme"><span class="header-link"></span></a>file:// URI scheme</h3>
<p>The most obvious and direct approach is to create a file on your computer and open it in your browser using the <code>file://</code> protocol.
It works for simple documents but comes with a huge list of limitations:</p>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Same-origin_policy_for_file:_URIs">Same-origin policy limitations</a></li>
<li>Can&#39;t open a <code>file://</code> URI from a <code>http://</code> web page</li>
<li>The reference to the document is local and can&#39;t be shared</li>
<li>Does it even work on mobile browsers?</li>
</ul>
<h3><a name="data-uri" class="anchor" href="#data-uri"><span class="header-link"></span></a>Data URI</h3>
<p>Data URIs allow to package all of your app logic and resources in a string format that your browser can recognise and execute.
Rather than using a URL as a reference to a content located somewhere, the URL contains everything. The address IS the content.</p>
<p>A very simple example is the following:
<a href="data:text/html;utf-8,%3Cb%3EHello%2C%20world!%3C%2Fb%3E">data:text/html;utf-8,&lt;b&gt;Hello, world!&lt;/b&gt;</a></p>
<p>Clicking on the link will display the text &quot;Hello, world!&quot; in bold. Everything is self-contained.</p>
<p>There is a limitation, however, in the number of characters such a URI can contain: no more than 65535. Here is the function I use to convert HTML code to data URI:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">dataUriEncode</span><span class="p">(</span><span class="nx">string</span><span class="p">)</span> <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">encoded</span> <span class="o">=</span> <span class="s1">&#39;data:text/html;utf-8,&#39;</span> <span class="o">+</span> <span class="nb">encodeURIComponent</span><span class="p">(</span><span class="nx">string</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">encoded</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;=</span> <span class="mi">65535</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="s1">&#39;The string generated is too long.&#39;</span><span class="p">)</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="nx">encoded</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</code></pre>
<h2><a name="abusing-data-uris" class="anchor" href="#abusing-data-uris"><span class="header-link"></span></a>Abusing data Uris</h2>
<p>Let&#39;s now abuse this simple mechanism to create web pages and distribute them without server.</p>
<p>For the sake of an example, I shamelessly stole <a href="http://www.p01.org/releases/WOLF1K/">WOLF1K</a>, a clone of Wolfenstein in JavaScript that only weights 1K. Here is the complete source code of the app that I&#39;ll try to distribute:</p>
<pre><code><div class="highlight"><pre><span class="nx">data</span><span class="o">:</span><span class="nx">text</span><span class="o">/</span><span class="nx">html</span><span class="p">;</span><span class="nx">utf</span><span class="o">-</span><span class="mi">8</span><span class="p">,</span><span class="o">&lt;</span><span class="nx">title</span><span class="o">&gt;</span><span class="nx">WOLF1K</span><span class="o">&lt;</span><span class="err">/title&gt;&lt;canvas id=c&gt;&lt;/canvas&gt;&lt;script&gt;E=&quot;A=document.body.children.c;B=A.getContext(&#39;2d&#39;~=1$&amp;31$&amp;992(E&amp;19)?1;    n=@nB#[A#)onkeyup=0};D=[setInterval(@=innerWidth-30;A.heigh@/2;    n=@n=[t,n,S,8+$*S&amp;8)|(X+y+t*s+t*c8&amp;7]){w=X=x=;v=y=;z=2]z+n/@ a=s=yG=F,r=u;a=c=X    ;$~)F&lt;G?(F,F1/uS=c/u):(G,G1/rS=32*s/r)}    n=@i&lt;15;i++){2];j=38;i?1X=(+,;Y=(,+;ji?random(8-42]=(b-t/16+9.42%6.28)-3.14;z-atan2(Y-=v,X-=w~i&amp;&amp;&gt;.5?=[sqrt(X*X+Y*Y),@/2-@*b,i,0,++n]    D.sort(+x[-y[}~n)    a=[,a/@ F=@/2//[,c=8,u=v=+1=[3]=c=1,@,0%)&#39;):a!ca)    &#39;+v+&#39;%)&#39;atob(&#39;CBF+/p6f9AC9bsP/w/dqvdvb2NvD29sb&#39;),y=8,@/4,b!yb)d&gt;&gt;y&amp;1,v),9)]&quot;;&quot;@A.widthMath.cos(b)B[i][function(x,y){B.fillStyle=&#39;hsl(&#39;+D[n][2]+&#39;1,99%,%=1;u=a&lt;0?-a:a,F=(a&lt;0?d:1-d)/u;onkeydownMath.sin(b).charCodeAt(x++%73)    for(?B.fillRect(a,b,u:A[j]-A[j+2];D[n]A[x.which]=--;*t/8;x|=y&lt;&lt;5;,i=0;Math.+=0]1.1,return)*b=,d=:0}F/41]t= -.5,!-=F;#[n]=$(x~);,x&quot;.replace(/.([%-}]+)/g,function(x,y){E=E.split(x[0]).join(y)});eval(E)&lt;/script&gt;</span>
</pre></div>
</code></pre>
<p>I will now run this web page and distribute it to other devices without using a server.
The tests below are based on the following browser/OS configuration:</p>
<ul>
<li>Firefox OS</li>
<li>Firefox for Android</li>
<li>Chrome for Android</li>
<li>Firefox and Chrome desktop (on Ubuntu ; where it makes sense)</li>
</ul>
<p>Feel free to test and send me the results on other OS configurations.</p>
<h2><a name="distribution-strategies" class="anchor" href="#distribution-strategies"><span class="header-link"></span></a>Distribution strategies</h2>
<h3><a name="link" class="anchor" href="#link"><span class="header-link"></span></a>Link</h3>
<p>This is the easier way of sharing a data URI app and it works everywhere! Just click the link below to start the app:
<a href="data:text/html;utf-8,%3Ctitle%3EWOLF1K%3C%2Ftitle%3E%3Ccanvas%20id%3Dc%3E%3C%2Fcanvas%3E%3Cscript%3EE%3D%22A%3Ddocument.body.children.c%3BB%3DA.getContext('2d'~%06%3D%03%0F1%12%18%24%2631%19%24%26992%19(E%08%2619)%3F1%1C%3B%09n%3D%40%13n%10B%23%5B%17%17%17A%23%16)onkeyup%3D%03%0F0%7D%3BD%3D%5BsetInterval(%03%40%3DinnerWidth-30%3BA.heigh%1F%40%2F2%3B%09n%3D%40%13n%10%0E%3D%5Bt%2Cn%2CS%2C8%2B%24*S%268)%7C(X%2By%2Bt*s%2Bt*c%198%267%5D)%7Bw%3DX%3Dx%3D%02%16%3Bv%3Dy%3D%02%1E%3Bz%3D%022%5D%12%1Az%2Bn%2F%40%20a%3Ds%3D%07%1By%05G%3DF%2Cr%3Du%3Ba%3Dc%3D%01%1BX%05%09%3B%06%24~)F%3CG%3F(%1FF%2CF%151%2Fu%7F%15S%3Dc%2Fu)%3A(%1FG%2CG%151%2Fr%7F%15S%3D32*s%2Fr)%7D%09n%3D%40%13i%3C15%3Bi%2B%2B)%7B%1A%022%5D%3Bj%3D38%3B%1Fi%3F1%0CX%3D%02%16%15%06(%02%16%2B%01%11%2C%02%1E%19%01%11%3BY%3D%02%1E%15%06(%02%16%2C%02%1E%2B%07%11%19%07%11%3Bj%10%1Fi%3F%14random(%198-4%0C%022%5D%3D(b-t%2F16%2B9.42%256.28)-3.14%3B%1Az-%14atan2(Y-%3Dv%2CX-%3Dw~i%26%26%01%3E.5%3F%0E%3D%5B%14sqrt(X*X%2BY*Y)%2C%40%2F2-%40*b%2Ci%2C0%2C%2B%2Bn%5D%1C%09D.sort(%03%18%2Bx%5B%16-y%5B%16%7D~n%10)%09a%3D%0E%5B%1E%2C%1Aa%2F%40%20F%3D%40%2F2%2F%01%2F%0E%5B%1A%16%2Cc%3D8%2Cu%3Dv%3D%1D%2B1%7F%3D%0E%5B3%5D%7F%0B%3Dc%3D1%2C%40%2C%040%25)')%3Aa!c%10a%15%1D)%09%04'%2Bv%2B'%25)'%1Batob('CBF%2B%2Fp6f9AC9bsP%2Fw%2Fdqvdvb2NvD29sb')%08%2Cy%3D8%2C%1A%40%2F4%2Cb!y%10b%15%1D)d%3E%3Ey%261%0B%2Cv)%1C%2C9)%5D%22%3B%22%40A.width%01Math.cos(b)%02B%5Bi%5D%5B%03function(x%2Cy)%7B%04B.fillStyle%3D'hsl('%2BD%5Bn%5D%5B2%5D%2B'1%2C99%25%2C%05%25%3D1%3Bu%3Da%3C0%3F-a%3Aa%2CF%3D(a%3C0%3Fd%3A1-d)%2Fu%3B%06onkeydown%07Math.sin(b)%08.charCodeAt(x%2B%2B%2573)%09for(%0B%3FB.fillRect(a%2Cb%2Cu%0C%3AA%5Bj%5D-A%5Bj%2B2%5D%3B%0ED%5Bn%5D%0FA%5Bx.which%5D%3D%10--%3B%11*t%2F8%12%3Bx%7C%3Dy%3C%3C5%3B%13%2Ci%3D0%3B%14Math.%15%2B%3D%160%5D%171.1%2C%18return%19)*%1Ab%3D%1B%2Cd%3D%1C%3A0%7D%1DF%2F4%1E1%5D%1Ft%3D%20-.5%2C!-%3DF%3B%23%5Bn%5D%3D%24(x~)%3B%7F%2Cx%22.replace(%2F.(%5B%25-%7D%5D%2B)%2Fg%2Cfunction(x%2Cy)%7BE%3DE.split(x%5B0%5D).join(y)%7D)%3Beval(E)%3C%2Fscript%3E">WOLF1K</a></p>
<p>Obviously a link means that a web page is required and possibly a server to host it.</p>
<h3><a name="emails" class="anchor" href="#emails"><span class="header-link"></span></a>Emails</h3>
<p>I haven&#39;t been able to send or receive a data URI link from an email. This is due to security reasons.
What works though is to paste the source code of the app and ask the recipient to copy and paste it in her browser address bar.</p>
<h3><a name="sms" class="anchor" href="#sms"><span class="header-link"></span></a>SMS</h3>
<p>Likewise, copy/pasting content from a text message is the only way to use SMS to send such an app.</p>
<h3><a name="bluetooth-and-nfc" class="anchor" href="#bluetooth-and-nfc"><span class="header-link"></span></a>Bluetooth and NFC</h3>
<p>This methods were a major disappointment to me. I was really hoping that one can send a data URI app from a device to another. But it doesn&#39;t work due to &quot;Can&#39;t open media type&quot; (Bluetooth) and &quot;Unknown tag type&quot; (NFC) errors.
That said, I suspect it can be fixed on Firefox OS.</p>
<h3><a name="qr-code" class="anchor" href="#qr-code"><span class="header-link"></span></a>QR Code</h3>
<p>1084 characters are too much for QR Code and make it impossible to decode.</p>
<p>This is sad because this prevents us from using printed material to distribute apps.</p>
<p>If you don&#39;t believe me, try to scan that:
<img src="https://lh3.googleusercontent.com/b60QnpsZFq0_-xrxhrypM9Tj_rMjoSHWNZjshbtz3aq9=s0" alt="WOLF1K" title="WOLF1K.png"></p>
<h3><a name="wifi-direct" class="anchor" href="#wifi-direct"><span class="header-link"></span></a>Wifi Direct</h3>
<p>This is a protocol to discover and communicate with devices connected to the same Wifi network, even if there is no Internet connection.
Though it is currently implemented in Firefox OS and Android, this needs to be tested to see if it&#39;s possible to send data URI web app via this channel.</p>
<h2><a name="bookmarking-and-adding-to-homescreen" class="anchor" href="#bookmarking-and-adding-to-homescreen"><span class="header-link"></span></a>Bookmarking and adding to homescreen</h2>
<p>Once the app received is running on your browser, you want to bookmark it so that you can use it later.</p>
<p>Desktop browsers permit bookmarking data URI apps, but not to add to homescreen.</p>
<p>On mobile browsers, things are slightly more complex:</p>
<ul>
<li>Firefox for Android: bookmark and add to homescreen both work OK</li>
<li>Chrome for Android: can bookmark but app added to homescreen can&#39;t be opened (&quot;App isn&#39;t installed&quot; error message)</li>
<li>Firefox OS: bookmark is replaced by add to homescreen, but this feature doesn&#39;t work as of version 2.1 with data URI (Here again I believe this can be fixed)</li>
</ul>
<h2><a name="so-what-now" class="anchor" href="#so-what-now"><span class="header-link"></span></a>So what now?</h2>
<p>Ironically the only methods that work are the server based one (link, email, text messages). Distributing web documents encoded in data URI without a server is a bit tricky at the moment. OS UI don&#39;t always allow creating, sharing or opening such apps.
I understand this falls in a particular edge case, but if data URI apps were supported like URL based apps, things would be easier.</p>
<p>Now I&#39;d love to see a discussion happening around what does the web need to achieve this. Are they any specifications currently being standardised that would go in this direction?</p>
<p>Let&#39;s move things forward and get a truly serverless web!</p>
]]></description><link>https://gu.illau.me/posts/experimenting-with-serverless-apps/</link><guid isPermaLink="true">https://gu.illau.me/posts/experimenting-with-serverless-apps/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Thu, 09 Oct 2014 00:00:00 GMT</pubDate></item><item><title><![CDATA[Google Play Music on Firefox OS]]></title><description><![CDATA[<p>Unfortunately, HTML5 playback of Google Play Music doesn&#39;t work in Firefox desktop, let alone Firefox OS.</p>
<p>The only workaround on desktop is to deactivate HTML5 Audio (and enable Flash!) in <code>Settings</code> &gt; <code>Lab</code>:</p>
<p><img src="https://lh5.googleusercontent.com/xzXQE966E7owgcLWgOzu2HI_9FfS0Q5neQZXaUkuVJcB=s0" alt="How to deactivate HTML5 audio in Google Play Music Settings" title="Deactivate HTML5 playback in Google Play Music."></p>
<p>The reasons why HTML5 playback doesn&#39;t work is probably because of browser sniffing. A couple of bugs are opened (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=911837">Google Play Music HTML5 Audio Feature broken</a> and <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=902531">Google Play Music not working on Firefox for Android/Firefox OS</a>), but no clear solution was provided thus far.</p>
<p>I&#39;m using Google Play Music to play my CD collection that I&#39;ve encoded over the last few years and I want listen to it on Firefox OS.</p>
<h2><a name="javascript-api-nay" class="anchor" href="#javascript-api-nay"><span class="header-link"></span></a>JavaScript API? Nay</h2>
<p>There are no official APIs, but some unofficial ones are available. The risk of relying your product on unofficial API is that it can stop working because of a redesign or a protocol change of the original service. Before consider this as an option make sure to check how is the maintainer committed to the API maintenance!</p>
<p>I&#39;m not enquiring further in this direction because a server is usually required. I want something that works offline.</p>
<h2><a name="offline-mode-yay" class="anchor" href="#offline-mode-yay"><span class="header-link"></span></a>Offline mode? Yay</h2>
<p>So, here&#39;s how I use Google Music on my Firefox OS devices:</p>
<ul>
<li>Install the official client on my desktop</li>
<li>Download all of my library (warning: may take time and bandwidth)</li>
<li>Copy to a memory card.</li>
</ul>
<p>I get:</p>
<ul>
<li>My albums</li>
<li>The songs metadata</li>
<li>The art cover (I <em>really</em> like that)</li>
</ul>
<p>I don&#39;t get:</p>
<ul>
<li>Uploaded content since last library download</li>
<li>My playlists</li>
</ul>
<p>It&#39;s completely disconnected to the Google Music account, so whenever I upload new CDs, I have to download and copy them to the SD card. But to be honest I don&#39;t really mind and it works for me: I get the album covers and it works offline!</p>
<p><img src="https://lh4.googleusercontent.com/-NuJrYDM4xSc/VBAjCsT5qvI/AAAAAAAAWxw/j357dFhtYt4/s0/Firefox-OS-play-app.png" alt="Firefox OS Play app showing albums imported from Google Music" title="Firefox OS Play app"></p>
]]></description><link>https://gu.illau.me/posts/google-play-music-on-firefox-os/</link><guid isPermaLink="true">https://gu.illau.me/posts/google-play-music-on-firefox-os/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Thu, 02 Oct 2014 00:00:00 GMT</pubDate></item><item><title><![CDATA[Follow-up on navigator.languages]]></title><description><![CDATA[<p><code>navigator.languages</code> recently made its way to the stable versions of browsers: Firefox 32, Chrome 37 and Opera 24!</p>
<h2><a name="getting-all-the-user-languages" class="anchor" href="#getting-all-the-user-languages"><span class="header-link"></span></a>Getting all the user languages</h2>
<p>As explained in an <a href="http://gu.illau.me/posts/the-problem-of-user-language-lists-in-javascript/">earlier post</a>, <code>navigator.languages</code> gives us the complete list of languages as set by the user in her browser.</p>
<p><code>navigator.languages</code> is an array of language codes sorted by priority (the lower the index, the higher the priority).</p>
<p>You can do cool things like:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">langNum</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Set</span><span class="p">(</span><span class="nx">navigator</span><span class="p">.</span><span class="nx">languages</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="nx">code</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;-&#39;</span><span class="p">).</span><span class="nx">shift</span><span class="p">();</span>
<span class="p">})).</span><span class="nx">size</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="s1">&#39;It looks like you can read %i %s.&#39;</span><span class="p">,</span> 
  <span class="nx">langNum</span><span class="p">,</span> <span class="nx">langNum</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="o">?</span> <span class="s1">&#39;different languages&#39;</span> <span class="o">:</span> <span class="s1">&#39;language&#39;</span><span class="p">);</span>
</pre></div>
</code></pre>
<p>(<code>Set</code> is used here to dedupe the array.)</p>
<p>Use this to show the best matching language by comparing <code>navigator.languages</code> to the ones supported by your app. But of course, also offer an option to change the language.</p>
<h2><a name="languagechange-event" class="anchor" href="#languagechange-event"><span class="header-link"></span></a><code>languagechange</code> event</h2>
<p>In addition to <code>navigator.languages</code>, browsers can now listen to the <code>languagechange</code> event fired by the <code>window</code> object to update the UI language accordingly:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;languagechange&#39;</span><span class="p">,</span> <span class="kd">function</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="s1">&#39;You updated your browser languages to &quot;%s&quot;&#39;</span><span class="p">,</span> <span class="nx">navigator</span><span class="p">.</span><span class="nx">languages</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;, &#39;</span><span class="p">));</span>
<span class="p">});</span>
</pre></div>
</code></pre>
<p>I set up this quick demo that <a href="http://jsbin.com/difen/1/">lists the languages set in your browser</a> and stays up to date.</p>
<p>This powerful event means web apps don&#39;t require to be reloaded to update their UI language and can integrate perfectly in the browser/OS.</p>
<h2><a name="polyfill" class="anchor" href="#polyfill"><span class="header-link"></span></a>Polyfill</h2>
<p>Polyfilling <code>navigator.languages</code> couldn&#39;t get any easier:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">navigator</span><span class="p">.</span><span class="nx">languages</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">navigator</span><span class="p">.</span><span class="nx">languages</span> <span class="o">=</span> <span class="p">[</span><span class="nx">navigator</span><span class="p">.</span><span class="nx">language</span><span class="p">];</span>
<span class="p">}</span>
</pre></div>
</code></pre>
<h2><a name="setting-the-language-independently-to-the-os" class="anchor" href="#setting-the-language-independently-to-the-os"><span class="header-link"></span></a>Setting the language independently to the OS</h2>
<p>As a side note on this topic, on most mobile OSes (and some others like MacOS), the language of the browser is tied to that of the OS. Since last year, it&#39;s now possible to change the language of Firefox for Android independently (and without restarting the browser!).
Why is it important? See <a href="http://160.twinql.com/new-locale-related-work-in-firefox-for-android/">this blog post</a> for more details.</p>
]]></description><link>https://gu.illau.me/posts/follow-up-on-navigator-languages/</link><guid isPermaLink="true">https://gu.illau.me/posts/follow-up-on-navigator-languages/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Tue, 09 Sep 2014 00:00:00 GMT</pubDate></item><item><title><![CDATA[Software gamepad]]></title><description><![CDATA[<p>I recently resumed my work on <a href="https://github.com/gmarty/jsSMS">jsSMS a JavaScript recompiler for Sega Master System and Game Gear</a>. Among the new features, I wanted to improve the software gamepad for touch screens.</p>
<h3><a name="naive-implementation" class="anchor" href="#naive-implementation"><span class="header-link"></span></a>Naive implementation</h3>
<p>When I started adding the software gamepad, I did something quick and dirty. I didn&#39;t really have time to waste developing a nice looking controller in canvas (though that would have been easier). So I just threw some <code>&lt;div&gt;</code> tags, styled them and attached a couple of event listeners.</p>
<p>To have a gamepad compatible with touch screens, I naturally listened to touch event on each key (up, down, left, right, fire1, fire2 and start).  <code>touchstart</code> and <code>touchmove</code> communicate the active key to the emulator and <code>touchend</code> release it.</p>
<p>The main issue I found was that if the user moves her finger, the JavaScript will recognise the activation of a particular key, but will release a different one. In other word, the key initially pressed will never be released.</p>
<p>Clearly, this was unusable.</p>
<h3><a name="better-implementation" class="anchor" href="#better-implementation"><span class="header-link"></span></a>Better implementation</h3>
<p>I looked for tutorials and references about how to build a gamepad using HTML5, but it looks like most HTML5 games use canvas and detect the currently touched key using the location of the touch.</p>
<p>The location of the finger relative to the screen is stored in <code>clientX</code> and <code>clientY</code> properties of the touch event. If you use jQuery, like myself, make sure to reference the original event using <code>originalEvent</code> property (i.e. <code>evt.originalEvent.clientX</code>).</p>
<p>To get the position of the currently touch key in HTML, I could have computed the position and size of each buttons, then loop through them to find the element touched. In my case, that wasn&#39;t possible because I use a complex layout made of rounded and rotated elements and not just square buttons.</p>
<p>Thanks to StackOverflow, the answer was actually quite easy and requires a single DOM method: <code>document.elementFromPoint</code>.</p>
<p>To get the currently touched element just pass the touch event coordinates to <code>document.elementFromPoint</code>:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">touchedElement</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">elementFromPoint</span><span class="p">(</span><span class="nx">evt</span><span class="p">.</span><span class="nx">clientX</span><span class="p">,</span> <span class="nx">evt</span><span class="p">.</span><span class="nx">clientY</span><span class="p">);</span>
</pre></div>
</code></pre>
<p>Then, you need to implement a mechanism to map back the DOM element touched to the emulated key  (I personally use CSS class name and a map object).</p>
<p>Also, you&#39;ll want to iterate over the <code>changedTouches</code> array to properly activate all the buttons pressed on multi-touch devices.</p>
<p>To put it in a nutshell:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">onTouch</span><span class="p">(</span><span class="nx">evt</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">emulator</span><span class="p">.</span><span class="nx">releaseAllKeys</span><span class="p">();</span>
  <span class="nx">evt</span><span class="p">.</span><span class="nx">changedTouches</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">touch</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">target</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">elementFromPoint</span><span class="p">(</span><span class="nx">touch</span><span class="p">.</span><span class="nx">clientX</span><span class="p">,</span> <span class="nx">touch</span><span class="p">.</span><span class="nx">clientY</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">key</span> <span class="o">=</span> <span class="nx">getKeyFromElement</span><span class="p">(</span><span class="nx">target</span><span class="p">);</span>
    <span class="nx">emulator</span><span class="p">.</span><span class="nx">pressKey</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
  <span class="p">});</span>

  <span class="nx">evt</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">onTouchEnd</span><span class="p">(</span><span class="nx">evt</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">emulator</span><span class="p">.</span><span class="nx">releaseAllKeys</span><span class="p">();</span>
<span class="p">}</span>

<span class="nx">padElement</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;touchstart&#39;</span><span class="p">,</span> <span class="nx">onTouch</span><span class="p">);</span>
<span class="nx">padElement</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;touchmove&#39;</span><span class="p">,</span> <span class="nx">onTouch</span><span class="p">);</span>
<span class="nx">padElement</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;touchend&#39;</span><span class="p">,</span> <span class="nx">onTouchEnd</span><span class="p">);</span>
</pre></div>
</code></pre>
<p>Obviously, you&#39;ll want to code your own <code>getKeyFromElement</code> and emulator communicating functions.</p>
<h3><a name="how-optimised" class="anchor" href="#how-optimised"><span class="header-link"></span></a>How optimised?</h3>
<p>The result is a nicely working touch optimised controller in HTML5. The finger can swipe from one key to another and the emulator reacts responsively.</p>
<p>I don&#39;t think you could do simpler and according to my coworker, the brilliant <a href="https://twitter.com/cwiiis">Chris Lord</a>, if your DOM tree is simple you shouldn&#39;t get any performance penalty from using <code>document.elementFromPoint</code>.</p>
<p>Happy gaming!</p>
]]></description><link>https://gu.illau.me/posts/software-gamepad/</link><guid isPermaLink="true">https://gu.illau.me/posts/software-gamepad/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Sun, 10 Aug 2014 00:00:00 GMT</pubDate></item><item><title><![CDATA[Building a syntactic translation engine]]></title><description><![CDATA[<p>I recently blogged about how <a href="http://gu.illau.me/posts/how-i-built-a-translation-engine-in-a-weekend/">I prototyped a very simplistic translation engine</a>. Here&#39;s a follow up to describe the logic involved.</p>
<h2><a name="disclaimer" class="anchor" href="#disclaimer"><span class="header-link"></span></a>Disclaimer</h2>
<p>I wish I had a serious background in NLP and machine translation, but I don&#39;t and the logic described here is solely based on my scarce knowledge in this field and my experience as a foreign language speaker.</p>
<h2><a name="definition" class="anchor" href="#definition"><span class="header-link"></span></a>Definition</h2>
<p>I&#39;m not sure if the word syntactic machine translation does really exist, but I found it describes what I mean very well. So let&#39;s start off by giving my personal definition of syntactic MT.</p>
<p>Unlike advanced techniques, the syntactic MT engine only takes the syntax of the languages into account. It doesn&#39;t try to understand the meaning of the phrases to translate. This is major limitation as it can&#39;t understand idiomatic expressions, such as proverbs...</p>
<p>Also a single word with different meanings will be translated the same way regardless of the context in the sentence to translate.</p>
<p>This is to be remembered when assessing the accuracy of the translated phrases.</p>
<p>However, the advantage of this method lays in the fact that it is very easy to develop, doesn&#39;t require a deep understanding of MT and can be hacked in a weekend!</p>
<h2><a name="how-does-it-work" class="anchor" href="#how-does-it-work"><span class="header-link"></span></a>How does it work?</h2>
<p>I&#39;ll now describe the mechanism I implemented to hack a quick and dirty syntactic MT engine for English and Japanese.</p>
<p>This idea of syntactic MT is that elements in translated pairs bear the same class of Part of Speech (POS ; i.e. noun, verb, adverb...) in both languages, for example, an adjective remains an adjective in the resulting translation. A certain grammatical pattern will be the same in each pairs of the corpus and the resulting translation.</p>
<h3><a name="spring-cleaning" class="anchor" href="#spring-cleaning"><span class="header-link"></span></a>Spring cleaning</h3>
<p>First of all, I cleaned up the corpus a bit, applying the following steps:</p>
<ul>
<li>Removing incomplete sentences</li>
<li>Unify punctuations (specially adding an optional question mark at the end of questions in Japanese)</li>
<li>Normalising the Japanese to use half-width alphanumeric characters and full-width katakana and punctuation signs</li>
</ul>
<p>I then normalise both languages to keep semantic equivalents while reducing inflected forms (e.g. <code>can&#39;t</code> -&gt; <code>cannot</code> ; <code>します</code> -&gt; <code>する</code> ; See <code>/utils/ja-normalizer.js</code> and <code>/utils/en-normalizer.js</code>). Doing so reduced noise and helped a lot on quality as the corpus is quite small.</p>
<h3><a name="tag-the-corpus" class="anchor" href="#tag-the-corpus"><span class="header-link"></span></a>Tag the corpus</h3>
<p>Then, the next thing to do is to tag the POS of all the pairs in the corpus.</p>
<p>The English sentences are tagged using <a href="https://github.com/fortnightlabs/pos-js">pos-js</a> written in JavaScript (an in-browser and Node.JS versions both exist).</p>
<p>The Japanese is tagged using <a href="http://en.wikipedia.org/wiki/ChaSen">ChaSen</a>. ChaSen is a famous command line utility, but this is a serious limitation here. To make it work, the sentence to translate must be tagged too (more on this later). I wanted the app to work offline and use frontend code only, but the lack of a JavaScript implementation of a Japanese POS tagger forced me to reject Japanese to English translation. Only English to Japanese is supported.</p>
<p>The first problem arising here is the difference between the POS items in English and Japanese. Chasen is very comprehensive, so I had to simplify and match its POS items to the ones returned by pos-js (see <code>/utils/chasen2jspos-map.json</code> and <code>/utils/jspos2simplified-map.json</code>).</p>
<h3><a name="build-a-dictionary" class="anchor" href="#build-a-dictionary"><span class="header-link"></span></a>Build a dictionary</h3>
<p>At this stage, I have 2 corpus tagged, I can easily align classes of POS in both languages to build a dictionary. Let&#39;s say a pair has only one adjective in English and in Japanese, we can conclude that this adjective in English is likely to be translated by this other adjective in Japanese. The first pass consists of extracting terms whose class of POS appear only once in each pair.</p>
<p>For more ambiguous pairs containing more than one class of POS in both sentences, alignment is harder. The method I found makes use of the dictionary we are building.</p>
<p>Let&#39;s say a phrase has 2 adjectives in both languages. If one of them and its translation are already in the dictionary, we can assume that the remaining adjective matches the other one in the destination sentence. This is the second pass. I repeat this step a couple of times until no new translations are found.</p>
<p>This dictionary building method gives incredible results. Of course there is some noise, but for frequent words, the translations are very accurate. Here&#39;s an example for the word <code>already</code> and its frequency in Japanese translations:</p>
<pre><code class="lang-json"><div class="highlight"><pre><span class="p">{</span>
  <span class="nt">&quot;すでに&quot;</span><span class="p">:</span> <span class="mi">23</span><span class="p">,</span>
  <span class="nt">&quot;既に&quot;</span><span class="p">:</span> <span class="mi">17</span><span class="p">,</span>
  <span class="nt">&quot;もう&quot;</span><span class="p">:</span> <span class="mi">8</span>
<span class="p">}</span>
</pre></div>
</code></pre>
<p>It indeed contains all the translation for <code>already</code> that I know!</p>
<p>See <code>/build-dico.js</code> for the implementation.</p>
<h3><a name="build-a-pos-converter" class="anchor" href="#build-a-pos-converter"><span class="header-link"></span></a>Build a POS converter</h3>
<p>Now we&#39;re still using the POS tagged corpus to match patterns in both languages.</p>
<p>For each phrase with a certain POS pattern (e.g. Noun Verb Noun), we look for the most common pattern in the translated phrases. The idea is to determine which is the most frequent translated POS pattern of a language given the POS pattern of the source phrase.</p>
<p>At this stage I also generate what I called placeholders. They are generic sentences for this particular POS pattern where I replaced each word by the most common one (I know it&#39;s completely unscientific!). These are used as a base for translation. I just need to inject the right words (see below).</p>
<p>See the code at <code>/build-pos-converter.js</code>.</p>
<h3><a name="finally-translate" class="anchor" href="#finally-translate"><span class="header-link"></span></a>Finally, translate</h3>
<p>With all these static assets generated (dictionary, POS pattern matcher, POS pattern placeholders), I can try to translate from one language to another.</p>
<p>The user input in English is first normalised (see above), then POS tagged (Remember? That&#39;s why I can&#39;t use Japanese input on the browser as ChaSen is a command line tool). I then look for the most frequent POS pattern in Japanese.</p>
<p>Once found, I take the Japanese placeholder sentence for this POS pattern and inject into it the translations from the original English input. For words that don&#39;t have translations, the word is just ignored and the one from the placeholder is preserved (thus creating very weird translations at time, but at least giving complete and correct sentences). Of course this could be improved using a more comprehensive dictionary, but I didn&#39;t try it.</p>
<p>One of the problem not addressed by this script is the alignment of several identical classes of POS. In this case, I just assign them in order: the first adjective in English is matched to the first in Japanese, then the second... and so on. I know this is quite of an issue, but I just couldn&#39;t be bothered trying to fix it.</p>
<p>The script is located in <code>/en2ja.js</code>.</p>
<h2><a name="the-future" class="anchor" href="#the-future"><span class="header-link"></span></a>The future</h2>
<p>There is a lot of room for improvement in many places:</p>
<ul>
<li>Using an unified POS tagger for English and Japanese, ideally written in JavaScript, for a better quality.</li>
<li>Using an external dictionary to enhance translations.</li>
<li>Use statistics to reject the less significant pairs in the dictionary and the POS converter.</li>
<li>Use a stemmer to group several inflections of the same nouns, verbs or adjectives and get a more complete dictionary.</li>
<li>Use a bigger corpus.</li>
</ul>
<p>But that&#39;s it for now, I may work on this later, but in the meantime, feel free to contribute!</p>
]]></description><link>https://gu.illau.me/posts/building-a-syntactic-translation-engine/</link><guid isPermaLink="true">https://gu.illau.me/posts/building-a-syntactic-translation-engine/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Mon, 21 Apr 2014 00:00:00 GMT</pubDate></item><item><title><![CDATA[How I built a translation engine in a weekend]]></title><description><![CDATA[<h2><a name="and-managed-to-go-out-on-friday-and-saturday-nights" class="anchor" href="#and-managed-to-go-out-on-friday-and-saturday-nights"><span class="header-link"></span></a>and managed to go out on Friday and Saturday nights</h2>
<p>Google Translate is powered by the technique called <a href="https://en.wikipedia.org/wiki/Machine_translation">machine translation</a>. It can translate sentences from one natural language to another, without human interactions.
I recently heard that Mozilla was starting a project to create an open source machine translation engine. That immediately resonated in me and I decided to give it a try and build my own English-Japanese translator in JavaScript.</p>
<h2><a name="day-1-get-ready" class="anchor" href="#day-1-get-ready"><span class="header-link"></span></a>Day 1: Get ready</h2>
<p>On the Friday late afternoon, I had a general idea of what I wanted to implement: a machine translation engine using syntax to translate sentences. I wanted something simple and couldn&#39;t wait to see it working. I realized I had this &quot;fire in the belly&quot; and jumped directly into the action.
I spent a small amount of time gathering what I needed: a corpus of translated pairs in English and Japanese and a part-of-speech tagger for these languages.
I started fiddling around with the tools with as few coding as possible.</p>
<h2><a name="day-2-put-it-together" class="anchor" href="#day-2-put-it-together"><span class="header-link"></span></a>Day 2: Put it together</h2>
<p>I had a late night and woke up on Saturday around 11 o&#39;clock. I spent a few hours cleaning up what I had done the day before, creating a dedicated folder and project in my IDE. I started coding and refactor the code.
I also spent some time sketching solutions on paper, to make sure I hadn&#39;t missed an important point.</p>
<h2><a name="day-3-make-it-work" class="anchor" href="#day-3-make-it-work"><span class="header-link"></span></a>Day 3: Make it work</h2>
<p>I got back to the project in the early afternoon. I mostly did coding this day. I was so excited to see my translation engine work that I sat in front of my computer for ~10 hours. At the end of the day, I had something working. After a bit of cleaning, I created <a href="https://github.com/gmarty/syntactic-machine-translation">the repo on Github</a> and pushed the code.</p>
<h2><a name="after-day-3" class="anchor" href="#after-day-3"><span class="header-link"></span></a>After day 3</h2>
<p>Whatever happened after day 3 is not important. Most of the work has been done over the weekend and I had a working prototype. Obviously, it is just a toy system, that is nothing comparable to Google Translate, but I&#39;m happy I was able to do it in a rather limited amount of time. And most importantly, I can iterate on it and progressively make it better. <a href="http://gmarty.github.io/syntactic-machine-translation/">Try it for yourself!</a></p>
<h2><a name="conclusion" class="anchor" href="#conclusion"><span class="header-link"></span></a>Conclusion</h2>
<p>I was able to achieve this because JavaScript is very suited for fast prototyping. If it were a business, I could have started generating profit from day 4. I really love the idea of hacking a quick and dirty prototype and see how it works. Next time you have an idea for a business, do some quick prototyping and launch it as early as possible!</p>
<p>And if you&#39;re wondering, I had dinner in a <a href="http://pastacibo.com/">lovely Italian restaurant</a> on Saturday night :-)</p>
]]></description><link>https://gu.illau.me/posts/how-i-built-a-translation-engine-in-a-weekend/</link><guid isPermaLink="true">https://gu.illau.me/posts/how-i-built-a-translation-engine-in-a-weekend/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Mon, 03 Mar 2014 00:00:00 GMT</pubDate></item><item><title><![CDATA[The problem of user language lists in JavaScript]]></title><description><![CDATA[<p><a href="http://gu.illau.me/posts/follow-up-on-navigator-languages/">Edit: I wrote a followup post to this one at [Follow-up on navigator.languages</a>]</p>
<p><a href="https://twitter.com/g_marty/status/412527722410553344">I&#39;ve always wondered</a> why it is not possible to get in JavaScript the list of all languages as configured in the browser. This list is made available to servers via a HTTP header.</p>
<p>On the other hand, JavaScript can only get the first language using:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">navigator</span><span class="p">.</span><span class="nx">language</span><span class="p">);</span> <span class="c1">// &#39;en&#39;, &#39;fr&#39;, &#39;de&#39; or whatever</span>
</pre></div>
</code></pre>
<h2><a name="browsers-inconsistencies" class="anchor" href="#browsers-inconsistencies"><span class="header-link"></span></a>Browsers inconsistencies</h2>
<p>Getting the language of the browser is part of the <a href="http://www.w3.org/TR/html5/webappapis.html#language-preferences">HTML5 specifications</a>, but implementations vary widely.</p>
<h3><a name="internet-explorer" class="anchor" href="#internet-explorer"><span class="header-link"></span></a>Internet Explorer</h3>
<p>Let&#39;s start with IE that has (surprisingly) the most complete set of (non standard) features about the environment language. <code>navigator.userLanguage</code> gets the first language set by the user (can be changed in Internet Options &gt; General &gt; Languages ; see <a href="http://msdn.microsoft.com/en-us/library/ie/ms534713%28v=vs.85%29.aspx">Internet Explorer Dev Center</a>).</p>
<p><code>navigator.browserLanguage</code> returns the language of the UI of the browser. You can&#39;t change this value, it is decided by the version of the executable you installed (This property and all its subtleties are described in <a href="http://msdn.microsoft.com/en-us/library/ie/ms533542%28v=vs.85%29.aspx">Internet Explorer Dev Center</a>).</p>
<p>Finally, <code>navigator.systemLanguage</code> will give you the locale used by the OS (See <a href="http://msdn.microsoft.com/en-us/library/ie/ms534653%28v=vs.85%29.aspx">Internet Explorer Dev Center</a>.</p>
<h3><a name="firefox-safari" class="anchor" href="#firefox-safari"><span class="header-link"></span></a>Firefox &amp; Safari</h3>
<p><code>navigator.language</code> returns the first language in the list of languages.</p>
<p>In Firefox, you can define it in Options &gt; Content &gt; Languages.</p>
<p>Safari uses the language set at the system level (See <code>navigator.systemLanguage</code> of IE above). You cannot just override it in Safari.</p>
<p>Some details are available on the <a href="https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage.language">navigator.language page on MDN</a>.</p>
<h3><a name="chrome" class="anchor" href="#chrome"><span class="header-link"></span></a>Chrome</h3>
<p>Invariantly returns the language of the UI through <code>navigator.language</code> without a <a href="https://code.google.com/p/chromium/issues/detail?id=1862">possibility to change it</a>. The value is similar to <code>navigator.browserLanguage</code> of IE.</p>
<p>Chrome extensions can retrieve the full list of languages as set by the user thanks to <code>chrome.i18n.getAcceptLanguages()</code> (Not sure why this API is async):</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="nx">chrome</span><span class="p">.</span><span class="nx">i18n</span><span class="p">.</span><span class="nx">getAcceptLanguages</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">requestedLocales</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// &#39;requestedLocales&#39; is an array of strings.</span>
<span class="p">});</span>
</pre></div>
</code></pre>
<h2><a name="whats-wrong-with-the-current-approach" class="anchor" href="#whats-wrong-with-the-current-approach"><span class="header-link"></span></a>What&#39;s wrong with the current approach?</h2>
<p>Well, apart from the semantic inconsistencies, knowing only the main language is a serious limitation. Let&#39;s illustrate this with my personal experience. My browsers have the following configuration:</p>
<ol>
<li>Japanese</li>
<li>English (GB)</li>
<li>English</li>
<li>English (US)</li>
<li>French</li>
<li>Spanish</li>
<li>Korean</li>
<li>German</li>
</ol>
<p>(Yeah, I want to train my Japanese, so I listed it first!)</p>
<p>A website available in several languages will show the interface in Japanese and English if not available.</p>
<p>But a local app will only get the first language, Japanese. So if this language is not available, the UI will be shown in a totally random language that I may not understand.</p>
<p>Also, if the app knows the full list, it could use it to detect visitors speaking rare languages and ask them to collaborate on translation.</p>
<h2><a name="how-to-fix-it" class="anchor" href="#how-to-fix-it"><span class="header-link"></span></a>How to fix it?</h2>
<p>First of all, an easy cross browser way to get the preferred language is to do:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="cm">/** @const */</span> <span class="nx">DEFAULT_VALUE</span> <span class="o">=</span> <span class="s1">&#39;en&#39;</span><span class="p">;</span>
<span class="cm">/** @const */</span> <span class="nx">PREFERRED_LANGUAGE</span> <span class="o">=</span> <span class="nx">navigator</span><span class="p">.</span><span class="nx">language</span> <span class="o">||</span> <span class="nx">navigator</span><span class="p">.</span><span class="nx">userLanguage</span> <span class="o">||</span> <span class="nx">navigator</span><span class="p">.</span><span class="nx">browserLanguage</span> <span class="o">||</span> <span class="nx">navigator</span><span class="p">.</span><span class="nx">systemLanguage</span> <span class="o">||</span> <span class="nx">DEFAULT_VALUE</span><span class="p">;</span>
</pre></div>
</code></pre>
<p>That&#39;s fine as long as your app supports this language.</p>
<p>If not, you could always ping a server, get the <code>accept-language</code> HTTP header, send the response back to JavaScript and parse it. That means that you need a scriptable server, so you cannot do it for, offline apps or for apps hosted on a static web server like Github Pages.
Oh and Mac have only one language configured at a time: you will never get more than 1 element in the list of this header on Safari.</p>
<h2><a name="what-to-do-next" class="anchor" href="#what-to-do-next"><span class="header-link"></span></a>What to do next?</h2>
<p>The good news is things are being worked on.</p>
<p>First, there is <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=23517">this bug</a> on the WHATWG bug tracker to discuss this feature, with all <a href="https://github.com/marcoscaceres/Locale-Preferences-API/blob/master/proposal.md">the details here</a>. Firefox is already <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=889335">thinking of implementing it</a>.</p>
<p>To put it in a nutshell, the current consensus is to have a new JavaScript property called <code>navigator.languages</code> that returns an array of language codes sorted by preference order:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">navigator</span><span class="p">.</span><span class="nx">languages</span><span class="p">);</span>
<span class="c1">// The configuration above would give something like:</span>
<span class="c1">// [&#39;ja&#39;, &#39;en-GB&#39;, &#39;en&#39;, &#39;en-US&#39;, &#39;fr&#39;, &#39;es&#39;, &#39;ko&#39;, &#39;de&#39;];</span>
</pre></div>
</code></pre>
<p>Also, firing an event when language changes is also being discussed. Firefox OS allows this on certified apps with a proprietary API:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="nx">navigator</span><span class="p">.</span><span class="nx">mozSettings</span><span class="p">.</span><span class="nx">addObserver</span><span class="p">(</span><span class="s1">&#39;language.current&#39;</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">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;New language&#39;</span><span class="p">,</span> <span class="nx">event</span><span class="p">.</span><span class="nx">settingValue</span><span class="p">);</span> <span class="c1">// Default value is &#39;en-US&#39;.</span>
<span class="p">});</span>
</pre></div>
</code></pre>
<h2><a name="to-conclude" class="anchor" href="#to-conclude"><span class="header-link"></span></a>To conclude</h2>
<p>Making the full list of languages configured in a browser available to JavaScript can&#39;t be done front-end at all and partially using back-end. But this information is stored in the OS/browser itself. Am I the only one to think something is wrong here?</p>
<p>This topic is hard and has been around for a while, so some of the resources I consulted might be outdated. Use the comments below if you spotted any error.</p>
]]></description><link>https://gu.illau.me/posts/the-problem-of-user-language-lists-in-javascript/</link><guid isPermaLink="true">https://gu.illau.me/posts/the-problem-of-user-language-lists-in-javascript/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Tue, 28 Jan 2014 00:00:00 GMT</pubDate></item><item><title><![CDATA[Don't optimise JavaScript]]></title><description><![CDATA[<p>I&#39;ve noticed lately a lot of confusion regarding performance of web applications. This post tries to clarify a few points while delivering a method for optimising your code.</p>
<blockquote>
<p><strong>tl;dr:</strong> In case of slow web app:</p>
<ul>
<li>Don&#39;t immediately jump into JavaScript optimisation; instead investigate network, DOM, rendering... and fix accordingly</li>
<li>Profile your application and optimise the code logic</li>
<li>Optimise JavaScript only when required</li>
</ul>
</blockquote>
<h2><a name="find-the-culprit" class="anchor" href="#find-the-culprit"><span class="header-link"></span></a>Find the culprit</h2>
<p>In modern browsers, JavaScript is rarely the cause of slow applications. There are many layers involved in web applications that are way slower.</p>
<p>The first thing to do is to investigate to find out where the performance issue is coming from. The causes can be multiple:</p>
<ul>
<li>Relying too much on the connexion</li>
<li>Extensive DOM manipulation</li>
<li>Rendering issues (forced layout...)</li>
<li>io (e.g. repeated usage of <code>localStorage</code>)</li>
</ul>
<p>Use the Network tab of your favourite browser&#39;s development tool. Make sure your requests don&#39;t have any impact on your application at start and run time. Repeated Ajax calls can slow down applications too.</p>
<p>Identifying slow DOM manipulation is a bit harder. The Timeline tab of Chrome&#39;s dev tools can help you pinpointing such issues. Of course, you must get familiar with the best practices. For example, when rendering a list of items in a templating engine, move the loop to the template and append all items to the DOM in one operation.</p>
<p>Rendering issues can also be <a href="https://developers.google.com/chrome-developer-tools/docs/demos/too-much-layout/">captured by Chrome&#39;s dev tools</a> and starting from version 27, Firefox can now <a href="https://hacks.mozilla.org/2013/11/firefox-developer-tools-episode-27-edit-as-html-codemirror-more/">log functions that trigger a reflow</a>!</p>
<p>There are a lot of valuable resources on the net about how to track down and fix these issues, so I won&#39;t cover them here. Once fixed, your application should work smoother. Not the case with yours? Keep reading then.</p>
<h2><a name="profile-and-improve-logic-rinse-and-repeat" class="anchor" href="#profile-and-improve-logic-rinse-and-repeat"><span class="header-link"></span></a>Profile and improve logic. Rinse and repeat</h2>
<p>So you made all these checks and you realised that JavaScript is actually what causes your application to perform badly.</p>
<p>Nice, my favourite part of the optimisation process starts here! You need to profile your application.</p>
<p>Grab your modern browser. Start the profiler then your app and interact with it like a normal user would. After a while, stop the profiler.</p>
<p>You can now drill down to the most frequently called functions. If you&#39;re using closures or generated functions, make sure to <a href="http://gu.illau.me/posts/generating-generator-functions/#caveat-2-named-functions">name them to get meaningful results</a>.</p>
<p>Now, have a look at the logic of the calls. There is certainly room for optimisation. Common mistakes include:</p>
<ul>
<li>Calling a function too many times, where the result could be cached and reused</li>
<li>Deeply nested loops</li>
<li>Iterating too many times when you could stop the iteration prematurely</li>
</ul>
<p>You also need to profile the memory used and track potential leak or heavy garbage collections.</p>
<p>By operating at the code logic level, you can improve the speed of your application. The fixes applied here are not directly related to the JavaScript language, but rather to the logic of your code.</p>
<p>You found and fixed these bottlenecks and now your application is running faster and smoother. You are now done, no need to read further.</p>
<h2><a name="about-javascript-optimisation" class="anchor" href="#about-javascript-optimisation"><span class="header-link"></span></a>About JavaScript optimisation</h2>
<p>You are still reading? I assume you are working on a signal processing tool, a game or a fundamental piece of software that must run fast.</p>
<p>Before looking into the optimisation of JavaScript, I must clarify a couple of things.</p>
<p>Keep in mind that JavaScript VMs are very good at running your code at a fast speed.</p>
<p>Trust the VM.</p>
<p>The second thing is using an alternate JavaScript syntax in your code is likely to never have any significant impact on speed. This belief dates back from the time browsers didn&#39;t have a JIT. Back then, using different syntaxes could make a difference. These kind of statements flourished over the web:</p>
<ul>
<li><code>if</code> are faster than <code>switch</code>.</li>
<li>bitwise operations are faster than mathematical operators.</li>
<li>join array to do strings concatenation</li>
</ul>
<p>Optimising JavaScript is not about the syntax. You can&#39;t base an optimisation strategy on syntax rewriting only. You&#39;ll end up wasting your time and get a little to no results. I&#39;m not even mentioning the impact on readability and maintainability of your code.</p>
<p>Also, VM are constantly evolving. What perform best today might not tomorrow. VM implementors take code from the real world to see what developers do and what patterns to optimise. Using weird syntax is likely to never be optimised. Just write your code in a way that makes sense and that should be enough.</p>
<h2><a name="finally-youre-ready-to-optimise-javascript" class="anchor" href="#finally-youre-ready-to-optimise-javascript"><span class="header-link"></span></a>Finally, you&#39;re ready to optimise JavaScript</h2>
<p>After reading and understanding the statements above, you are now ready to improve your code using advanced optimisations. These crazy techniques include:</p>
<ul>
<li>Enforcing type stability</li>
<li>Tracking deoptimisations</li>
<li>Use web workers to do parrallel processing</li>
</ul>
<p>In the 2nd part of <a href="http://www.youtube.com/watch?v=65-RbBwZQdU">this talk</a>, Vyacheslav shows a tool to inspect the code generated by V8. It&#39;s complex to dive into the VM internals, but that&#39;s the only way to gain some performance points.</p>
<p>To track deoptimisations, using Chrome or V8, you can pass some flags like <code>--trace_deopt</code> (trace deoptimization). You&#39;ll get a more or less descriptive message about why V8 is not able to optimise your code. Fix it if possible.</p>
<p>There are no such tools for Firefox (since <a href="https://addons.mozilla.org/ja/firefox/addon/jit-inspector/">JIT inspector</a> is not working) or IE. So I have to recommend Chrome to optimise JavaScript this way. However, try as much as possible not to be too specific so that your code run fast, or at least not slower, on other browsers too.</p>
<p>Optimisation is a complex topic, but there are techniques we can apply to make your code run fast. I&#39;d like to elaborate on each step described in this process in the form of blog posts. But for now, just take the time to locate the cause of slowness and don&#39;t incriminate JavaScript right away, the culprit can be hiding elsewhere!</p>
]]></description><link>https://gu.illau.me/posts/dont-optimise-javascript/</link><guid isPermaLink="true">https://gu.illau.me/posts/dont-optimise-javascript/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Mon, 16 Dec 2013 00:00:00 GMT</pubDate></item><item><title><![CDATA[Firefox OS: the Device Storage API]]></title><description><![CDATA[<p>Working with the <a href="https://developer.mozilla.org/en/docs/WebAPI/Device_Storage">Device Storage API</a> of Firefox OS can be a bit complicated if you don&#39;t have a real device at hand. But if you use Firefox OS Simulator, the following advices can help you.</p>
<h2><a name="sd-card" class="anchor" href="#sd-card"><span class="header-link"></span></a>SD Card</h2>
<p>The SD Card location used by Firefox OS Simulator is mapped to a physical folder on your computer.</p>
<p>On Windows:</p>
<blockquote>
<p>C:\Users\<i>USERNAME</i>\AppData\Roaming\Mozilla\Firefox\Profiles\<i>PROFILEKEY</i>\extensions\r2d2b2g@mozilla.org\profile\fake-sdcard</p>
</blockquote>
<p>On Ubuntu:</p>
<blockquote>
<p>/home/<i>USERNAME</i>/.mozilla/firefox/<i>PROFILEKEY</i>/extensions/r2d2b2g@mozilla.org/profile/fake-sdcard</p>
</blockquote>
<p>On Mac:</p>
<blockquote>
<p>Let me know via a comment below where is this folder on Mac.</p>
</blockquote>
<p>Of course, <i>USERNAME</i> and <i>PROFILEKEY</i> are specific to your configuration, so make sure to look into the right folder.</p>
<p>Place files in this folder and you’ll be able to access them from the Simulator using a privileged app.</p>
<p>If this folder doesn&#39;t exist, I believe it&#39;s safe to create it yourself first.</p>
<h2><a name="the-file-objects" class="anchor" href="#the-file-objects"><span class="header-link"></span></a>The File objects</h2>
<p>When you call <code>get</code> or <code>enumerate</code> on <code>navigator.getDeviceStorage(&#39;sdcard&#39;)</code> you get File objects.</p>
<p>For reference, these objects look like this (slightly different than the <a href="https://developer.mozilla.org/en-US/docs/Web/API/File">File API page on MDN</a>):</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="p">{</span>
  <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;file.txt&#39;</span><span class="p">,</span>
  <span class="nx">size</span><span class="o">:</span> <span class="mi">32768</span><span class="p">,</span> <span class="c1">// In bytes</span>
  <span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;text/plain&#39;</span><span class="p">,</span> <span class="c1">// MIME type</span>
  <span class="nx">lastModifiedDate</span><span class="o">:</span> <span class="s1">&#39;Fri Nov 22 2013 12:00:00 GMT+0000 (GMT Standard Time)&#39;</span><span class="p">,</span> <span class="c1">// Date object,</span>
  <span class="nx">mozFullPath</span><span class="o">:</span> <span class="s1">&#39;path/to/the/file&#39;</span> <span class="c1">// Relative to the SD Card folder</span>
<span class="p">}</span>
</pre></div>
</code></pre>
<p>They also have 2 methods: <code>slice()</code> and <code>mozSlice()</code>.</p>
<p>Then if you want to have access to the content of these files in JavaScript, you can just pass them to the FileReader API:</p>
<pre><code class="lang-javascript"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">reader</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">FileReader</span><span class="p">();</span>
<span class="nx">reader</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</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="c1">// e.target.result is the content of the file.</span>
<span class="p">};</span>
<span class="nx">reader</span><span class="p">.</span><span class="nx">readAsText</span><span class="p">(</span><span class="nx">file</span><span class="p">);</span> <span class="c1">// Or whatever method suits you best.</span>
</pre></div>
</code></pre>
<p>I found this API complex to work with. There are different way to access files depending on:</p>
<ul>
<li>what you do with (read only or write)</li>
<li>whether you know the file location or not</li>
</ul>
<p>I hope to write a more complete post or tutorial on the Device Storage API in the future, as accessing files is a common use case for web apps in Firefox OS.</p>
]]></description><link>https://gu.illau.me/posts/firefox-os-the-device-storage-api/</link><guid isPermaLink="true">https://gu.illau.me/posts/firefox-os-the-device-storage-api/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Mon, 25 Nov 2013 00:00:00 GMT</pubDate></item><item><title><![CDATA[The ideal blogging workflow]]></title><description><![CDATA[<p>Before even starting this blog, I took some time to think about what would be my ideal workflow for publishing new posts. I decided it should be:</p>
<ul>
<li>Simple</li>
<li>Hosted for free</li>
<li>Editable from anywhere</li>
<li>and of course based on open source tools</li>
</ul>
<h2><a name="finding-tools-and-solutions" class="anchor" href="#finding-tools-and-solutions"><span class="header-link"></span></a>Finding tools and solutions</h2>
<p>I&#39;m a lazy person and I find it very difficult to do things routinely. So, if I start a blog, I must make sure that nothing gets in my way. The writing/publishing process must be as easy as possible. It took me a while to love the simplicity of Markdown. But ever since I started working heavily with Github, I fell in love with its syntax. Markdown powers the simplicity I needed.</p>
<p>I admire the logic behind the static websites generators. They move the complexity of blogs from the server to your computer. The resulting blogs are incredible fast. We can then use Github as a web hosting platform for free! I choose <a href="http://www.cabinjs.com/">Cabin</a> because it is simple and I wanted to experiment with Jade templates.</p>
<p>The mobile aspect was important to me. I wanted to start or edit posts directly from my mobile, wherever I am, whenever I have time. Also I always use several browsers on different computers all the time, sometime on a bad connexion, if any at all. That&#39;s why I needed something distributed and not dependent on network status. A few months ago I came upon <a href="https://stackedit.io/">StackEdit</a> and was struck by its simplicity, beauty and powerfulness. It works on the browser, offline by default, can synchronise to many services (including Dropbox and Google Drive). The interface is split vertically with the original Markdown view on the left hand side next to the resulting formatted post, a UI pattern used by the <a href="https://ghost.org/">blogging platform Ghost</a> that received a lot of attention lately.</p>
<h2><a name="putting-it-all-together" class="anchor" href="#putting-it-all-together"><span class="header-link"></span></a>Putting it all together</h2>
<p>A typical blog post starts like this. I launch a browser on the device available (laptop, mobile...), start StackEdit and open a new document. I&#39;ve modified the default document to start with the metadata used by Cabin (Think of it as YAML front matter used by Jekyll, but in JSON):</p>
<pre><code class="lang-json"><div class="highlight"><pre><span class="p">{</span>
  <span class="err">title:</span> <span class="nt">&quot;Title&quot;</span><span class="p">,</span>
  <span class="err">date:</span> <span class="nt">&quot;2013-11-01&quot;</span><span class="p">,</span>
  <span class="err">description:</span> <span class="nt">&quot;Description&quot;</span>
<span class="p">}</span>
</pre></div>
</code></pre>
<p>I edit these metadata, start writing my draft and save it to Google Drive. I guess I could publish it directly to the Github repo as a draft (prefixed by <code>_</code>), but I prefer to keep my drafts private until they are ready for publication. Then I can synchronise and edit the posts from whatever device is available.</p>
<p>When the post is ready, I publish it to <a href="https://github.com/gmarty/blog">my blog repo</a> on Github, in the <code>posts</code> folder. The tricky part now is that I need to launch the terminal, navigate to the blog folder on my computer and type:</p>
<pre><code class="lang-bash"><div class="highlight"><pre>git pull <span class="o">&amp;&amp;</span> grunt deploy
</pre></div>
</code></pre>
<p>The Grunt task <code>deploy</code> of Cabin is responsible for generating a static version and push it to the <code>gh-pages</code> branch of the repo.</p>
<p>That&#39;s it.</p>
<h2><a name="wrapping-up" class="anchor" href="#wrapping-up"><span class="header-link"></span></a>Wrapping up</h2>
<p>This blog is powered by:</p>
<ol>
<li><a href="https://stackedit.io/">Stackedit</a></li>
<li><a href="http://www.cabinjs.com/">Cabin</a></li>
<li><a href="https://github.com/gmarty/blog">Github</a></li>
<li><a href="https://www.google.co.uk/search?q=You&#39;re+not+looking+at+the+right+place">Love</a></li>
</ol>
<p>I really wish I were able to optimise the pull/deploy step and call it from any device, but I can&#39;t really think of any free and easy alternative. Do you have any ideas? Use the comments box below and make my life easier :-)</p>
]]></description><link>https://gu.illau.me/posts/the-ideal-blogging-workflow/</link><guid isPermaLink="true">https://gu.illau.me/posts/the-ideal-blogging-workflow/</guid><dc:creator><![CDATA[G.C. Marty]]></dc:creator><pubDate>Tue, 12 Nov 2013 00:00:00 GMT</pubDate></item></channel></rss>