← Back
Part 2

Don't Buy Cord; Build It Yourself

an imageJackson Gabbard
  • Product
an image

Welcome back! If you’re arriving here fresh, you probably want to step back to Part 1.

Step 3: Build your first version

Week One: Design

Building the first version of collaborative features is pretty fun, actually. Your engineers, designer, and product lead will love this work. Thinking through what good collaboration might look like for your product is thrilling. When you imagine your product with things like commenting, annotations, real-time presence, it’s really easy to get excited. Your users will be thrilled to have these sweet, sweet features some day.

Most product teams start with some sort of chat feature – a comment thread, for instance. Your designer will need to mockup what the chat thread will look like. They’ll have to think through things like different operating systems, fonts, screen sizes, screen resolutions, and browsers. Especially for screen sizes, you’ll have to be pretty thoughtful about how much screen real estate you’re going to devote to the chat thread.

Your first week or so will be all about prototyping in Figma and thinking about the implications of different design choices. It might seem like a long time, but building the wrong collaborative features is much, much more expensive.

Weeks 2 and 3: Identity Yak Shaving

Something that emerges pretty quickly from trying to build chat is that you actually need a fairly strong notion of identity. You know who your user is because that person logged in. But does that person know who other users are? It depends on whether or not you’ve already solved problems like user names / nicknames. Do you have good profile photos? Have you built the APIs required to get these bits of information into the product easily?

For many teams building their first pass at collaboration, it actually starts with a load of plumbing around identity. You’ll have to handle profile picture file uploads. But if you use Single Sign On with Google, for instance, you’ll also need to support getting the profile photo from their APIs. Now there’s API key management and request quotas to worry about. You’ve got the team required to build this – shouldn’t take more than a couple of weeks for an experienced team.

You’ll need some design support here, too. And frontend support. If you offer a profile photo upload UI, someone is going to upload a massive ultra-high res photo to it. You’ll need to handle things like image resizing. Likewise, people usually want to be able to crop their photo after they upload it so that it shows up nicely. Profile pics are always square or round, but photos are always rectangular. You’re going to want to invest a few days in getting that profile photo uploader and profile pic rendering logic to be sound. Your operations person will be able to sort out the S3 buckets and such.

Week 4: Chat Version 0

By now you’ve got reasonably good user identity sorted out. You have designs for showing chat messages from two users in a way that feels on-par with most basic chat systems. Now you need to think about the message contents. Users will want to format their text. We’re a long way from the days of SMS-style chat messages. People expect to be able to make lists and bold their text. They want to be able to paste links and images. After you’ve got your identity management sorted out, you need to agree on a data model and feature set for the basic chat experience.

This will require cross-functional work. Your designer will need to design a chat composer and a chat thread UI. This will need to work with your existing product design systems and colours. They’ll also have to think about things like when a user pastes 3 pages of text into the composer and hits send. Users do weird stuff. You definitely don’t want to just render a 6000px tall message. So, your UI engineer in going to have to get very creative about rendering and measurement. Users understand things like “Read More” links, so you can re-use some existing UI patterns.

But there’s a hidden trap here. What happens if you clip a message in the middle of of bold text? Or maybe in the middle of a link? Your UI code is going to be complex. You can expect it to take days to get this anywhere close to good. Doing a good job here is a lot less straightforward than what our intuitions tell us “quick and dirty” chat should be. One week is a very, very optimistic estimate of how hard it is to achieve decent message rendering in the client-side code.

Week 5: Chat Version 0, Continued

Along side all that tricky frontend code, there’s a really hard server-side problem you’re going to need to be tackling. That is – how do you store these chat messages? I mean, you need a database for a start. But even then, there are a load of small decisions to make. The read-patterns on chat messages is heavily biased towards new messages. Months-old messages pretty much never get read. So you need to be able to query by date and sorted. So, you can kiss MongoDB goodbye unless you want to re-invent features that relational databases are already amazing at.

Chat messages are also chained together by the conversation itself. You need to be able to go back from any messages to whatever message preceded it or followed it. You can use timestamps for this if you’ve got a relational database. But you also need to be able to quickly select for the chat messages in a particular conversation. You’ll like need a compound primary key. If you decide to go schema-free, you’re going to have to put together something for yourself.

Also keep in mind that users expect to be able to delete and edit messages. So from a data modelling stand point, you’re going to have to solve for these cases. A simple cursor based solution will be complicated by deleted messages, requiring more complex database queries.

Week 6: Chat Version 0, Still Going

Did I mention deleting messages? Well, that requires UI work. It also requires design work. There’s a bunch of nuance here, too. Do you want to allow for editing messages? If so, how are you going to let other users know when a message has been altered? Nothing is more frustrating that getting a notification only to click the link and land on a page and see nothing or see the text of a message that doesn’t match what you were shown before. So you’ll need to be fairly intentional about this choice. I mean, Facebook and Twitter took years to get this right, but you’ve got the benefit of hindsight. You can do better. One week, tops.

Week 7-10: Chat Version 0, Still

By now you’ve got basic chat working. Hooray! A user can land on a page within your SaaS product and make a comment. This is starting to shape up. At this point, you’re going to discover something important about humans: when there’s nothing specific to do, we do nothing.

Turns out if you drop someone on a page with an empty chat sidebar, people don’t instinctively chat with it. This is why Facebook works so hard to get you to do something in the composer.

It doesn't look like anything to me.

You’ll have to solve your empty room problem somehow. Your collaborative features will need to be discoverable by the users and clear enough that they know what to do with them. It’s painfully common for a SaaS product to slap a comment box underneath some random interface component and declare the product collaborative. Those teams might as well have taken the week off. They won’t reap the benefit of the work they put in.

It doesn't look like anything to me.

Just putting a comment box on part of your UI will not get you the lift in user experience you’re looking for.

Shown above is exactly what this looks like in a real SaaS product. I won’t name the product because I’m not evil, but I will point out that despite having used this product for more than a year, I can’t tell you of a time where even a single person on my team used this comment box. It’s not clear what it’s for. It’s not clear who will see the messages. I’m pretty sure I posted a comment in this box once on one of the screens, but I can’t tell you what happened next. And that’s because I don’t think anything happened next. I typed my messages into the collaborative equivalent of /dev/null, never to return. But hey – at least it had @-mentions, right?

So around this time, you’ll probably be starting to rethink exactly what you wanted the collaborative experience to be. Who should interact with whom? Are the collaborative affordances in the right place in the product?

Also by now you’ll probably start to wonder if it was right to build it all yourself. Don’t give up – you’ve spent this much time on it, you should double down so it’s not wasted. That’s how sunk costs work.

Joking aside, it’s still time to go back to design and UI work on the core collaboration experience. You’ll need to iterate on this. You’ll need to schedule user feedback sessions, capture their input, and convey it to the broader team. For iteration speed, you’ll need to have the UI code better abstracted so that you can tinker with it more. Your designer is going to need to really nail the prompt for user engagement. All of this takes time and coordination. Your product lead is going to be working double time to figure it all out.

Week 11-15: The Audience Problem

Once you’re certain you’ve got the basic chat into serviceable condition, you’re still going to find you have no engagement. How is this possible? You’ve spent months now on just the basic implementation. You have worked with users. You know that people know what to do with the chat box.

At this point, someone will be looking at the engagement data. I didn’t mention it, but surely you’ve been collecting engagement data. You know how many users focused the chat box. How many of them typed something. You know how many people sent messages. You know how many people never saw the chat UI at all. Someone surely will have built this. If they didn’t… you’re going to have to go back into your UI and add instrumentation code and setup some sort of server-side solution for collecting those metrics. Then you need to leave the already-not-working chat running for a few more weeks so that you can collect metrics. Whoops! (Whoopsie!)

Next, you set up some sort of dashboards using some sort of graphing utility. Your operations person will handle this for you. I’m sure the IT administrators (if you have them) will make that easy. With that, you’ll start to dig into what’s actually happening with your sweet new chat features at last.

What you’re going to discover is that only a small number of your users create chat messages – typical. Most of the content on the whole internet is created by a tiny subset of users. Importantly though, you’re going to find that mostly no one saw the messages. Despite all the work you’ve put in so far, the problem is that most people aren’t stumbling onto the chat messages that your most-engaged users are creating.

The problem here is two‑fold.

First, people usually won’t know who is going to see their message, so they won’t send one. Fear of embarrassment is a much, much stronger feeling than the warm glow of collaborative nirvana. The majority of users are going avoid the risk. This is why the screenshot above explicitly includes the instruction to use @-mentions. They’re trying to re-assure their users that this product does something and that the person they want to reach is actually there. But are they… really?

Second, just because I type a message into a collaborative chat box doesn’t mean any collaboration is going to happen. Think about it. Consider all the possible screens of your app for the average user. What’s the likelihood that shortly after User A types a message on a particular page, User B happens onto that exact same page and sees the message that A sent? In practice, I can tell you – very, very low.

So now you have to start tackling the audience problem. That is – who should see this message? And how do you ensure they do?

Your server-side engineer is going to have to get acquainted with email sending APIs, for a start. But do your users even use email? Did you build on top of Slack single-sign-on? Maybe it’s both? Now you’ve got a multi-headed problem. Maybe you have really time-sensitive content that also need SMS notifications. Sending notifications is hard and takes a lot of work to support properly.

Oh, and before we move on – let’s not forget about seat sharing. Your product is probably a lot like like most SaaS products. Some teams pay for each seat they need. Some teams give five people the same username and password and everyone is the same user. So, when someone makes a chat message – who even are they? Who do you notify? How do you stop it from devolving into some horrible variant of 4chan where everyone is anonymous?

At this point, you’re probably starting to rethink your choice to build it yourself again. Don’t give up though – you can solve this audience problem!

However, it means going all the way back to the data model again and to your identity model. Who are your teams? How do you know which users actually work together? If you’ve got small teams, you can probably message them all, but what about large teams? You don’t want to be spammy after all.

What you’ll need to do is experiment and iterate. You’ll need to do things to cluster your users and test drive different notification mechanisms and orders‑of‑operation.