Building a Contentful Slack bot in the cloud with Gomix

December 20, 2016


Lists, lists, lists – I keep track of various things to manage my life. I’ve got lists for several different things spread over Wunderlist, Google Inbox, and Google Spreadsheets. Just recently I wrote about how I managed to eliminate one of these lists by putting my planned event schedule into Contentful, and today I want to share with you how I removed one more list.

Writing belongs to my daily tasks, and usually topic ideas appear in situations when I’m doing something completely different, which makes it hard to not immediately forget the story. What I did so far is, that I kept all the ideas in a grouped folder in Inbox.

This works more or less fine, but it still has the problem that Inbox is my mail client, and I’d like it to stay to be only for email handling. Putting more and more things in there results in a mess for me. My personal website is built with Contentful, so why not put the ideas into the CMS as soon as they appear?

Always keep Slack’in

Slack is one of those apps that stay with me all day long. I use it for work but also for private communication. It’s on my computer and on phone, and I receive message updates via email. A cool thing about Slack is that you can easily create bots to customize the default functionality. Deploying your website, sending an email to your mom, managing lunch plans – all this is possible using Slack bots. It’s up to you what you bring into this messenger.

The way it works is that you have to define an HTTP endpoint, which Slack will then call when the user enters your defined command. Even though this seems to be really straight forward, I’ve never written a Slack bot before, and the main reason for that is that deploying an accessible endpoint to the cloud can take some time and effort.

Gomix tries to solve this problem. It’s like CodePen but for server side node.js applications. And that’s why it’s perfect for not too complex things, like prototyping a Slack bot.

Gomix – quick Node.js apps in the cloud

When visiting Gomix for the first time, you’ll be redirected to the community page. This page will show you recent projects that have been developed on Gomix. You’ll quickly notice that this is really powerful as it makes it possible to just look around for cool things and play around with these. People can create applications and share them easily for other users to discover. Every project can then be taken to be reused and modified. This is called “mixing”. There are already several example boilerplates for bots, games and more.

Mixing and editing on Gomix

To get you started with the Contentful bot, you can navigate to the “Handy Bots” overview and choose the “Contentful Command Slack Bot”. There you have the option to “Remix your own” bot. And this is all it takes. After hitting the button, a new project will be initialized for you and you’re ready to make the first file changes.

Gomix’ editor looks like most of the cloud-based editors out there. There is a file explorer on the left side and a big coding window in the center of the screen. You can choose between a light and a dark theme.

Files changes in the project are constantly autosaved, which feels a little bit weird in the beginning as the UI is repeatedly telling you to not hit COMMAND+S on every save attempt. On every change, the running node server will also immediately be restarted. To see what is going on a log panel can be shown.

By default, the project runs on node version 6.9.1. This doesn’t seem to be changeable at the moment. The engines.node property in the package.json doesn’t have any effect on the environment. Node version 6 is quite recent so this is not a big deal, and you can use most of the new JavaScript goodies like Arrow functions and let/const variable declarations.

Registering a new Slack command

Now that you have “mixed” your first project the next thing to do is to register your new Slack bot in your Slack organization. For that, you can use the already existing Slash Commands app. You can go there and add a new configuration for several commands easily.

To add a command the most important things are to choose a given command (/contentful in this case) and to define the server endpoint Slack should call whenever this command is entered. You’ll get the URL of your new server after clicking the “Show” button in the upper left corner of the Gomix window. The Contentful bot is made to receive POST requests so make sure to not change method parameter in the Slack configuration.

Now you have to copy the token which Slack generated for you. This is needed to make sure the requests hitting your new Gomix server are truly coming from Slack and not from somewhere else.

Hit “Save integration” and your Slack setup is done. Next step is to open the .env file in Gomix and add the Slack token there. The .env file is a configuration file that will be kept private and only collaborators can see the internals of it. That’s why you don’t see any values in this file in your mixed project. Values defined in this file will be available in the node context via process.env.

At this point, your .env file should look as follows.

# Environment Config
# store your secrets and config variables in here
# only invited collaborators will be able to see your .env values
# reference these in your code with process.env.SECRET






As you see, in this file there are several more configuration fields to be added, all of which are Contentful-specific. The most important part is to set a valid content management token, as the goal of this bot is to access data that is not necessarily public yet. You can get this token in the API section under “Content management keys” inside of the Contentful web app. However, if you don't want to create an actual OAuth app, you might want to simply use the token you can generate from the documentation page (but remember, this is useful for testing only, you want to have a real OAuth app token when working on a real application that uses our CMA). The other fields are there to make the actual commands works. This bot specifically is built to work with one space accessing and manipulating data of a given content type in a particular language. So you just have to add your space ID, the content type ID and the language you want to work with.

And now you’re set up and should be able to retrieve entries and drafts stored Contentful right in Slack. You can see all available commands by firing up the command /contentful help.

With this setup you can now quickly see entries of a given content type and also create entries right from your fingertips when being in Slack.

How does it work?

What I could have done would be to spin up an Express server and set up the request handling myself, but fortunately the npm ecosystem is quite rich these days so I looked for a package I could use for the specific use case of Slack integrations instead.

Spinning up a server using TinySpeck

The first package I found was called TinySpeck. It was nicely documented (lacking test coverage though) so I decided to give it a try. Integrating a Slack command mainly consists of two parts – retrieving the HTTP call made by Slack to the defined endpoint and then answering it. Both can be done easily with the help of TinySpeck.

'use strict';

const slack    = require( 'tinyspeck' );
const port     = 3000;

// accepting calls of the contentful command
slack.on( '/contentful', ( { response_url, user_id, text } ) => {
  // some command parsing here

  // answering the command
  return slack.send( response_url, { channel: user_id, text: ‘Hello User’, []} )
  .then( () => {
    console.log( 'Successfully answered the command' );
  } )
  .catch( console.error )
} );

console.log( `Starting server at ${port}` );
// starting the server
slack.listen( port, process.env.SLACK_TOKEN );

By using TinySpeck, I didn’t have to deal with the server myself as it is already able to start one on its own. To react to certain Slack commands, TinySpeck provides event handling using the on function in which I then can send back responses using the send method. The send function accepts two arguments. The first one is the response_url, while the second one is an options object including the user_id of the user we want to send a message to, and the actual message parameters. response_url and user_id can be taken from the object that is passed to the event handler. Slack offers several formatting options which you definitely should check out.

Connecting the bot to Contentful

To use the content management API of Contentful we can also use the npm package contentful-management. Using the credentials we already set in our .env file, we can create a new client and start fetching entries right away.

const cma   = require( 'contentful-management' );
const space = cma.createClient( {
  accessToken : process.env.CF_CMA_TOKEN
} ).getSpace( process.env.CF_SPACE_ID );

space.then( space => {
  // fetch the entries of a given content type
  return space.getEntries( Object.assign( {
    content_type : process.env.CF_POST_CONTENT_TYPE_ID,
    order        : '-sys.createdAt'
  }, query ) );
} );

Connecting the service with Slack and Contentful is the main focus of this article, but if you’re interested in the text command parsing and the project structure you can head over to the project, it’s really just a few lines of code.

Building apps completely in the cloud – is this a thing?

After playing around with Gomix for a few hours, I have to say that I was rather skeptical in the beginning. It’s still in beta stage which means that you can not expect a perfect product yet. I can not see myself working in an environment like this every day, due to the lack of proper editor settings, shortcuts, and a debugger for node. But for quickly hacking together a prototype or a simple project like a Slack bot, it’s perfect. And even if it’s not perfect yet after reporting a few issues on Twitter (although later I figured out I should have used the forum instead) people came back to me quickly, and critical issues were fixed in almost no time.

Gomix also offers sync with GitHub, which is quite nice to get code in or out. This feature is also a bit jumpy right now, as it’s missing some proper error messages when something fails. Real-time collaboration is also worth mentioning, but this is a feature I couldn’t delve into, as I was working by myself the whole time.

Overall I feel that if Gomix can grow a community around itself, it definitely has big potential to become something very useful. In my case, I definitely will use it for my upcoming bots and prototypes again, because hey – why should I deal with setting up an infrastructure when there is a service doing that for me already? You can try using my own demo app, or remix it on Gomix to make your own customizations. Remember that this demo was built using Contentful's Javascript SDK for our Content Management API, so npm install --save (or yarn add, if you're one of the cool kids) the SDK and start hackin'!

About the author

Don't miss the latest

Get updates in your inbox
Discover new insights from the Contentful developer community each month.
add-circle arrow-right remove style-two-pin-marker subtract-circle