You can have a business model OR an ecosystem

So now Apple are rejecting iPhone apps that link to the Dropbox “create account” page:

Reason for rejection is the fact that if the user does not have Dropbox application installed then the linking authorization is done through Safari (as per latest SDK).

Once the user is in Safari it is possible for the user to click “Desktop version” and navigate to a place on Dropbox site where it is possible to purchase additional space.

Apple views this as “sending user to an additional purchase” which is against rules.

Devin Chalmers has a similar story:

Through five rounds of rejection and revision, over eight weeks, we and our appeals team kept bowdlerizing our signup links and verbiage to no avail: every week the big red dot would descend again on our iTunes Connect icon


Eventually it became clear that, from the reviewers’ perspective, there was a problem with that, at all: it wasn’t the (already redacted) signup links that we were being rejected for, but any GitHub link. At all.

In the specific case of Dropbox, they have an SDK that will let you sign into an existing account. According to MacStories:

[..] the Dropbox team has already released a “beta” version of the 1.2.2 SDK, which removes the option to create an account on The beta SDK was seeded a few hours ago, and there’s the possibility Apple will reverse its decision on those rejections once they see the removal of the incriminated links.

So, if I’m trying to write a client app against a third party API, I have exactly one option – put a username/password login form for that service directly into my app – not exactly good security practice – and offer the user no help at all in creating accounts on this service.

If I’m integrating against, say, the Flickr API, which doesn’t offer this ability, I’m stuffed. No more third party Flickr clients on the App Store, I guess. Or I could write to Yahoo! and ask them to provide a login flow that doesn’t provide any links that lets my users escape and get to a page that’ll let Yahoo! ask for money. Good luck with that.

As someone who wants to write apps against third party APIs, I now limited to writing clients against:

  • free services that have no intention of ever charging money (i.e., services that are going to go out of business)
  • or paid services that are willing to not try to up-sell their customers during account creation and won’t ever change this policy (i.e., services that are going to go out of business)

And if I have a web service with an API and would like people to write against it, my options are limited to one of

  • Don’t charge money, or provide the option to charge money, and never plan to charge money
  • Don’t provide any easy way for users who are new to the service and are coming from a third-party client to give me money
  • Don’t have an ecosystem


I built another thing. Feedify will make Atom feeds out of things that don’t have feeds, because I like having feeds. Basically, I got bored of having to jab at 5 icons on my phone every time I wanted to do a sweep of “what my friends are doing” – I’d much rather just subscribe to feeds and my RSS reader can tell me about things.

Right now it’ll make feeds out of Flickr and Instagram photo uploads of your friends. These were easy – they map directly to single API calls to the respective services (in the case of flickr, this leads to unavoidable disadvantages with the feed. But that’s life). As and when I think of more things that are easy, I’ll add them.

So yes. Feedify. Play with it.

Launchbar 5.1

Adds support for indexing Google Chrome bookmarks and history

Launchbar 5.1 release notes

Launchbar is the piece of software on my machine that I notice the least and
use the most. I cannot use my computer without it, and get confused on other
poeple’s macs when I can’t run applications any more. Until today, I had
exactly one problem with it.

Facebook’s Open Compute Project

On a large scale like this — not a small open-source project by good-willed individuals — “opening” something is almost always an effort to commoditize it, leveling the playing field as much as possible and marginalizing competitive advantages that others might have had.


Nobody “opens” the parts of their business that make them money, maintain barriers to competitive entry, or otherwise provides significant competitive advantages. That’s why Android’s basic infrastructure is “open”, but all of Google’s important applications and services for it aren’t — Google doesn’t care about the platform and doesn’t want it to matter.

marco. It’s interesting that open-source is now considered a weapon against other companies. Though I guess it was always intended to be such a weapon…

Talking to Jekyll using MarsEdit

Brent Simmons wrote a plea for Baked Weblogs the other week. It resonated – I’m the sort of nerd who obsessively re-writes his blogging engine more often than he actually uses it to blog things with, so I’ve been through a lot of solutions, and I keep coming back to baking.

Anyway. Brent wrote another piece in which he mentions,

I still get to write using MarsEdit, by the way. It talks to WEBrick running on my laptop.

Now, currently I blog in Tumblr, but I have the next generation version all set up and ready to cut across to when I feel like it, and it’s based on Jekyll, like the rest of my site is. I want to be able to post to it from MarsEdit! How hard could it be to build something that will let me?

Actually, it turns out to be really annoying. I’m extremely unimpressed by the MetaWeblog API. HOWEVER, finally today I have a releasable / working version of jekyll-metaweblog, a stand-alone ruby webrick server that will expose a Jekyll source tree via MetaWeblog and let you post, edit, delete, upload images, etc, etc, from MarsEdit (and hopefully anything else that supports MetaWeblog).

Get the code and play.

An aside – Talking about baking, Brent writes

[Aaron] also wrote that he doesn’t care about performance. If getting fireballed were a thing back in 2002, he might have cared about performance. If he had seen system X go down for a day, he might have cared about performance. It’s interesting that performance — or robustness — arguably wasn’t an issue in 2002, but it is now.

The Wikipedia page for ‘slashdot effect’ goes back to at least September 2001. Performance did matter. Aaron’s position is actually a lot closer to mine:

Honestly, I don’t care about performance. I don’t care about performance! I care about not having to maintain cranky AOLserver, Postgres and Oracle installs. I care about being able to back things up with scp. I care about not having to do any installation or configuration to move my site to a new server. I care about being platform and server independent. I care about full-featured HTTP implementations, including ETags, Content-Negotiation and If-Modified-Since. (And I know that nobody else will care about it enough to actually implement it in a frying solution.)

Baking has many problems, of course, but it has (for me) one huge overriding advantage – if I get bored of my codebase and want to build something else (this happens a lot), my blog doesn’t go away. It just stops getting new content. Much safer. It’s easy to build a dynamic site that’ll cope with being Fireballed and still host it on a single system. It’s hard to have to host 50 megs of mongrel process for the rest of time because you thought it would be a good idea to build some part of your site in Rails and now you can’t turn it off.

I bake a lot of my site – everything except the blog, in fact, which is hosted on Tumblr. I do, however, also pull all the blog pages down and render them to another domain, as an emergency “Tumblr has died again” measure. I can repoint a DNS record and I’m entirely stand-alone. In theory.

Brent Simmons talks about how he bakes his blog, and it’s very similar to mine. However, he does seem to have a bit of cleverness in there that I’m jealous of:

I still get to write using MarsEdit, by the way. It talks to WEBrick running on my laptop.

I have an idea for this sketched out – clearly I have to finish implementing it. The obvious thing to do it to just expose the folder full of raw blog post sources via a metaweblog API. But it’s such a horrible protocol to write for. Not that it’s complicated. And I love XML-RPC. But it’s just grown so organically that there’s not really one authoritative source of “these are the methods you need”. You just need to keep adding extensions from various people till all your clients work.

Also, I want to make life difficult for myself and write it in PHP, so it’s easy to deploy.

You can actually get pretty far on a single MySQL database and not even have to worry about partitioning at the application level. You can “scale up” to a machine with lots of cores and tons of ram, plus a replica. If you have a layer of memcached servers in front of the databases (which are easy to scale out) then the database basically only has to worry about writes. You can also use S3 or some other distributed hash table to take the largest objects out of rows in the database. There’s no need to burden yourself with making a system scale more than 10x further than it needs to, as long as you’re confident that you’ll be able to scale it as you grow.

– This. Adam D’Angelo’s answer to Why does Quora use MySQL as the data store rather than NoSQLs such as Cassandra, MongoDB, CouchDB, etc? – Quora

Imagine that your task for the day is to localize a piece of software — and luckily for you, the only output the program emits is two messages [..] how hard could that be?

[… some time later …]

[..] where $directory_count % 10 is 2, 3, or 4 (except where $directory_count % 100 is 12, 13, or 14), the word for “directories” is forced to be genitive singular — which means another ending [..] But with all other integer values, since “directory” is an inanimate noun, when preceded by a number and in the nominative or accusative cases (as it is here, just your luck!), it does stay plural, but it is forced into the genitive case — yet another ending.

A Localization Horror Story: It Could Happen To You – Locale::Maketext::TPJ13