<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Pixelbloom</title>
  <id>http://pixelbloom.com</id>
  <link href="http://pixelbloom.com"/>
  <link href="http://pixelbloom.com/notes.xml" rel="self"/>
  <updated>2013-04-15T00:00:00Z</updated>
  <author>
    <name>Justin Morris</name>
  </author>
  <entry>
    <title>middleman-imageoptim</title>
    <link rel="alternate" href="/notes/middleman-imageoptim/"/>
    <id>/notes/middleman-imageoptim/</id>
    <published>2013-04-15T00:00:00Z</published>
    <updated>2013-04-15T00:00:00Z</updated>
    <author>
      <name>Justin Morris</name>
    </author>
    <content type="html">&lt;p&gt;Last week I had a little hack at building a quick ‘n’ dirty extension to get &lt;a href="https://github.com/toy/image_optim"&gt;image_optim&lt;/a&gt; better integrated into &lt;a href="http://middlemanapp.com"&gt;Middleman&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s face it; serving big, bloated images is for chumps, that’s why the &lt;a href="https://github.com/toy/image_optim"&gt;image_optim&lt;/a&gt; tool is really awesome. However, I wanted a way of getting Middleman to automate running it for me, and better integrate it into the whole &lt;code&gt;middleman --build&lt;/code&gt; workflow.&lt;/p&gt;

&lt;figure class="poster-frame slammed"&gt;
  &lt;img src="/notes/middleman-imageoptim/terminal.png" alt="Optimise!"&gt;
&lt;/figure&gt;

&lt;p&gt;It is already pretty easy to get image_optim to process a bunch of files just by using some bash in a deploy script — you can just have the deploy script run it after it has finished building markup &amp;amp; assets via &lt;code&gt;middleman build&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example;&lt;/p&gt;
&lt;pre class="highlight shell"&gt;image_optim -r &lt;span class="k"&gt;$(&lt;/span&gt;find ./build -type f -iname &lt;span class="s1"&gt;'*.png'&lt;/span&gt; -o -iname &lt;span class="s1"&gt;'*.jpg'&lt;/span&gt; -o -iname &lt;span class="s1"&gt;'*.gif'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&amp;hellip;but this doesn’t really work too well when you are using other tools like &lt;a href="https://github.com/fredjean/middleman-s3_sync"&gt;middleman-s3_sync&lt;/a&gt;, &lt;a href="https://github.com/fredjean/middleman-s3_redirect"&gt;middleman-s3_redirect&lt;/a&gt;, or &lt;a href="https://github.com/andrusha/middleman-cloudfront"&gt;middleman-cloudfront&lt;/a&gt;, which are chained to run after a &lt;code&gt;middleman build&lt;/code&gt; — not much point uploading your images before they have been run through image_optim!&lt;/p&gt;

&lt;p&gt;So I made (the imaginatively titled) &lt;a href="http://github.com/plasticine/middleman-imageoptim"&gt;middleman-imageoptim&lt;/a&gt; gem! It integrates into the Middleman build process so will just be run as a part of constructing, and then deploying the rest of your site.&lt;/p&gt;

&lt;p&gt;Anyway, if big, dirty, sweaty images aren’t your thing and you use Middleman I would love to know what you think!&lt;/p&gt;

&lt;p&gt;Go install &lt;a href="#"&gt;image_optim&lt;/a&gt;, stick the following in your Gemfile;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'middleman-imageoptim'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 0.0.4'&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&amp;hellip;activate the extension (there are lots of options you can play with too — &lt;a href="https://github.com/plasticine/middleman-imageoptim"&gt;check out the repo&lt;/a&gt;);&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;span class="n"&gt;activate&lt;/span&gt; &lt;span class="ss"&gt;:image_optim&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&amp;hellip;and let me know what you think!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Removing tap-delay from iOS WebViews</title>
    <link rel="alternate" href="/notes/removing-tap-delay-from-ios-webviews/"/>
    <id>/notes/removing-tap-delay-from-ios-webviews/</id>
    <published>2013-04-11T00:00:00Z</published>
    <updated>2013-04-11T00:00:00Z</updated>
    <author>
      <name>Justin Morris</name>
    </author>
    <content type="html">&lt;p&gt;Have you even noticed in Mobile Safari (and UIWebViews, and Home screen web-apps) that when you tap a link or button there is a slight delay (300ms to be precise)?&lt;/p&gt;

&lt;p&gt;The reason this exists is as an assistive mechanism for browsing the (very often) touch-hostile web. Interacting with anchors in websites where touch targets are not optimised for small screens and fat fingers can be a frustrating business and this delay/highlight is a method of messaging to the user which link they actually tapped.&lt;/p&gt;

&lt;p&gt;That’s great and all, but what if you are a responsible developer and have accommodated for touch and designed large, tappable targets? Or if you are building a web-app that should look, feel and respond natively?&lt;/p&gt;

&lt;p&gt;This behaviour becomes pretty frustrating in those cases, especially so in the case of a web-app where navigation &amp;amp; interaction is task based and helps maintain the user’s focus on the job at hand.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://nngroup.com/articles/response-times-3-important-limits"&gt;According to Jakob Nielsen&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“1.0 second is about the limit for the user’s flow of thought to stay uninterrupted, even though the user will notice the delay. Normally, no special feedback is necessary during delays of more than 0.1 but less than 1.0 second, but the user does lose the feeling of operating directly on the data.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So in a touch-friendly web-app we really can’t afford to throw an extra 300ms on top of the response time.&lt;/p&gt;

&lt;h2 id="toc_0"&gt;A (kinda) fix&lt;/h2&gt;

&lt;p class="annotation" data-type="Edited"&gt;
I was wrong about removing the delay with just CSS — you actually cannot (which sucks). However, you can help give the impression of a more reactive interface by removing the visual tap cue.
&lt;/p&gt;

&lt;p&gt;Without &lt;a href="https://github.com/ftlabs/fastclick"&gt;using javascript&lt;/a&gt; there is no way to remove the delay completely, however there is a pretty trivial way of giving the perception of the UI being faster with just some CSS.&lt;/p&gt;

&lt;p&gt;By default when a link is tapped UIWebViews render a garbage grey “tap-area” around the hit target, however this can be re-styled to be transparent.&lt;/p&gt;

&lt;p&gt;In completely un-scientific testing (read: ‘IMO’) this definitely gives the impression of a more reactive UI by removing the “I tapped you and now you are just sitting there for 300ms with a janky grey thing hovering over you” experience.&lt;/p&gt;
&lt;pre class="highlight css"&gt;&lt;span class="nt"&gt;-webkit-tap-highlight-color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;rgba&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;-webkit-user-select&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;none&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;-webkit-touch-callout&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;none&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Beware though that &lt;code&gt;webkit-user-select&lt;/code&gt; does exactly what it says on the tin, if you apply that to your HTML tag then &lt;em&gt;everything&lt;/em&gt; on your page is no longer selectable&amp;hellip;probably not what you want.&lt;/p&gt;

&lt;p&gt;To get around this I use this handy little bit of SCSS, which I the explicitly apply where removing delay makes sense (big UI buttons, navigation, etc). Using something like &lt;a href="http://modernizr.com/"&gt;Modernizr&lt;/a&gt; allows you to only apply it to touch devices too.&lt;/p&gt;
&lt;pre class="highlight scss"&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="nc"&gt;.touch&lt;/span&gt; &lt;span class="nv"&gt;%no-tap-delay&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;-webkit-tap-highlight-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="na"&gt;-webkit-user-select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="na"&gt;-webkit-touch-callout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;</content>
  </entry>
  <entry>
    <title>Transitional Interfaces</title>
    <link rel="alternate" href="/notes/transitional-interfaces/"/>
    <id>/notes/transitional-interfaces/</id>
    <published>2013-04-10T00:00:00Z</published>
    <updated>2013-04-10T00:00:00Z</updated>
    <author>
      <name>Justin Morris</name>
    </author>
    <content type="html">&lt;p&gt;I’ve been a pretty big fan of &lt;a href="http://pasqualedsilva.com"&gt;Pasquale D’Silva&lt;/a&gt; for ages, ever since I stumbled across some of his illustrations a few years back — he has an amazingly distinctive style which I really rather like. :-)&lt;/p&gt;

&lt;p&gt;More recently he’s been working as an animator, and today I came across &lt;a href="https://medium.com/design-ux/926eb80d64e3"&gt;an awesome article he wrote on the subject of Transitional Interfaces&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s a &lt;strong&gt;really&lt;/strong&gt; great read. Pasquale highlights the importance of the role that animation &amp;amp; motion plays in creating more engaging, and accessible user-interfaces that guide and inform, by relating animation to real-world concepts of movement.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Folks keep throwing around the word ‘delight’ when referring to animation and cute interactions. Cool and great for those guys. Guess what though? Animation can be used functionally too. It’s not just an embellished detail.”&lt;/p&gt;

&lt;p&gt;“[&amp;hellip;] animation can help to provide context. It helps brains understand how the information flows.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After reading Pasquale’s article I got thinking about how often I actually make the time to really give &lt;strong&gt;detailed&lt;/strong&gt; thought to how animation can help, guide and give context in what I’m working on&amp;hellip;more to the point how I can design UI and animation together to make it relatable to IRL concepts.&lt;/p&gt;

&lt;p&gt;The Web is not a static medium. The way we design for it should not be either.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Ironman Melbourne</title>
    <link rel="alternate" href="/notes/ironman-melbourne/"/>
    <id>/notes/ironman-melbourne/</id>
    <published>2013-03-25T00:00:00Z</published>
    <updated>2013-03-25T00:00:00Z</updated>
    <author>
      <name>Justin Morris</name>
    </author>
    <content type="html">&lt;p&gt;After the last three years of trying to make it to the start-line of another Ironman, I finally managed it this year. It is now the day after &amp;amp; I’m bed-ridden, so I decided to write a race-report!&lt;/p&gt;

&lt;p class="annotation" data-type="Note"&gt;
    This is completely non tech-related in any way, and is pretty long, rambling, and quite possibly incoherent. &lt;strong&gt;You’ve been warned!&lt;/strong&gt; :)
&lt;/p&gt;

&lt;p&gt;I managed to have a really great build up during the few months, then weeks prior to the race. Went in feeling (really) nervous, but pretty confident that I had aced my prep and done all that I could.&lt;/p&gt;

&lt;p&gt;Race morning was a 4am wake-up, to allow for food and then the drive to the race start. I could tell we were in for a pretty epic day early on as even that early the wind was already quite violent and gusty. This was more than confirmed when we arrived in Frankston to be greeted by white-caps and very lumpy surf (&amp;amp; I can call it surf, there was actually someone surfing it).&lt;/p&gt;

&lt;p&gt;Went in and finalised my T1 (bike) transition — tyres, prepped the bike (gearing, etc), and then slowly started pulling the wetty on.&lt;/p&gt;

&lt;p&gt;Was working really hard to stay focussed, get more food down (and keep it down!), and try and get in the zone.&lt;/p&gt;

&lt;h3 id="toc_0"&gt;Swim &lt;span class="im-time"&gt;30:36, 2:02/100m&lt;/span&gt;&lt;/h3&gt;

&lt;figure class="poster-frame"&gt;
    &lt;img src="/notes/ironman-melbourne/swim_warmup.jpg" alt="  Pre swim-start warming up…lots of time to kill with the changed swim course." class="fluid"&gt;
    &lt;figcaption&gt;Pre swim-start, warming up…lots of time to kill with the changed swim course.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Given the conditions the race organisers decided (twice) to shorten and alter the swim course, which also meant that the start time was pushed back a few times to account for the shorter duration. This made for even more standing around waiting…grrr.&lt;/p&gt;

&lt;p&gt;In hindsight I think the decision was a good one (for the sake of safety). The swim was quite simply a meat-grinder. Completely insane.&lt;/p&gt;

&lt;p&gt;A combination of 2200 competitors, a mass and ungraded start, very hard conditions (wind, surf and strong cross beach current), and a shorter duration tells you all you need to know. I personally saw 3 people hauled out of the water by life-guards during the 1.9km, and would not be surprised if there were more than a few black eyes and broken noses.&lt;/p&gt;

&lt;p&gt;Personally I was really, really unhappy with my swim. Normally I really like the swim leg as it really rewards stronger swimmers over the longer duration and allows you to set the tone onto the bike (i.e beat the masses out of the water, through T1 and onto the bike — huge advantage). Today I just got absolutely beaten up. I copped elbows twice that had me seeing stars, and found swimming through the crowds and surf to be really frustrating. No ability to actually put your head down and swim. Very start/stop. I also swallowed so much sea water that I vomited twice. Eww.&lt;/p&gt;

&lt;p&gt;Just to cap it all off I got caught out in the crowds and by the current and exited the water about 400m the wrong way down the beach, making for a long, wet-suit clad run-of-shame into T1.&lt;/p&gt;

&lt;p&gt;If I had to run the race again I would take 3.8km of calmer water over the 1.9 kilometers of chaos. Easy decision. The average pace tells the story—in normal conditions I would usually average 1.30-40/100m for the full 3.8km, but could only manage 2.02/100m for 1.9km. Yikes, not a great way to start the day.&lt;/p&gt;

&lt;h3 id="toc_1"&gt;Bike &lt;span class="im-time"&gt;5:16:27, 34.13 km/h&lt;/span&gt;&lt;/h3&gt;

&lt;figure class="poster-frame"&gt;
    &lt;img src="/notes/ironman-melbourne/bike.jpg" alt="Half way through the bike, Frankston turn-around." class="fluid"&gt;
    &lt;figcaption&gt;Half way through the bike, Frankston turn-around.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p class="annotation" data-type="Note"&gt;
    Bike leg on Strava: &lt;a href="http://app.strava.com/activities/45757404"&gt;http://app.strava.com/activities/45757404&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Came out of the water pretty mad and with a point to prove. I also knew that I would be moving through some pretty serious traffic given my swim and would need to put the hammer down in order to get any clean air and be able to focus.&lt;/p&gt;

&lt;p&gt;The outward trip on the first lap was against the wind, but I worked solidly and basically just sat right and passed a pretty steady stream of people on my left. I was aware that I was working a little above what I would have ideally paced myself at, but I was convinced that the trade off would be worth it to move up the field, just so long as I was careful not to push too hard.&lt;/p&gt;

&lt;p&gt;This was working really well until I was swept up by a big (50-60 riders) group that were quite blatantly all drafting (I saw at least 5 groups like this).&lt;/p&gt;

&lt;p&gt;These guys were riding wheel to wheel, half of them freewheeling at 35km/hr into the wind. This was really infuriating as their pace was yo-yoing as they “rolled turns”, and was making life really hard for me as I was keeping my draft-box off the back to zone in and ride my pace.&lt;/p&gt;

&lt;p&gt;They were essentially just riding a 180km crit race. You really have to wonder what these dickheads were playing at—the whole point of an IM is that it is a solo affair. What made matters worse was that there was actually a TO (technical official) sitting alongside these wankers who was doing nothing about it.&lt;/p&gt;

&lt;p&gt;Shortly after this I had words with the TO (who unwilling to take control of the situation—these guys should have been penalised &amp;amp; then DQed). Shortly after that I cracked it and lifted my pace again to ride around the bunch and off the front.&lt;/p&gt;

&lt;p&gt;This happened several more times (get caught by the bunch, get angry, ride away, rinse/repeat) until we hit the tunnel. I knew these jokers would be messing about in the tunnel not wanting to work, and that the bunch would probably fracture on the climb out of the tunnel. I made sure to leave it in the big ring and ensured that I had enough of a margin that I didn’t have to see them again.&lt;/p&gt;

&lt;p&gt;The ride south was awesome, sitting on 60km/hr for long stretches on a TT bike, with carbon tubulars singing underneath you is pretty awesome. :) Averaged a shade over 40km/hr for the return.&lt;/p&gt;

&lt;p&gt;Lap two was more of the same, though I finally had enough room to pace properly. I was more disciplined about heart-rate for this 90km, though I could feel some of the unwanted efforts of the previous 90km in my back and legs. Still managed to ride strongly, especially given that the wind started to swing west during the outward journey and turned into a pretty brutal cross wind. Not a day for a disc. I was being blown meters sideways even just on my 90mm rims. Scary stuff. Was having to be opportunistic about using the TT bars.&lt;/p&gt;

&lt;p&gt;Spent the last 20km of this lap starting to warm the legs up for the marathon, trying to match bike/run cadence, stretch back and shoulders, and get last minute food down.&lt;/p&gt;

&lt;h3 id="toc_2"&gt;Run &lt;span class="im-time"&gt;4:02:50, 5:45/km&lt;/span&gt;&lt;/h3&gt;

&lt;figure class="poster-frame"&gt;
    &lt;img src="/notes/ironman-melbourne/run.jpg" alt="About 10 meters to go. Best 10 meters EVER." class="fluid"&gt;
    &lt;figcaption&gt;About 10 meters to go. Best 10 meters EVER&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p class="annotation" data-type="Note"&gt;
    Run leg on Strava: &lt;a href="http://app.strava.com/activities/45758380"&gt;http://app.strava.com/activities/45758380&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;The first 20km of the run were simply magical. I was feeling a million bucks. I think my first couple of kays were pretty close to being sub-four-minutes, and I was really having to put the brakes on and not be too silly. Loving it. I managed to settle down a little by about the 5km mark into a nice gait and was feeling really comfortable with a ~4:50min/km pace.&lt;/p&gt;

&lt;p&gt;I was conscious that due to the really strong winds on the bike some of my food and fluid intake had been compromised (I missed a bottle and 2 gels on the bike), so I was making an effort to really utilise the aid-stations to make sure that I was properly fuelled. However I might have overcompensated slightly as I was starting to get some minor stomach cramps around 17km.&lt;/p&gt;

&lt;p&gt;Coming into Mordy across the bridge things started to go down hill—just as the camber on the road reversed (Franga-&amp;gt;Mordy was all in one direction in the outside lane) my left foot exploded with cramps. I pushed on from there until the next aid station were I ate about half a kilo of raw vegemite (delicious). Over the next few aid stations and about the next 8km I was really battling with various mutinous limbs. I was throwing down pretty much all the fluid I could get my hands on, despite still having a very upset stomach.&lt;/p&gt;

&lt;p&gt;I finally managed to get the cramping under control but by this point my previous good pace was broken, and I was also now battling with really nasty stomach cramps and some nausea.&lt;/p&gt;

&lt;p&gt;The rest of the run saw me struggling along trying as hard as possible to keep the pace up, and see-sawing between going hunger-flat and my stomach rebelling. The last five kays I couldn’t have blown out a candle—I had absolutely nothing left and the only thing keeping me from walking it out was the proximity of the finish line. There was some pretty serious internal-monologue/confirmation stuff going on for this last bit. The faster you run the faster you’re done. :)&lt;/p&gt;

&lt;p&gt;Hitting St Kilda was obviously awesome, and running those last two hundred meters down the chute was just an amazing flood of relief, happiness and satisfaction that I left it all out there. The icing on the cake was a 9:59:56 hour day. Couldn’t be happier.&lt;/p&gt;

&lt;p&gt;Lastly I just wanted to say a really massive thank you to all the people that came along on the day. I can’t even begin to tell you how much it helps seeing a familiar face or having someone yell out support on such a long day. Thanks! &amp;lt;3&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>TIL: AirBnB tech-talks are awesome</title>
    <link rel="alternate" href="/notes/til-airbnb-tech-talks-are-awesome/"/>
    <id>/notes/til-airbnb-tech-talks-are-awesome/</id>
    <published>2013-03-18T00:00:00Z</published>
    <updated>2013-03-18T00:00:00Z</updated>
    <author>
      <name>Justin Morris</name>
    </author>
    <content type="html">&lt;p&gt;&lt;strong&gt;TIL:&lt;/strong&gt; The &lt;a href="https://www.airbnb.com/techtalks"&gt;AirBnB tech-talks site&lt;/a&gt; (all the videos are &lt;a href="http://www.youtube.com/playlist?list=PLECD54527EBCE4021"&gt;on YouTube too&lt;/a&gt;) is pretty awesome! I don’t know how I managed to miss it for so long—they host a regular tech-talk by someone interesting every fortnight, and then make the video available for everyone—cool stuff!&lt;/p&gt;

&lt;p&gt;This morning I watched &lt;a href="http://www.youtube.com/watch?v=ipgo93g4Xak"&gt;the latest talk&lt;/a&gt; “Dive Into Performance” by &lt;a href="http://stevesouders.com"&gt;Steve Souders&lt;/a&gt; (&lt;a href="https://docs.google.com/a/pixelbloom.com/presentation/d/1ZZfy5zKx8cYSMGoi2QzM3viI6RUEWbV6S98yTfF5i0o/edit#slide=id.p"&gt;he also made the slides available!&lt;/a&gt;).&lt;/p&gt;

&lt;figure class="poster-frame"&gt;
    &lt;iframe width="853" height="480" src="http://www.youtube.com/embed/ipgo93g4Xak?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;/figure&gt;

&lt;p&gt;It runs a little over an hour, and is packed with awesome knowledge that you should probably try and jam into your skull. Some of it is pretty common-sense type stuff but there are some real gems in there.&lt;/p&gt;

&lt;h6 id="toc_0"&gt;A few of the things I picked up;&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html"&gt;The nav timing spec&lt;/a&gt; (&lt;code&gt;window.performance&lt;/code&gt;) is &lt;strong&gt;full&lt;/strong&gt; of awesome information (all good browsers but only Chrome flavours of Webkit—WTF Apple?). MDN has &lt;a href="https://developer.mozilla.org/en-US/docs/Navigation_timing"&gt;some more interesting reading&lt;/a&gt; too.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://webpagetest.org"&gt;webpagetest.org&lt;/a&gt; is even more amazing than I thought. You always learn a lot watching power-users, Steve is a Webpagetest.org power-user. This is a must for squeezing free speed out of your app/site.&lt;/li&gt;
&lt;li&gt;Browser asset load order is != to document order. Modern browsers use speculative look-ahead parsing of a the document while blocked (say while waiting on a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag) to actually eagerly-load content “further down” the document. Crazy stuff! According to a quote from Steve during his talk, the Chrome team attribute a ~30% page speed increase to this.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Fever on Heroku</title>
    <link rel="alternate" href="/notes/fever-on-heroku/"/>
    <id>/notes/fever-on-heroku/</id>
    <published>2013-03-16T00:00:00Z</published>
    <updated>2013-03-16T00:00:00Z</updated>
    <author>
      <name>Justin Morris</name>
    </author>
    <content type="html">&lt;p&gt;So yesterday brought the sad news that Google Reader is being killed off. C’est la vie it seems, given it was a Google product. In my search for an alternative I rediscovered &lt;a href="http://feedafever.com"&gt;Fever&lt;/a&gt; and decided to see if I could run it up for free on Heroku. Onwards…&lt;/p&gt;

&lt;p class="annotation" data-type="Be advised"&gt;
Unfortunately there were more issues than I first thought with the licensing built into Fever and getting it to play nice in a filesystem-less environment like Heroku. The below steps will work just fine, however you will be left having to re-activate Fever every time your dyno goes away (thus blowing away the in-memory downloaded activation). Sadface.
&lt;/p&gt;

&lt;p&gt;Personally I think the news about Reader is quite sad, as I would quite happily have paid for it as a service. In fact I like RSS so much that I actually shelled out the $30 for Fever when it first came out years ago (I was also pretty massive &lt;a href="http://shauninman.com"&gt;Shaun Inman&lt;/a&gt; fanboy if I’m being honest).&lt;/p&gt;

&lt;p&gt;I ended up setting Fever aside because screw having to manage self-hosting for PHP and MySQL, right?&lt;/p&gt;

&lt;p&gt;If you’re new to Fever I recommend going and checking it out, but also reading &lt;a href="http://www.shauninman.com/archive/2013/03/14/fire"&gt;the post in response to the Google Reader announcement by Fevers author, Shaun&lt;/a&gt;, for a good list of what Fever is and isn’t.&lt;/p&gt;

&lt;p&gt;Enough jibba-jabba!&lt;/p&gt;

&lt;h2 id="toc_0"&gt;Let’s turn up the heat!&lt;/h2&gt;

&lt;p&gt;OK, so I’m going to go ahead and just assume that if you’re reading this then you are already probably familiar with &lt;a href="http://heroku.com"&gt;Heroku&lt;/a&gt; and already have an account and their toolchain already set up on your machine (for the sake of not having a bad time I’m also going to assume you are not using Windows, because LOL).&lt;/p&gt;

&lt;p&gt;There are unfortunately several extra steps to getting the Fever app set up on Heroku. The design of Fever’s setup is such that it actually downloads itself during setup. Weird stuff. I guess this is some sort of code obfuscation(?), but all of this code can be acquired prior to entering your activation anyway…&lt;/p&gt;

&lt;p&gt;Anyway, this all creates something of an issue when you are looking to deploy to an environment that doesn’t have a writable file-system…like Heroku.&lt;/p&gt;

&lt;p&gt;The way to get around this is to go through the setup process right up until activation on your local machine—at which point the you have all the app code—then just commit this code and push that up to Heroku.&lt;/p&gt;

&lt;p&gt;If you just commit the bootstrapping stuff and then run the setup on Heroku the app will run just fine…right up until the dyno is recycled, at which point the code disappears, your app breaks.&lt;/p&gt;

&lt;h3 id="toc_1"&gt;Local stuff&lt;/h3&gt;

&lt;p&gt;First up we need to make a local repo for Fever to live in and for us to deploy to Heroku from.&lt;/p&gt;

&lt;p&gt;Let’s open Terminal and mash some keys!&lt;/p&gt;
&lt;pre class="highlight shell"&gt;mkdir fever
&lt;span class="nb"&gt;cd &lt;/span&gt;fever
git init .
&lt;/pre&gt;
&lt;p&gt;…while we’re at it let’s create a new Heroku app!&lt;/p&gt;

&lt;p&gt;Running PHP on Heroku is not officially supported, but it  is easy, thanks to &lt;a href="https://github.com/iphoting"&gt;iphoting’s&lt;/a&gt; awesome PHP + nginx, etc… custom buildpack.&lt;/p&gt;
&lt;pre class="highlight shell"&gt;heroku create -s cedar -b git://github.com/iphoting/heroku-buildpack-php-tyler.git
&lt;/pre&gt;
&lt;p&gt;…and now we’ll grab the Fever bootstrap code and commit it. We also need to add an empty &lt;code&gt;index.php&lt;/code&gt; file to the root of our app. This is required as this is how Heroku will identify it as being a PHP deployment…&lt;/p&gt;
&lt;pre class="highlight shell"&gt;wget http://feedafever.com/gateway/public/fever.zip
unzip fever.zip -d . &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm fever.zip
touch index.php
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;?php header(&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;Location: /fever/&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;); ?&amp;gt;&amp;quot;&lt;/span&gt; &amp;gt; index.php
git add -A .
git commit -m &lt;span class="s2"&gt;&amp;quot;Added Fever bootstrap code, Heroku index.php&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Next up you’ll need to load up the app locally in your browser (you will need a way of running PHP/MySQL locally, just grab &lt;a href="http://mamp.info/en/mamp/index.html"&gt;MAMP free&lt;/a&gt;), and jump over to &lt;code&gt;/fever/boot.php&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Jump through all the setup steps until you get to the database setup stage. Throw in your local MySQL details (you’ll need to create a temporary DB, don’t worry we’ll delete it all later).&lt;/p&gt;

&lt;p&gt;At each stage here the boot script is downloading more of the actual fever app, once you get to the section where it asks you to activate Fever you have all the core code needed to run the app.&lt;/p&gt;

&lt;p&gt;The last thing we need to so is throw in the actual settings for our Heroku MySQL database and replace out the local settings we used when running setup.&lt;/p&gt;

&lt;p&gt;Before we can do that though we need to add a MySQL addon to our app:&lt;/p&gt;
&lt;pre class="highlight shell"&gt;heroku addons:add cleardb:ignite
&lt;/pre&gt;
&lt;p&gt;Once that’s done, we can grab our DB config details by running the following:&lt;/p&gt;
&lt;pre class="highlight shell"&gt;heroku config | grep CLEARDB_DATABASE_URL | cut -d &lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt; -f2 | php -r &lt;span class="s1"&gt;'$conn=&amp;quot;&amp;quot;; $in=fopen(&amp;quot;php://stdin&amp;quot;, &amp;quot;r&amp;quot;); while(!feof($in)){ $conn=$conn . fgets($in, 4096); } print_r(parse_url($conn));'&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Note that &lt;code&gt;path&lt;/code&gt; is the database name, just leave out the &lt;code&gt;/&lt;/code&gt; at the start.&lt;/p&gt;

&lt;p&gt;You then need to add these credentials to &lt;code&gt;./fever/firewall/receipt_db.php&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once this is all done:&lt;/p&gt;
&lt;pre class="highlight shell"&gt;git add -A .
git commit -m &lt;span class="s2"&gt;&amp;quot;Fever setup complete&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;…and deploy!&lt;/p&gt;
&lt;pre class="highlight shell"&gt;git push heroku master
&lt;/pre&gt;
&lt;p&gt;Once the post-recieve hook has finished up (it will do a bunch of stuff to pull down binaries for our buildpack) you should be able to load up the app:&lt;/p&gt;
&lt;pre class="highlight shell"&gt;heroku open
&lt;/pre&gt;
&lt;p&gt;Awesome—you should now have Fever up and running! You just scored a very capable RSS reader for the worth-while one-off cost of $30m and set up free managed hosting for it for eternity (or until Google buys Heroku and then shuts them down ;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get reading!&lt;/strong&gt;&lt;/p&gt;

&lt;hr&gt;

&lt;h4 id="toc_2"&gt;Bonus Round!&lt;/h4&gt;

&lt;p&gt;By default Fever will refresh feeds on page load, however they do provide a method for triggering a refresh via a web-hook, which you can hit from a cron task.&lt;/p&gt;

&lt;p&gt;If this sounds like something you might be interested in then install and configure the Heroku scheduler addon:&lt;/p&gt;
&lt;pre class="highlight shell"&gt;heroku addons:add scheduler:standard
heroku addons:open scheduler
&lt;/pre&gt;
&lt;p&gt;You’ll want to set the command field to:&lt;/p&gt;
&lt;pre class="highlight shell"&gt;curl -L -s http://YOUR_HEROKU_APP/fever/?refresh
&lt;/pre&gt;
&lt;p&gt;Save and you’re done.&lt;/p&gt;
</content>
  </entry>
</feed>
