I like to make software that is fun and good looking.

Thu September 02

What to drink on Thursdays?

I’ve been making a real effort to avoid coffee in the afternoon. I’ve made the discovery that although the first cup of coffee in the morning is awesome, afternoon coffees are just that ‘cup of stress’ that my vegan friends talk about.

So I made myself a handy guide to what I should drink, hour by hour, on Thurdays.

Tea... Wins!

The beer is optional, although I was planning on catching up with Herr Schommer after work.

Wed September 01

Polygons and postgis

I use postgis extensively in my geo-local development. If you’re working on a project that involves geo data and you haven’t seriously looked into postgis, you’re doing yourself a disfavour.

Postgres is really quite epic.

We used the C++ API to make a xapian plugin for zoomin, back in the day before tsearch2 became integrated into Postgresql.

Twitterplaces

Sam asked that I add polygons onto my twitterplaces maps, so that he could see where the boundaries of a neighbourhood are.

South of Mission on Twitterplaces

The twitter places API gives you the bounding boxes of a place, so I already had the information, it was just a case of how to store the bounding boxes. I decided to do it properly and use spatial_adapter and a :polygon column in my places table.

This meant I could use a method like so:

def bounding_box=(params)
  points = []

  params['coordinates'].first.each do |c|
    points.push GeoRuby::SimpleFeatures::Point.from_x_y(c.first, c.last)
  end

  self.latitude = points.collect(&:y).sum / points.length
  self.longitude = points.collect(&:x).sum / points.length

  c = params['coordinates'].first.first
  points.push GeoRuby::SimpleFeatures::Point.from_x_y(c.first, c.last)
  self.geom = GeoRuby::SimpleFeatures::Polygon::from_points([points])
end

To convert twitters json representation of a place into a WKRT geometry object in my database. This is cool, because then I can use some coffeescript like this to draw the polygon onto my maps.

if $place.geom.rings
  points = []
  bounds = new google.maps.LatLngBounds

  for point in $place.geom.rings[0].points
    coord = new google.maps.LatLng(point.y, point.x)
    bounds.extend coord
    points.push coord

  if bounds.toSpan().lat() == 0.0 or bounds.toSpan().lng() == 0.0
    marker = new google.maps.Marker {
      map : map
      position : bounds.getCenter()
    }
  else
    poly = new google.maps.Polygon {
      paths : [points]
      map : map
      strokeColor : '#ff0000'
      strokeOpacity: 0.5
      fillOpacity : 0.1
      fillColor : '#ff0000'
    }

That code also checks whether the polygon is degenerate (of zero size), and then plots a marker instead. Twitter always sends polygons, even if the polygon has zero area. Anyway. So this was all nice and took 15 minutes to code up. But it also let me do something super awesome:

def find_child_pois
  Place.find(:all, :conditions => ['kind = ? AND st_contains(?, geom)', 'poi', geom])
end

I now have a method to find all places contained inside a place. So for example, South of Mission in San Francisco, has Adobe Systems inside of it. You can also find out which places contain this one - for example:

>> Place.find_by_path('sfo/soma').find_parents.collect(&:name)
=> ["San Francisco", "SoMa", "California"]

I was pretty excited when all this came together so well. When I’ve got more time, I’d like to fix up the crawler that feeds twitterplaces, since at the moment it just dumps the database and recreates it every hour from a sampling of the twitter firehose.

Ah - for more good hours in the day.

Mon August 30

Agile board in html5

I put this together as a quick prototype of what an agile board in HTML5 could look like. I’m not a huge agile fan myself, but since I keep having to use pivotal tracker in projects - I’m always tempted to do a little bit more work on it and get it to a usable state.

Sun August 29

Batched save ruby module

In my work on twitterplaces - I’ve been commonly importing several thousand tweets at once from the streaming API. As I re-write my import process, I have to re-run this import job, so I’ve been trying to get it as fast as possible. Currently what I do is:

Batched save is my module I created to let you include BatchedSave in a model, and then when you save a new record - it’ll batch up 100 records and use COPY to insert them. It is for postgresql only, and obviously only works in situations like mine where the data isn’t self-referential, but it’s mega fast.

Fri August 27

My 10k submission was accepted

Woohoo! Please go vote now! It’s a bit lame they’ve got the unsexiest screenshot first, but… yay!

My entry in the official 10k gallery

There is a community prize that you win by getting the most votes - so if you like my submission, please spread the word.

Thu August 26

All done - in under 10240 bytes

Well, it’s done. I just submitted my entry to the 10k apart competition. It’s been a pretty intense 24 hours, but I’m glad I gave myself some extra time this morning to polish up my entry.

Planning a trip to Paris, a screenshot from an earlier build

You can try it out here - all 9766 bytes of it.

Toolchain

I built the app using:

I have some extra code that is commented out, that does an autocomplete from Wikipedia when you add a new destination to your trip. So for example, you could type ‘Montmar’ and get an autocomplete for Montmartre. It’s nice because a I’m not very good at french spelling and b you automatically get some description text of the place from Wikipedia.

I also removed a column on the left that let you organise trips to different cities. I probably would’ve been pushing the 10k limit had I kept adding features, but mainly I didn’t have time to build and test the features properly. I enjoyed having time today to add some extra destinations to the trip, change the dates a little, and test the app thoroughly on each of the browsers.

Compression

I’d like to thank Nihilogic for their awesome canvas compression technique. Because I could compress the javascript and css so effectively, I didn’t have to muck around pruning bytes from my css and javascript, which meant I could spend more time polishing the app.

For reference - here’s the breakdown of the sizes of my CSS at different stages of my development pipeline. I used a simple bash script to compile, compress and package everything.

|              | Source | Comp  | Opt  | PNG  |
| Less CSS     | 7143   | 7589  | 5961 | 1898 |
| Coffeescript | 11388  | 13742 | 9445 | 3879 |

Internet Explorer 9

It’s been an interesting experience using IE 9. It looks like it’s going to be a good browser. I will still use Safari as my main browser and development tool (even if they did release IE9 for mac), but it looks like I’ll be supporting Safari 5, Chrome, Firefox 3.5 and IE 9 in all my future web apps.

Thanks

I’d like to thank @sminnee, @ristari, @nzkoz, @clarketus, @nikz, @agrath, @terrcin, @lancehodges, @youdoham, @nazdrug and @campbell for their support, feedback and bug checking while I put this thing together. I couldn’t have got it done without you all, thanks.

Wed August 25

Why not consult?

In the preparation for my leap back into the world of start-ups, I’ve been wondering why I don’t prefer to consult full-time. Consulting has a bunch of pros:

  1. Excellent pay
  2. Challenging projects
  3. Turn your brain off at 5pm

It struck me today - that the main reason I don’t enjoy doing javascript / rails consulting is because I can’t do it all day long. I can do 4-5 hours of it and stay in flow, but after that it’s a real struggle. Sure I can churn out more code and fix bugs, but I’m not being creative, I’m overexercising the part of my brain that writes code.

And in a small business, that’s the perfect time of day to put away your text editor, open up skype, imovie and mail.app, and start down some of that marketing work.

I think this all comes back to Heinlein.

Specialization is for Insects

I want to be able to play the cello, climb a multipitch, fix a car, nurse a child, write a book, rally a crowd, run a marathon, pontificate on a beer, console a friend or any of a million more things.

Small business takes away your safety net, but it lets you try out as every act in the circus.

Tue August 24

My 10k apart submission

I haven’t had much time to look at the Facebook Places API, but I have been working on my 10k apart submission. This competition challenges you to build a functioning web app in only 10 kilobytes of javascript, html and css.

I’ve decided to take an idea I’ve had kicking around (a trip planner for weheartplaces) and see if it can be polished up to fit into the 10k limit.

Planning a trip to Paris, a screenshot from earlier this morning

Using the command ls -l *.css *.js *.html | awk '{sum+=$5} END {print sum}' to sum up the bytes, I’m already up to 12k of content for the unoptimized code.

I’m aiming to keep the entire project under 20k in unoptimized form, which will hopefully make the 10k limit achievable. Coffeescript and less output is quite verbose - and will benefit from closure and the YUI compressor.

Wish me luck. The deadline is lunchtime tomorrow (NZDT).

Mon August 23

A varied gym schedule

Like some web developers, I’m a bit ADD, so I find going to the gym a bit of a chore. Don’t get me wrong. I love the exercise, the clear headedness afterwards, the more energy you have in every day, the rest for your mind - a blissful 45 minutes where your brain doesn’t have to analyse pixels on a screen, or type strange patterns into the keyboard.

But spending 45 minutes with no mental stimulation - how dull is that! Especially when you go to the gym at quiet times (I don’t like noisy gyms), there’s not even anyone to talk to.

So my workout which is nice and varied is like so:

  1. 3km rowing ~12 minutes
  2. Situps, pushups and chins x3 sets ~15 minutes
  3. Treadmill on hilly mode ~15 minutes

I find the treadmill the hardest, since it’s just so dull - but I take it as a nice time to be all Zen (after the half an hour of exercise I find my inner Zen-buddha is easier to access). I set the treadmill to ‘randomly changing gradient’, so that your heart rate is constantly moving up and down.

Anyway - that works for me, and I’ve found it an easy workout to do consistently 4 times per week

Fri August 20

Analyzing a places page

Since Facebook places isn’t available outside of the US yet - I’ve only had two options for exploring the places api.

Firstly - my good friend loliver moved to Palo Alto two months ago to work for Wildfire, so I’ve been following his checkins.

Wildfire HQ Places page

I love the design, it’s nice and simple, has a strong social component (with the facebook wall), had a piece of content in the middle of the page (the map), some stats on the left to get an idea of the popularity of this place - and then a list of people who have checked in there which gives some ‘explorability’ to the places pages.

They don’t have ‘nearby’ or ‘similair’ places, but that might just be because it’s new and not enough of my friends have checked into multiple places.

Proxies and geolocation hacks

The other way I’ve been trying out the facebook is by proxying my requests through my US servers (which doesn’t seem necessary now that they’ve deployed the places functionality worldwide). The only downside is that when your browser tries to geolocate you, Facebook works out you’re not in the US and gives up.

The next trick for Monday will be to make a greasemonkey script that emulates the W3C geolocation API and let’s you check friends into Kentucky strip clubs.

Thu August 19

Facebook Places

I’m really excited about the release of Facebook Places. It’s not widely available yet but it should be rolled out to American Facebook users over the next 24 hours.

Facebook places on the iPhone

The features:

  1. Checking in to places, for where you are at the moment
  2. Tagging friends as being with you at a place
  3. Seeing where your friends are and have been
  4. An extensive API for accessing a users places data

It’s number 4 that’s exciting to me. Facebook gives a bunch of examples of ways the API could be used - including:

A travel application that gives people the ability to see which of their friends have already been to the place they are visiting.

That’s kind of exactly what I’ve been building. Starting next week, I’ll be working on the re-release of weheartplaces, integrated with the Facebook Places api.

Wed August 18

We Heart Nokia

I’m excited to announce that weheartplaces will be available for Nokia Series 60 phones, as well as the iPhone and Android.

I’ll be using the Nokia Webruntime (WRT 1.0), a browser-based environment that effectively allows you to create web/javascript programs that masquerade as normal symbian applications. I’ve just been testing out the functionality of my Nokia 6220, which is a $150 phone with 3G, GPS, driving directions and a 5 megapixel camera.

I got the icon going! That's like 80% of the work right there.

I’m not sure of the release date yet - but when it’s ready it’ll be available at my publishers page on the Ovi store.

Tue August 17

To Market!

Are you in Wellington and are serious about starting a tech business? I got an email from the bright ideas challenge with information about the following presentations, from various technical and business development peoples. I’ll be attending these three…

Strategy

Value proposition, business model, pricing model, finances and sustainability - Monday, 30 August 2010.

Technical

Intellectual property strategy, legal and governance, prototyping and funding options - Monday, 6 September 2010.

Go-to-Market

Go-to-market strategy, branding, exporting and distribution - Wednesday, 8 September 2010.

All events are held 4.30-6.30pm in the Memorial Theatre, Victoria University of Wellington. That marketing one sounds especially interesting.

Mon August 16

Weird bug of the day

On Safari, it’s nice to use ellipsis to limit the length of text. However, a warning to young players - text-overflow: ellipsis doesn’t work with webfonts.

Correctly functioning ellipsis stylingWhen using a webfont, Safari gives up, it's all too hard
Sun August 15

Hey what does this button do?

I’ve used photoshop for years and consider myself an intermediate user. You end up using photoshop a lot in webdesign to slice stuff up, or create decent logos - and prior to CSS3 it was my number one gradients tool. However - there’s a bunch of stuff photoshop doesn’t do.

With the advent of resolution-independent interfaces (retina display, next version of os x, landscape and portrait views of a site) and the need to create business cards, flyers, stickers and pixel art for websites - I’ve been learning Adobe Illustrator.

While playing with the weheartplaces logo - I discovered this menu item:

Hey - what does this effect do?Houston. We have a logo.
Sat August 14

Logo Design

I’ve been working on logos and design rules for Weheartplaces, creating dozens of Artboards in illustrator. I’m not a designer by trade, so some of my design is a bit stilted, but bear with me and eventually there might be a nice logo and style for the site.

Dax, probably too strong a shadow.Eurostile, going cold on this one.Oh, hai Steve.The Scott Pilgrim special, plus Illustrator gradients.For legal correspondence only.
Fri August 13

Push state and Node.js

I’ve talked with Sam Minnee (CTO at Silverstripe) a bunch of times about running jquery on the server side. It was only a hunch, I never knew exactly what the benefits would be - but with the availability of pushState on Firefox, Safari and Chrome - it suddenly makes a lot of sense.

What pushState and jquery on the server lets you do - is to have a pure javascript application that doesnt require page reloads to go to different urls. For example:

  1. http://yourapp.com/
  2. http://yourapp.com/search
  3. http://yourapp.com/search/myterms
  4. http://yourapp.com/tweet/12345

Can all be generated client side by your jquery and coffeescript code. This is an awesome way to write an app, you get a good responsive app and it’s easy to persist state between pages (eg your google map won’t spring back to the default location everytime you click ‘back’).

The number one downfall of javascript apps, is that there are now pages in your app that can’t be linked to - nor can they be crawled by google, or scraped by any other site that uses the http protocol. Building exciting new apps that ‘break the internet’ isn’t cool.

But if you can run your entire app on the server side - then if someone goes to http://yourapp.com/search/myterms - node.js can load your page on the server, recognize the url, run the correct javascript code to update the state as the browser would - then send it down the wire. So that non-javascript clients can access the same content that a desktop browser can.

It’s a whole new way to do accessibility.

Thu August 12

Facebook places

This analysis by Gigaom is interesting to me. I’m really keen to see what Facebook does with places. What they’ve done so far has been underwhelming technically, but has seen impressive takeup.

For example - try searching for Hashigo Zake (a Wellington beer bar popular with early adopters / geeks) on various services:

Facebook has such massive uptake, that whatever it does has an impact. The understanding, technology and devices behind ‘location based’ services are so widespread that it’s really a case of Facebook just providing the tools and they’ll probably dominate existing location based services.

Also - note that all of the sites have reasonably terse (or even descriptive) URLs. All except Google. They really don’t get clean URLs.

Wed August 11

Make LESS less painful

I’ve been using LESS to make writing css for a jqtouch app less painful. However - the less compiler is a bit awkward to use by default - if you run:

lessc -g -w *.less

It recompiles your scripts everytime you make a change, which is perfect, and it notifies you by growl if you have a syntax error - wonderful.

However - every time you get a syntax error, it also blocks the terminal that you launched less from, and you have to go to that terminal and ‘Press [return] to continue…’. It’s pretty annoying. The solution is to load up /Library/Ruby/Gems/1.8/gems/less-1.2.21/ in your text editor, search for command.rb, and change the run! method, to disable the $stdin.gets and replace it as so:

# File has changed
if (not File.exists?( @destination )) or File.stat( @source ).mtime > File.stat( @destination ).mtime
  print Time.now.strftime("%H:%M:%S -- ") if @options[:timestamps]
  print "Change detected... "

  if parse
    # ...
  else 
    `touch #{@destination}`
  end
end

I also set the growl.priority to 1 in err(...) to make my notifications show up in red.

growl.priority = 1

You then get growl notifications on error, but simply correct the error and hit save again to recompile. No more hunting to find the right terminal.

Mon August 09

CoffeeScript 0.9

CoffeeScript 0.9 was released over the weekend. CoffeeScript is a compiler that turns .coffee files into .js files. CoffeeScript is a significant whitespace, rubyish language that makes large (and small) javascript projects much more manageable and fun.

I’ve been using CoffeeScript since 0.5, first with a multiplayer javascript game experiment, then more recently as part of my consulting with Lonely Planet Labs. It’s been interesting working with multiple developers on CoffeeScript - and seeing how it works in a production environment. I can heartily recommend it to teams that are looking to ease their javascript development.

CS 0.9 is a big change from 0.7.2, read this ticket for some of the background on the change. My own reaction to the change is interesting - I was against the change at first, and only changed my mind after 0.9 was released. I was impressed by how Jeremy got opininions and analysis from all the existing users, then quickly made such a fundamental change to the language, let people try it out in a branch - and finally decided to merge it back into stable.

All this - despite the fact that upgrading most coffeescript apps to 0.9 is non-trivial. Changing the symbol used for assignment will probably break most existing code. The assignment change was required to bring in yamlish object assignment which is awesome. The new release also has a host of other, non contentious improvements, around superclasses.

I think it’s a good reminder, that no matter how substantial a change - if you manage is right, and the benefits outweigh the costs, your community will adapt and embrace the new version.

Sun August 08

Safari Extension

I’ve been working through the extension authoring documentation for each of the browsers. I was excited when I got my little icon showing up in the Safari toolbar for the first time:

Weheartplaces toolbar button
Thu August 05

Design features

While redesigning this blog (I love being able to edit css and template as easily as blog posts, go github pages!), I found myself turning this:

Ordered chronologically

Into this:

Ordered by aesthetic

I find the wave a lot more pleasing to the eye, and I still kept the primary order mostly intact. This is one of my design tenets - lay out the page by weight and balance, then work out what text you can fit into each of the boxes.

It’s almost the opposite of how the signals do design, but I love it.

Wed August 04

Brewdog Punk IPA

I just discovered the awe inspiring flagstaff cellars, which is a tucked away little beershop in an unassuming corner of Melbourne.

The thing about this place though, is that is a stocker of Brewdog, Rogue, Epic and a number of good Australian beers - such as Matilda Alpha, Little Creatures and Moo Brew.

Anyway - they had this beer on special - Punk IPA by Brewdog, so I bought two and came home and tried them.

A very good beer.

The internet website rate beer said good things about the Punk IPA, although the haters at beer advocate weren’t so enamoured. The guy who drunk a Punk IPA that was 12 months past it’s best date - in particular - has a bad time with the beer.

My review of Punk IPA

This beer is awesome. It cost $5. I will drink it again. Probably in a few minutes when I get the other one out of the fridge. 5 stars.

Thu July 29

Cities in the world..

When you’re building an application for travellers, you come up against the problem of how do you get enough data in the system so that it’s useful for 455 cities with a population of more than one million people, 1054 with more than 500,000 and 2851 with more than 150,000 people.

Or to look at the problem a different way - the most visited cities in the world…

Most visited cities

This table at Wikipedia shows the top 10 most visited cities to be Paris, London, Bangkok, Singapore, Kuala Lumpur, New York City, Dubai, Istanbul, Hong Kong, Shanghai.

Crawling data for these cities

I’m not sure what the take away from this data is. Seeding 2851 cities with data seems very doable in a week of crawling, seeding the top 10 visited cities with deep data is also achievable - it’d be interesting to compare the list of top 2851 cities with the hometowns of the users of weheartplaces.

The real take away

Is that it’s better to encourage users to add content to ‘empty’ cities, than to expect to have every city to have a persuasive dataset when you launch your travel site.

Wed July 28

Haversine in Coffeescript

The Haversine formula is a equation that can be used to calculate the straight line distance between two coordinates on a sphere. It is commonly used by geohackers to work out how far in kilometres it is between two latitude/latitude coordinates.

Remember that lat/longs are actually spherical coordinates expressed in degrees.

This page at kapelica.hr contained a great implementation of the haversine formula in javascript, I tidied it up and ported it to coffeescript to measure distances to the nearest places in my iphone app.

Radians: (degrees) ->
  degrees /  57.2957795

Haversine: (lat1, lon1, lat2, lon2) ->
  R = 6371 # km
  dLat: Radians(lat2-lat1)
  dLon: Radians(lon2-lon1)
  a: Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(Radians(lat1)) * Math.cos(Radians(lat2)) * Math.sin(dLon/2) * Math.sin(dLon/2)
  c: 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
  R * c

Note that the degrees->radians conversion isn’t exact, but the results should be within the margin of error for most GPS positioning systems.

Wed July 28

Displaying only the first paragraph

In redesigning my blog and publishing it on github pages, I wanted a simple way to show only the first paragraph of each post on the front page. The way I did it isn’t something I’m proud of - but it does show the power of css.

The following rule hides everything apart from the first child of a div.

div > * + *{
  display: none;
}

It works on safari, firefox and will work on ie9.

Fri July 23

Offline manifests

I’ve been working on an html5 app for Lonely Planet, and part of the task is to make the app work offline on the iPhone. Getting it to work isn’t too hard - you need to create a cache.manifest file and make sure it is served with the correct mime type.

The problem is online

When you have the phone offline and load the app, it loads in 2 seconds. When you turn the phone online again, it takes about 30 seconds to load all the javascript and so on.

It’s the caching rules

We have been deploying to google app engine, and by default - app engine sets all files to expire after 10 minutes. So even though the iphone has a local copy of the files, every 10 minutes, it’ll expire the local cache and redownload everything that the manifest refers too.

A checklist for fast online iphone apps

  1. Use a manifest
  2. Ensure the manifest is served with the mimetype text/cache-manifest
  3. Ensure the manifest has no 404 errors in it
  4. Ensure the manifest and all the content in it has an expiry date in the distant future
  5. White-list your network resources explicitly in the manifest
  6. Use jqt.offline.js to help debug the browser behaviour
  7. Tail your webserver logs and keep an eagle eye for unnecessary requests

All going well, your html5 app will load instantly, and still be able to access network resources.

Mon July 05

Coffeescript

I’ve been doing a lot of coffeescript lately and can recommend it wholeheartedly.

That is all.

Sun June 20

Skating in Melbourne

I just went on a big skate of melbourne CBD.

I started at home (nähe Southern Cross Station), then skated out to Prudence in West Melbourne. Prudence is a highly recommended bar. The beer is expensive, but the cocktails apparently are affordable. From Souther Cross to Prudence is mostly uphill, which meant that after a few beers, a few conversations and a good laugh - it was all downhill to Section 8.

Section 8 is a very cool bar. During the day. I went there in the evening and wasn’t so impressed. The skate was good though - it’s mostly downhill from Prudence along Victoria Street - then turn right, drop down into town (it’s a pretty steep skate through traffic down to little collins street) - and a hard left into Section 8.

S8 only had one beer I wanted - and it was in what australians call a “tallie” (800ml beer). I took a few drinks - decided S8 wasn’t for me, then stashed the beer in my back pocket and headed through town. There were people everywhere (and you can’t drink in public anywhere in Australia) so it took 5/10 minutes before I got out of the city (skating past the Melbourne Cricket Ground by now) and could drink the rest of my beer. It was a lovely long skate past the MCG - down a shallow smooth slope on a path surrounded in trees and grass. Had some good tunes on - nice times.

Then I bombed from the MCG down to Richmond - eyeballed out the gig I was going to go see at the corner bar, decided it wasn’t worth $50 to go see - then caught a tram back to Southern Cross and mellowed along Spencer street to home.

Melbourne. Good for skating.

Mon May 24

Merging identities

I’ve set this blog up on Github pages using Jekyll. My old posts may find their way here….