Create Gravatar Photo Urls in Javascript

Sometimes one needs quick profile images in a development project. Enter Gravatar:

Your Gravatar is an image that follows you from site to site appearing beside your name when you do things like comment or post on a blog. Avatars help identify your posts on blogs and web forums, so why not on any site? source:

The only meaningful step in generating image urls is creating an MD5 hash of the users email, which is pretty easy to do in Javascript (i.e. Ember.js & Phonegap projects).

  var loweredEmail = email.trim().toLowerCase();
  var md5 = MD5(loweredEmail);
  var photoUrl = "" + md5;

If you need a sample MD5 function, take a look at this repo.

You should spend some time getting to know what paramaters you can pass to Gravatar, such as size and default images here.

Run Ember.js in Phonegap

Running an Ember.js project built with Ember CLI in Phonegap is really simple.

Note: These instructions are based on projects built with CLI v 0.4.

1: Build your project, and copy the assets to your Phonegap www/ directory.

  ember build --environment=production

2: Include Ember.js project to Phonegap

Ensure vendor is included first.

<script type="text/javascript" src="js/ember-vendor.js"> </script>
<script type="text/javascript" src="js/ember-app.js"> </script>

3: Attach your Ember project to window

You can copy/paste these from your Ember projects dist/index.html, with two small changes. It is best to wait for the ‘deviceready’ event.

  • locationType should be set to “hash” or “none”; and
  • baseURL should be removed.
window.AppENV = {"environment":"production","locationType":"none","EmberENV":{"FEATURES":{}},"APP":{}};
window.EmberENV = window.AddoEmberENV.EmberENV;
window.AppEmber = require('app/app')['default'].create(AppENV.APP);

4: Done!

Your Ember.js project should be running in Phonegap with no further issues/configuration.

Basic Connection Pool in Go

I started working in Go ~10 months ago, after seeing Rob Pike talk on Concurrency Patterns in Go (link).

Enter my first messing around at a Connection Pool, because I could not find any libs to handle this just yet:

type MemberInitFunction func() (interface{}, error)
type ConnectionPool struct {
  size int
  conn chan interface{}

func (p *ConnectionPool) Init(size int, initFn MemberInitFunction) error {
  p.conn = make(chan interface{}, size)
  for i := 0; i < size; i++ {
    conn, err := initFn()
    if err != nil {
      return err
    // If the init function succeeded, add the connection to the channel
    p.conn <- conn
  p.size = size
  return nil

//Get connection, block if none available
//Any call to get should defer.Release
func (p *ConnectionPool) Get() interface{} {
 return <-p.conn

//Release connection back to pool
func (p *ConnectionPool) Release(conn interface{}) {
  p.conn <- conn

//Postgres Pool
var pgPool = &ConnectionPool{}

//function to open postgres connection
func initPostgres() (interface{}, error)  {
  db, err := sql.Open("postgres", "secretstring")
  if err != nil {
    return nil, err
  return db, nil

Go Tip: Always Set GOMAXPROCS

So, it turns out there are Go people who have not read Effective Go. Thus far this month, I’ve had conversations with two Go friends (both well funded companies) who were running Go in production without setting GOMAXPROCS.

You should always read Effective Go.

In a nutshell, Go will not parallelize your code by default. You must GOMAXPROCS to the number of cores on your CPU.

Read more about GOMAXPROCS

Format Go Programs With Go Fmt

Continuing my Go adventures, I must document one of my favourite parts.

How much time do you spend tidying up, styling and aligning your code? Probably more than zero.

Go takes the approach that the machine can handle formatting, and it’s better if programmers don’t have to adapt to different formatting styles.

Simply run:

go fmt file/path

and your Go code will be automatically formatted to the canonical Go style.

Cool aye? Read more on the gofmt docs.


If you missed it, I recently open-sourced a Ticketing / Support desk software on github.

Taken from the readme:

TicketDesk is an e-mail driven system. Customers are never exposed to the portal. Instead, a support e-mail is created. TicketDesk receives tickets via a rake task that connects to IMAP. Responses to tickets are e-mailed to clients, and threading is enabled.

TicketDesk is also issue driven. Instead of manually managing 10 tickets with the same problem/solution, create an ‘Issue’. You can then focus your time on solving the issue at hand, and batch e-mail updates / close tickets with the same

TicketDesk was built as an internal tool, so is rigged for my needs and use case. I’d encourage you to share the customizations made along the way.

Take a look on the TicketDesk Github page. What’s kind of cool is it trended as the #1 new app on github for a day and a bit.

Lemonade Stand Startups

I’m sitting in an airport right now on my way back from Silicon Valley / San Fran / Los Angeles (WiFi is terrible, so this likely won’t get posted until later). It’s been a nice mix of seeing some older friends, attending events and meetings. I’ve not been here for a few years, and am amazed (and happy) to see the volume of Lemonade Stand Startups around.

To me, Lemonade Stand Startups are practice runs, proof of concepts or smaller companies that never grow big, but serve as a basis for future startups. To me, my Lemonade startups taught me more than any other experience I’ve been through, including University.

I wanted to post my story, in the hope that we can begin encouraging more of this behavior. I credit this experience with getting me a start in entrepreneurship, and for giving me the nose, guts and mind to keep at it.

In my world, this Lemonade Stand Startup was a Shared Web Host (yawn! It was saturated then, and it is saturated now) that I began in high school and eventually sold (more on that part later). Barriers to entry were low, so I jumped in perhaps a little faster than I should have (lesson: always know barriers).

It took me a few days to lease and configure some servers (Redhat / Apache / Cpanel, like everybody), build a website and an automated signup form. The original web designs were as nasty as one can find (see for v1 and for v2), but they did the job. We launched, and got no customers.

The natural instinct is to change pricing (a bad idea!). After running spreadsheets , I realized that our calculations would leave us far less undersold than competitors. Instead of playing smart and using this as an advantage, I shaved our prices and posted on every forum we could find. It worked, and within a few hours we had $300/month of paying clients (generally who stayed until the end) and the client base continued to grow throughout the day. It was a band-aid solution to the problem (no clients = lower prices and pump). Eventually, it taught me that immediate (and even intermediate) positive feedback does not mean a core issues is resolved; it can in-fact be more detrimental.

The next months were smooth sailing. We were getting new clients every time we posted to some core forums (Web Hosting Talk, Namepros, DN Forums, etc.) and I was spending most of my high school lunch hours answering support tickets. I began expanding our server base via leases, and was returning 4-6x the lease. As was the craze at the time, I began onboarding dedicated offshore resources to support with low-level systems admin and customer support.

Then the signups stopped. Not to lose, I turned my attention to my local town. All of my clients were American, so I thought calling up local businesses in regional Australia would work. It did, and our signups kept flowing. The positive here was the lesson that an software business can compete, evade and potentially beat larger competitors without a core online presence, but a strong offline game (something I feel has changed a little since). The negative was it was another band-aid solution to our core problem – the product offering was cheap, competed on price and had no differentiation.

As more sophisticated buyers started switching to VPS / Dedicated Boxes, Shared Hosting rates plummeted (our most popular plan was $20/month). This is when the reputation for competing on price, being no frills, leveraging offshore resources and generally being an office-less company began to hurt us. Customers expected a price drop, and we experienced the company’s single biggest customer purge in the following week. Unable to differentiate (looking back, moreso unwilling than unable) we dropped our prices and kept the signups flowing.

At this point you should be seeing a few of the core lessons I learned:

  • Price competition as a core value proposition can be scary. Our customers were only with us for prices. This was bad;

  • Getting immediate positive feedback led to a false conclusion – that the problem was solved;

  • Barriers to entry were low and our technology was old; every day somebody was overtaking us;

  • We did not have a repeatable customer acquisition model (forum posts and cold calling local businesses); and

  • We were able to stay alive in down periods by competing offline. Though, web presence was never strong or highly automated in the best of times. Googling the company today shows not much more than our cheap forum posts.

After 1.5(ish) years of moderate growth, and now being in the double digit range of servers, I finally realized this. For a kid in high school the business was strong, but I felt there was no way out of the bind the company was in. We were also getting to the point of requiring a more serious registration of the business but I was not seeing the margins or continuity to justify this.

There was enough cash to try something new.

One evening I was invited to a private Counter Strike server. For those unaware, serious PC gamers used to buy private servers ($8-$16 per player slot) each month to practice with their guild on, or to play with friends. A lightbulb moment went off, and I realized we had the skills and access to servers to make a run in this business.

This time it was a little slower to launch. Time was spent to validate the market. I had the first $7,200 (600/month) of clients lined up before the product ever launched. It was small, but it was something. The margins went from 4-6x to 10-14x on this new product line. Average customer buys went from $240/year to $600-$800 / year.

Because each sale was now worth more, it was easier to justify extra resources to pursuing them. For the first time, we bought ads. The ads failed miserably. We learned how complex and time consuming that game was, and stayed away. The good news is our forum posts would nearly sell out each time. Following my prior cold calling model, I began reaching out to guilds asking them to switch, and we offered big incentives to our existing clients to refer their sister guilds. Both worked, and I began to learn how to hunt for clients without dropping a dime. We had the first markings of a serious brand.

It took less than 3 months for the gaming server revenues to overtake the web host. While I waited too long, it was a nice lesson in pivoting. It was also a lesson that opportunities can come from anywhere.

Unable to support both businesses(I was still in high school, and unwilling to let offshore labor have core access to the servers) I began reaching out to competitors in an attempt to sell the web hosting business. At the time, some larger players were growing through acquisition to stay competitive. The general pattern was buy the customer set and delete the old brand immediately, and in turn boost internal subscriber numbers. It was a nice path for smaller players to exit, bidding wars would often result and forums dedicated to buying web hosts were created. I felt that this market couldn’t remain so rabid forever. After posting our financials (privately) we got some offers. Once I met somebody I liked (and had the offer), I explained the pivot to Game Server hosting. After explaining our models, I was asked to sell that too.

It took around two weeks to close the negotiations. Both businesses were small, and had medium-ish offshore headcounts. Both were acquired for the customer lists, and our pages were taken down immediately. Everything was redirected to the buyer, and customers were given an option to leave the host without any penalty due to the acquisition, as well as refunds and free time if they felt it was unfair. Sadly, the company domains were left to expire after a few years. It’s tempting to buy the back for nostalgia’s sake.

In terms of lessons, this pivot and exit taught me how to discover new opportunities, keep customers happy (through entry and exit), find exit opportunities and how to generate repeatable acquisition models. Naturally I’ve spent years refining these skills since, but they’ve stuck with me. More importantly, it game me a nose and a taste of blood that stuck with me through University, and to this day.

Quite often, when I think back to the startups we are now working on, I’m relying on advanced versions of skills I prototyped back then. I never had a real job through high school, and grew comfortable with the risk sand managing my own financial expectations that every startup requires

Megaupload Implications Are Plain Scary for Cloud Storage

EDIT: There have been comments informing me that Dropbox keeps a local copy of files on a users desktop (generally speaking), thus making some of my Dropbox examples less relevant. While true, the purpose of this post is around the legal precedent being set vs. a specific fear for a specific provider. As you read, feel free to think of whichever provider you wish interchangeably with Dropbox.

I’m the first to agree that any website obviously engaged in piracy (vs. having independent users leverage the platform in unintended ways) should be shut down, and if this is the case with Megaupload, it should be shut down. However, the way Megaupload was shut down raises scary implications. With cloud based storage becoming primary for many, it is rather jarring to have people losing legitimate files in the process, with no recourse to immediately find or recover them. I store a lot of personal files in Dropbox, and if they ever got megauploaded (I’m sure there is unintended piracy at Dropbox) I’d likely lose my copies. One has to wonder how many users have less faith as a result.

We also need to consider that the average user is likely unable to determine what a websites primary use is outside of their personal use case (would your Father know MegaUpload was mostly piracy, or would he think it is a site to share and store files?).

The conclusions here alone are scary: – If a website has significant piracy, it will be shut down at the expense of legitimate users; – Legitimate users may be unaware of the piracy while using a legitimate service; – Users have no recourse to immediately recover legitimate files; and – Legitimate users may thus be less likely to use cloud services / cloud storage.

If a site must be shut down we, at the very least need a mechanism for users to immediately recover legitimate files.

Nothing above sounds attractive (at all!) to our industry. I wanted to dig further into the indictment based on the information I could find, and am concerned that a cornerstone of the argument rests on the way infringing files are deleted.

The Digital Millenium Copyright Act provides safe harbor for sites which take down illegal content within a reasonable period of time, of which they had no prior knowledge of. Broadly speaking, it’s a concession whereby a sites users upload illegal content against the sites wishes, and is why companies such as Youtube don’t get shut down.

The Megaupload indictment reads that they removed links to the illegal file, but did not remove the actual file. To those blissfully unaware of how the file systems / internet cloud storage works, this makes sense. But, let’s consider how an average file sharing service works:

User A comes along and uploads a file (say, the film Big Fish.) User B, whom has no relationship to User A, uploads the same file. Instead of store the same file twice, most services will recognize the file is the same and give both users a differing ‘link’ to the same file. If User A deletes the file from their service, they are deleting their ‘link’ to the file, so as not to affect User B.  Only when no users have a ‘link’ to the file will it be purged from servers (and in some cases, if a file is routinely popular, it may remained on the servers to account for future uploads).

When receiving complaints, Megaupload removed the ‘link’ to a file, with the assumption that other uploaders’ of the file were legitimate. If you still think that this move is directly supportive of piracy, consider the user who saves backups of digital purchases they have made / old digital content (legal in some jurisdictions). Removing a link, vs. the actual file, is clearly the fairest solution so as to not harm legitimate users.

If the precent is set that the physical file must be deleted where one of many users with ‘links’ engages in illegal activity, things will become very scary. All of a sudden, I can’t trust any file storage, saving or backup mechanism where I don’t hold the physical hard drive. Most less informed users won’t realize this until they get burned.

TODO – migrate rest