I built a thing called soonsnap, and various people said that I should write up how and why.
First, what it’s for.
Here’s the use case. You’re there in the pub, Friday night, and there’s a group of people squeezing themselves together behind a table while one of their number takes a photo of them. So you step up, helpful, and say “hey, let me take that, then you can be in it!” and whip your phone from your pocket and snap a picture of them all pulling faces and drinking cocktails.
Great. You’ve got a picture of them. How do you give that picture to the people in it?
Here are the constraints:
- You don’t know these people. This is not a surreptitious excuse to obtain the phone number of the attractive one in the group. So you can’t ask for a phone number, or add them as a Facebook friend
- You’re all in the pub having fun; you’re not at a computer class. You want to get this photo to them as quickly and easily as possible. So if you ask them to do anything complicated to get the photo, such as “install this app”, or “turn on Bluetooth and then tell me your phone’s Bluetooth name”, they’ll just shrug and say “whatever” and ignore you like the sad techie lunatic that you are
- Either you or they might not have an iPhone, so no AirDrop for you
- You’re in the pub. So this is primarily for mobile. Obviously it should work on a big wide screen, but that’s not what it’s aimed at
- Me, the person running the server, does not want to pay for lots of hosting, and people in the pub don’t want photos of them stored forever in someone else’s cloud. Images are not stored on the server; they’re transferred as much as possible device-to-device
Sometimes, the people asking for a photo will hand you a phone to take it with. At that point, you don’t need any technology to assist; take the picture, give the phone back, done. But if they don’t… you need to get that picture to them.
The one huge overriding goal here is complete ease of use. Anything at all which can be construed as a barrier will mean that you’re unsuccessful. “To get the picture, install this app” takes too long and is too annoying. “Turn on Bluetooth” is too annoying. “Turn on Android Beam” is too annoying. This means the solution needs to be on the web, because everybody has that.
But it should feel like an app, because people are accustomed to that and so the sense of familiarity is important. It’s a very simple set of actions: either “take a photo” or “receive a photo”. So the thing I came up with, soonsnap, is this:
- You hit this website and it tells you to pick or take a photo
- It gives you a simple four-letter code and gives you instructions to read out to them: go to this website, enter the four letters of the code
- They do it: it gives them the photo
- You say “there you go”, they say “thank you!”, and another little human interaction is improved with technology without getting in the way
So there are two paths through it: the photo taker, and the photo getter. The taker needs to say “take a photo”, then take the photo, then get a nice clear set of instructions and a code to tell to the getter. The getter needs to get to the website itself, say “receive a photo”, type in the code. That’s it.
To this end, all the thinking went into making soonsnap so it’s really hard to screw the interaction up. Take the codes as an example. They’re four characters — long enough that a code isn’t reasonably guessable, short enough that you can say it to someone else in a crowded bar and they’ll hear you. The code does not repeat any characters. This is done so that when tapping a letter of the code, that letter disappears and can’t be used again — this prevents someone accidentally tapping a letter twice. The characters used for the code could have been all 36 letters and numbers, but it’s actually only 20: 0123456789ACFHNRUWXY. This is so that all letters which sound the same are removed; this stops someone saying “did you say B zero one two or P zero one two?”, especially if you’re shouting over the music in a crowded pub.
And it looks simple but colourful and clear to make it easy to see what’s going on even if your vision’s a bit blurry. I wanted it to be attractive partially because of the aesthetic usability effect, and partially just because, well, things should be pretty. I knew I couldn’t do that, so I talked to Sam Hewitt who put together a great visual design for soonsnap. Thank you, Sam!
Technologically, soonsnap is designed so that images aren’t stored on the server. Partially this is for security — there’s no big archive there, and your photos aren’t being kept around by a service you don’t trust — and partially for cost, because it’s not supposed to be a big photo archive. It’s used to send photos. Soonsnap uses socket.io, which is basically a self-hosted version of something like pubnub. So the images go through the soonsnap server, but they’re transmitted from sender to receiver and aren’t kept around on the server. I’d have liked to do that with WebRTC so that it’s genuinely peer-to-peer and doesn’t involve the server at all, but firstly you need to set up a STUN server to do that and that’s complicated, and secondly iPhones don’t do WebRTC yet.
Update, May 2020: as a result of issue #4 I should explain, in addition to the above technical information, why Soonsnap scales images down to 500px before sending them. Soonsnap’s overriding goal, which takes precedence over everything else, is making the transaction as quick and unobtrusive as possible. We shrink the image to minimise the amount of time taken for the transfer, and to reduce the bandwidth that has to be shipped through the back end, and the screens are all as basic as is possible to avoid confusion. I don’t think that the benefits from sending a larger image (that you get a higher-quality image) outweigh the deficits (the sending screen is mildly more confusing; transfer takes longer), which is why we shrink the image. If someone else were to wish to deploy soonsnap themselves, getting the code from github to do so, and they want to relax that restriction, then the 500x500 box for scaling is configured in index.html and can be changed to whatever the deployer prefers.