10x your Slack App’s UX with Message Menus
This is part 1 of a series on the trials and tribulations (a.k.a. design and engineering decisions🤓) of building Memo, a note-taking app for technical teams using Slack.
When you work in a small technical team, information is always flying around in Slack, in email and in meetings — code snippets, interesting links, great ideas, meeting notes, etc. That’s why we built Memo, a note-taking app for technical teams.
Teams spend a lot of time in Slack, so using Memo right inside Slack, without needing to context switch, has always been an important part of our value proposition.
Building great experiences in Slack is an ongoing venture, an eclectic mix of “conversational interfaces” and “standard GUI” — you have to think from first principles!


We set out to do just that, by obsessively talking to users! After several dozen user interviews and usability tests we found that, at least for Memo, conversational interfaces aren’t intuitive (“what can I type?”) or efficient (lots of keystrokes vs. a few clicks). They can be used judiciously (e.g.: executing a complex command like /memo-board rename meetings to Meeting Notes), but most interactions in Memo work better with GUI (both inside and outside Slack).
Once we learned about Message Menus, we were excited to add them to Memo and were surprised how they made the core interactions (saving and finding notes) 10x easier to use. Don’t believe me? Take a look:
/memo-save 📝
If you see an important message or file in Slack, you can save it in Memo with one click, by 🌟 starring it. Also, if you have a thought or idea you’d like to capture you can use /memo-save brilliant idea.
Everything saved is organized in boards, and many times you might want to move a saved note to the right board. Here’s how you did that before Message Menus:


And here’s how you do it today:


/memo-find 🔍
Every note is searchable by board name, keywords, @author or #channel. Just type /memo-find followed by what you remember to find what you saved, without leaving Slack. Unfortunately, if you can’t find what you’re looking for on the first try, it can become quite complicated:


But here’s how it works with Message Menus:


Behind the scenes 🤓
So how do we make all this work? The Slack API documentation is a great place to start. Here are some of the more interesting trade-offs we had to consider with Message Menus:
- Both notes and boards in Memo change frequently, so using a static menu wouldn’t do, we had to use
"data_source": "external"for most menus - When saving a note, we unambiguously know you want to see a list of boards for organizing it. However, when finding a note, you might be looking for a note or a board, or both! So we use
"options_groups"to show Boards and Notes in separate groups — and dynamically decide which group goes first. - Since we use
"data_source": "external"and ElasticSearch on the backend, we can dynamically rank which boards and notes to show, not only based on what you type, but also taking into account if you’re the author, if you interact a lot with that note, how old it is, etc.


- The Memo Slack integration is (mostly) stateless, so every interaction needs to describe the user action completely. For example, with Message Buttons, a click on “Move” actually describes
"move note 47013"— and that state (the note ID in this case) is stored in thevaluefield. More specifically, we store a reference to a stored state on our server, rather than the state itself.
Since options in Message Menus are dynamic, we ended up using a composition pattern for efficiency — we create the"move note ..."state, store a reference to it in thenamefield, and every option has just the missing"…"in itsvalue. You can imagine the options being something like this[{"text": "Board A", "value": 9901}, {"text": "Board B", "value": 47013}, ...], and then being able to executemove note 9901,move note 47013, etc. with just one state stored on the server. - Last, but not least, a ✨sprinkle✨ of emoji helps, not just in the results but also in the
textfield that gets displayed before you start using the menu

