A classic app like this would have checkboxes to the left of the ToDo items. Unfortunately, Slack only allows us to put buttons on the right, and there can be exactly one button combined with a text caption. We wanted the user to perform multiple actions, so we had to resort to the “overflow” element. It’s a “…” button that hides several menu items underneath. Overflow adds an unnecessary click to the workflow, but there’s no other way around it. We faked checkboxes with an ◽️ emoji for now, hoping that Slack would one day implement them and we’ll make our app behave like a proper todo ;)

Update:

Slack has just released, guess what — checkboxes! Great job, Slack! Unfortunately, we couldn’t implement them in ToDoBot right away due to some limitations. Specifically, you can’t combine more than two elements in a row, and if you have checkboxes, you can’t have any extra buttons next to an item. Our ToDos have multiple actions associated with them (e.g., edit, share, set reminders), and we couldn’t find a better place for them to live (for now). We found some great use for emojis, though, and now they actually mean something!

👉🏻 is a “regular” ToDo

⏱ for ToDos with a reminder

🔥 means that a ToDo has expired

✅ for Done items

Choosing a name

This is arguably the hardest part of building anything.

Todoist? Nope, already exists. Checker? Chckr? Todo-ninja? Todo-panda? Todofu? Todobot!? Todobot sounds pretty good! Let’s see if there are any domain names available! Ughh… all .coms are taken, there’s something ugly in .org and .net, there’s also an odd todOObot.com… It seems like we have to go with a prefix...

thetodobot.com or gettodobot.com? Let’s get both of them!

Infrastructure

It’s not worth it setting up Kubernetes for a small project like this, but… we already have it behind OneBar. Also, Slack Bolt seems to be meant for the apps like ToDoBot, but… we already know and use Django, no time to learn NodeJS! The stack has been chosen.

The rest of the Day 1 we spent setting up webhooks, configuring SSL, defining database schema, and putting together the rest of the bot plumbing.

Day 2

Coding

We spent all of Day 2 coding the bot logic. We’re going through an acceleration program with OneBar right now, and it’s pretty intense. ToDoBot was an experimental side-project, so we worked on it in between meetings, customer calls, on a commute, and late in the evening.

I didn’t mean this to be a deeply technical article or a tutorial, so I’m going to mention a few Slack API features that we used only briefly:

app_home_opened — Slack sends this event every time someone opens the ToDoBot’s App Home. We react to it by sending back a bunch of JSON that represents the current state of a person’s todo list.

views.update — This is how you actually update the App Home. We do it reactively when someone opens the Home Tab or proactively when we know on the backend that the state has changed for a given user.

messages.im — We receive this event every time someone sends a DM message to the ToDoBot. We then simply add every message to the list and acknowledge it with an emoji.

reactions.add — This is how you react with an emoji.

We’ve also registered a /todo slash-command, “Add to my TODO” message action, and implemented a few simple dialogs for adding and editing items.

/todo slash command

Somewhere during Day 2 came the idea of shared TODOs. We tag each other in messages all the time, hoping that the other person will not forget to do what we asked them. This naturally translated into tagging people in TODOs. A shared TODO would appear in each person’s Home Tab, and anyone mentioned would be able to close it. We started using shared TODOs for our own needs way before the rest of the ToDoBot was completed, and quickly got hooked on the feature.

a TODO shared with two people

Day 3

Debugging

By Day 3, most of the bot mechanics were completed, although we still had a few issues. I spent several hours debugging this one. Even though ToDoBot is super light-weight and there was no load on the server whatsoever, our gunicorn workers were dying left and right, and the bot behaved very unpredictably. It turned out that the AWS ELB that we had in front of the app tried to maintain and re-use the same connection when possible, and this didn’t play well with the sync workers that we used by default. It took me time to understand what’s going on, but simply tweaking the timeouts seems to have helped.

An interesting observation came up while debugging the gunicorn issue. Our servers were getting quite a bit of traffic already, even though the domain was brand new and nobody knew about us yet. It turned out our ELB happened to get an IP address which has constantly been poked by a bunch of security scanners somewhere in Russia, check this out:

Some security scanner in our access log

Website

We wanted to submit our bot to the Slack App Directory, so we needed a website. We didn’t intend to spend much time on it, though. Our designer helped us put a few stock pictures together and crafted us a standard single-page layout. Andrew has then implemented everything in Webflow.