Tutorial: Your First Mobile HTML5 App - The Basics, Forms, and Geolocation (Part 1)

I’m writing a tutorial about developing a very simple mobile HTML5 web app (while I’m learning a lot of the features myself). This is part 1, where I discuss the basics, new form elements, and geolocation.

Mobile HTML5 is so exciting to me. I’m crazy interested to see what innovative apps people will begin developing.

()

Tips for running a startup virtually

AppStoreHQ isn’t really a virtual company, but it’s close (especially for me): My co-founder and our first employee both work from our office in Seattle, while I work from my apartment in Los Angeles. It’s definitely an adjustment, but I we’re doing well with this set up.

Here are some tips that have helped us over the past year or so:

  • Begin by working together. Chris and I spent a few months together in the office in Seattle before I moved to LA. Before that, we spent upwards of a year chatting off and on about business, startups, etc. This time together helped us get used to our styles and understand the primary objectives of the business in a way I’m not sure we could’ve done purely virtually.
  • Know when to use various tools. Email is great for things you don’t need a response to immediately. IM is good for getting quick answers to simple questions. Voice is the best for hashing out more elaborate issues or arguments. In-person is the best for long-term strategy and planning. Learn when to use each of these tools and you’ll have a successful virtual startup with great communication.
  • Skype video chat is your friend. You’re running a startup, so you probably have a new laptop. It probably has a web cam. Use it. Seriously, Skype video chat is fantastic: being able to see your teammates faces and reactions is an amazing tool for virtual teams. It also has a great Screen Sharing feature to show-off half baked ideas.
  • Make sure you’re in-sync with daily video chats. Every morning the AppStoreHQ team logs on to Skype and does a quick video chat. We go over projects in progress, recently completed, and upcoming. We make sure everyone on the team understands what everyone else is working on and how it’s going. This 15 minute video chat is, in my mind, probably the single biggest key to our success working virtually. Getting on the same page every day is so important.
  • Make your progress transparent. We use a Google Spreadsheet to keep track of all our projects and where we are in each of our tasks. Keeping that up to date gives everyone, regardless of location, insight into how everyone else is performing and how close each project is to launch.
  • Get together in person every once in a while. Once every month or month and a half, I head up to Seattle for a few days and meet face to face with the team. We spend a few hours going over higher level strategy, thinking ahead a few steps. We go out to team lunches. Things we couldn’t otherwise do effectively over email, IM, or Skype.

These tips are simple, but they’ve helped us a ton. You have to be committed to running a startup virtually, but if you are, you can be successful.

Thursday, February 4, 2010   ()

On Mobile HTML5 vs Native Apps: An Overview

The future of mobile apps is definitely an area in which I have a lot to say. Specifically, my views around HTML5-based mobile web apps and native apps. Here’s my personal overview of the world as it is right now.

Overview

Chris and I often talk about how there’s a strong correlation between what’s happening right now in mobile apps and what was happening to the web around ‘96-‘99 or so. That is, it’s exploding, discoverability is hard, people want to be on board but aren’t sure why/how yet, etc. Many, many similarities.

But there are also correlations to even earlier than that, such as the OS wars of Windows and Mac. Right now there are many platforms (Apple, Android, BlackBerry, Symbian, Windows Mobile, etc) all gunning for the apps, while developers are trying to increase distribution. To do so, developers have to rewrite their app — mostly from scratch — for each new platform. Back when the web came around, people hopped on thanks in part to its much nicer write-once-run-anywhere feature (disregard browser incompatibilities here). We’ll see the a similar transition with mobile apps (though not necessarily to the same extent).

There’s plenty of reasons for apps to be native, especially over the short term: access to the camera, better/faster/easier graphics (read: games!), multi-touch. But there’s also plenty of reasons for apps to be web-based: ease of maintenance, write-once-run-anywhere, freedom from approval restrictions.

HTML5 and open source libraries like PhoneGap really start to blur the lines between what is necessary to be done natively and what can be done from the web. As developers begin to learn these new tools, we’ll see some really impressive new apps come to the web (Google Voice), but there will remain the need for native apps, too.

MobileHTML5.com

On that note, because mobile web apps are ready for prime time, I’ve decided to start a new tumblog, MobileHTML5.com. The goal is to provide links, videos, quotes, and hopefully some articles on how to get started and keep up on writing great mobile web apps. Check it out, subscribe, follow, etc. And let me know what you think.

AppStoreHQ

Similarly, if mobile web apps are going to explode, discoverability will be a problem. Luckily, I know of just the site to help with that sort of thing. ;) Today we announced that we now include mobile web apps in AppStoreHQ’s database. We’re starting with just one example, the recently launched Google Voice for iPhone. You can now search for web apps, browse web apps, learn about each web app, and get connected immediately to the app with a click of the mouse (touch of the finger, as it were).

If you have an app you’d like us to include, we’re starting with a manual inclusion process, so just email me and we’ll try to get you set up as soon as possible. In the near future we’ll make this much easier for developers. :)

Wednesday, February 3, 2010   ()

Tools We Use At AppStoreHQ

I said last week that February would be blogging month, but today came and I felt as though I had nothing to write. Still, I couldn’t start the month off on the wrong foot, so I’m beginning with a softball…

Every day we use at least a few tools to help run AppStoreHQ:

  • Google Spreadsheet: We have a “master” spreadsheet that helps us manage all the ideas, features, and products we’re building, have built, or want to build. There are 3 tabs: Backlog, Roadmap, and Completed. Backlog is where we keep any and all ideas about what we want to do. Nothing is too big or too small to go here, all the way from bugs to “personalized recommendations.” Roadmap is where we keep track of the projects currently in progress or just about to begin. While the Backlog is tracked at a “feature” level, the Roadmap is at “task” level (where many tasks equal a feature). Each task has a time estimate (no less than one hour and no more than one day) and a “time left” estimate. This simple system works surprisingly well to keep us on track, informed, and cranking out the features, especially considering the various levels of project management I’ve used in the past (ranging from sticky notes to trac to FogBugz and on and on).
  • GitHub for source code management. We host our code, a few docs, as well as do code reviews, etc.
  • AWS: Our live site runs on AWS: EC2, EBS, S3, and SQS.
  • Rails.
  • Solr for all searching and browsing.
  • Capistrano for all deployments.
  • Google Analytics: At a price tag of free, this is an amazing tool for tracking your visitors. It’s quite simple to pick up the beginner features, but provides tremendous amounts of power user features as well.
  • Vanity: A tremendous Rails based A/B testing framework, Vanity has helped us optimize various parts of the site.

Like I said, starting with a softball of a blog post. I’ve started to think of some better post ideas, but I’d really love some more, so please, ask me anything.

Tuesday, February 2, 2010   ()

I picked up an interesting factoid this week from AppStoreHQ - a Founder’s Co-op portfolio company that offers iPhone app search, discovery and social recommendations. In addition to their consumer-facing site, the company also owns and operates iPhoneDevSDK, the leading independent community site for iPhone developers. iPhoneDevSDK has over 20,000 registered members, but also picks up a ton of iPhone developer search traffic thanks to a very active and content-rich member forum.

I was curious to see how strongly the iPad announcement would register in the inbound search terms to the site, so I pulled the Google Analytics keyword analysis for Wednesday (the day of the announcement) and there it was at the top of the list: ‘iPad human interface guidelines’ was the top term for the day. I polled the whole keyword set for phrases that included ‘iPad’ and found almost 100 more, accounting for a little over 1% of site traffic that day (see image for the top 10 terms by volume).

So for what it’s worth, my take is that iPhone developers *are* excited about the iPad as a new vector for innovation, and are already getting busy figuring out how to take advantage of its capabilities.

Chris DeVore: Do iPhone developers care about the iPad? Here’s a data point… (via iseffcom)

Nice, Ian! I didn’t know you were a Founder’s Co-op company. Congrats on the traction!

(via caterpillarcowboy)

Thanks! Yep, we were actually “spawned” from Founder’s Co-op, as opposed to being started, then taking the investment at a later point. I believe that Founder’s Co-op is going to be a big/the biggest player in the Seattle startup scene — they’re funding great people, are thinking about how to fix the VC model, and they have an active, experienced group of LPs who engage with the portfolio companies and give advice whenever asked. The fact that Andy, Chris, and Founder’s Co-op will run TechStars Seattle will help the scene tremendously, too.

()

I picked up an interesting factoid this week from AppStoreHQ - a Founder’s Co-op portfolio company that offers iPhone app search, discovery and social recommendations. In addition to their consumer-facing site, the company also owns and operates iPhoneDevSDK, the leading independent community site for iPhone developers. iPhoneDevSDK has over 20,000 registered members, but also picks up a ton of iPhone developer search traffic thanks to a very active and content-rich member forum.

I was curious to see how strongly the iPad announcement would register in the inbound search terms to the site, so I pulled the Google Analytics keyword analysis for Wednesday (the day of the announcement) and there it was at the top of the list: ‘iPad human interface guidelines’ was the top term for the day. I polled the whole keyword set for phrases that included ‘iPad’ and found almost 100 more, accounting for a little over 1% of site traffic that day (see image for the top 10 terms by volume).

So for what it’s worth, my take is that iPhone developers *are* excited about the iPad as a new vector for innovation, and are already getting busy figuring out how to take advantage of its capabilities.

Chris DeVore: Do iPhone developers care about the iPad? Here’s a data point…
()

Resolved: February will be blogging month

Last night on a flight from Seattle to Los Angeles, I decided to make February a month of blogging. Everyday I’ll write at least one post here. The posts might be long or might be short, perhaps an essay or perhaps just a bulleted list of links or a quote I found interesting. Whatever the case, I want to create content at least once per day.

I have some ideas of things I want to write about: I’ve been keeping a (short) list of things I’ve learned over the last 9 or so months of running a startup so I’ll definitely include some of those, then there are probably some posts about software, sports, Los Angeles, the mobile web, etc that I’ll add in the mix to keep some variety. I’m sure I’ll still be hunting for ideas, so please ask me anything.

Friday, January 29, 2010 — 1 note   ()

All I ask of you is one thing: please don’t be cynical. I hate cynicism — it’s my least favorite quality and it doesn’t lead anywhere. Nobody in life gets exactly what they thought they were going to get. But if you work really hard and you’re kind, amazing things will happen. As proof, let’s make an amazing thing happen right now.

Conan O’Brien
()

The Joys of Rails (OR: How we sped up a process from 5,500hrs to 1.5hrs)

Today we released what I think has to be one of the coolest features we’ve ever released: personalized iPhone app recommendations based on tweets! It’s quite cool: we monitor tweets about iPhone apps, and then we recommend more iPhone apps based on your tweets. And if you’re a registered member of AppStoreHQ, we also include your loved apps, bookmarked apps, etc as a way to improve your recommendations.

As one can imagine, finding these recommendations requires some backend processing to establish relationships between users and apps. We made a rake task to handle this for us. The process itself isn’t too complicated: first we build relationships between users, and then, given two similar users (user A and user B), we see which apps user B has liked that user A has not, and we recommend those apps to user A.

In testing — on our development database which has just a couple hundred apps and just a handful of users — this whole process took just a few seconds. The first time we ran it in production, however, it was projected to take 5,500 hours to complete!

With a few hours worth of work, we were able to get this number down from 5,500 to 1.5 hours. Here’s how we did it (short version: it’s all about remembering not to let Rails do it’s normal thing):

When we started, the code to build relationships between users looked a little something like this:

build_relationship(User.all).each do |u1, u2|
  logger.info "Finding score between #{u1.inspect} and #{u2.inspect}"
  score = u1.apps_in_common_with(u2).size
  logger.info "Found score of: #{score}"
  score
end

The apps_in_common method grabbed apps from three different denormalized tables for both users and found the intersection.

The first thing that we did was stop instantiating all of these User objects! We didn’t really care about anything but their id’s, so we didn’t need that extra SELECT statement.

build_relationship(User.all(:select => :id)).each do |u1, u2|
  logger.info "Finding score between #{u1.id} and #{u2.id}"
  score = User.apps_in_common(u1.id, u2.id).size
  logger.info "Found score of #{score}"
  score
end

Then we refactored the apps_in_common method to do everything it needed with just the user_id. This helped fairly significantly — somewhere around 4x as fast. That that’s still over 1,000 hours to complete!

The next thing we did was to add some timing code in our logging, just to see how long the User.apps_in_common method was taking. Obviously, it was the bulk of our time. Finding the apps for each user was the big time waster. We knew we had to do something about that.

Luckily, for a related project, we needed a denormalized version of this data anyways, indexed by user_id. Perfect!

build_relationship(User.all(:select => :id)).each do |u1, u2|
  logger.info "Finding score between #{u1.id} and #{u2.id}"
  u1_apps = denormalized_apps(u1.id)
  u2_apps = denormalized_apps(u2.id)
  score = (u1_apps & u2_apps).size
  logger.info "Found score of #{score}"
  score
end

(I’m simplifying here: the real code stayed in User.apps_in_common, etc.)

This helped out A TON. I don’t remember the exact statistic at this point, but I do remember it being close to a day. There was still plenty of room to go.

Next we had the “duh, we’re idiots” moment where we realized that we were getting the apps many, many times for each user. We decided to cache that.

user_ids_to_apps = {}
DenormalizedApp.all.each do |da|
  user_ids_to_apps[da.user_id] = [] if user_ids_to_apps[da.user_id].nil?
  user_ids_to_apps[da.user_id] << da.app_id unless user_ids_to_apps[da.user_id].include? da.app_id
end

build_relationship(user_ids_to_apps.keys).each do |u1, u2|
  logger.info "Finding score between #{u1} and #{u2}"
  u1_apps = user_ids_to_apps[u1]
  u2_apps = user_ids_to_apps[u2]
  score = (u1_apps & u2_apps).size
  logger.info "Found score of #{score}"
  score
end

Amazing! This was the HUGE winner. With this change, we were down to about 3 hours or so. The DenormalizedApp.all.each block only takes a few seconds to complete, and we’ve then built a hash of exactly what we need.

Lastly, we stopped logging (in reality, we log every 10,000 steps just to ensure we’re still going okay):

user_ids_to_apps = {}
DenormalizedApp.all.each do |da|
  user_ids_to_apps[da.user_id] = [] if user_ids_to_apps[da.user_id].nil?
  user_ids_to_apps[da.user_id] << da.app_id unless user_ids_to_apps[da.user_id].include? da.app_id
end

build_relationship(user_ids_to_apps.keys).each do |u1, u2|
  u1_apps = user_ids_to_apps[u1]
  u2_apps = user_ids_to_apps[u2]
  score = (u1_apps & u2_apps).size
end

Surprisingly, this cut out about 50% of our time. We were now down to 1.5 hours, which we think is quite fast for our data set.

To summarize, remember that (a) Ruby can be slow, (b) Rails can be slow, yet (c) it’s still likely your fault for not optimizing.

Tuesday, January 19, 2010 — 7 notes   ()

The best and worst things about the job [as a startup founder] are the same: you’re constantly forced to become more self-aware, to recognize your weaknesses, to strengthen your weak points, to accept criticism as constructive. This applies equally to yourself — your ego — and the business. This is an unambiguously positive thing, but it can be painful at times.

()