I put together slack_layout, a Ruby gem that makes building Slack’s Block Kit layouts easy while keeping everything organized.

It started when I was reviewing a colleague’s PR. Something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class SomeJob < ApplicationJob
  def perform(...)
    # Logic stuff
    $slack.chat_postMessage(
      channel: channel_id, 
      blocks: build_blocks(channel_id, "some message")
    )
  end

  def build_blocks(channel_id, message)
    [
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": message,
        },
      },
      {
        "type": "actions",
        "elements": [
          {
            "type": "button",
            "text": {
              "type": "plain_text",
              "text": "Archive Now!",
              "emoji": true,
            },
            "style": "danger",
            "value": channel_id,
            "action_id": "archive_now",
          },
          {
            "type": "button",
            "text": {
              "type": "plain_text",
              "text": "Snooze 14 days",
              "emoji": true,
            },
            "style": "primary",
            "value": channel_id,
            "action_id": "archive_snooze",
          },
        ],
      },
    ]
  end
end

Any method like the one above should catch your eye. The blocks stuff seemed to be something particular from Slack. Indeed, it is the spec to build Slack’s blocks (units for Slack’s Block Kit system). Roughly, it lets you compose rich UIs with these blocks. Did this mean we needed to do this JSON stuff every time we wanted to build this UI type? It seemed brittle. There probably was a better way.

Layouts

Slack Block Kit reference docs don’t especifically set an abstraction with the name layout. But the word came to me as I inspected Christian Gregg’s gem slack-ruby-block-kit. I found Christian’s gem because I thought someone had to have built something out to build these blocks more quickly. Indeed, his gem did some heavy lifting and laid down the work to speed up building these blocks. However, it is essential to develop conventions when working with a team. That’s how I came up with the idea of the SlackLayout pattern—an interface to compose Block Kit “layouts” that can be easily reused and organized.

I released a gem in case anyone also thinks it can help: SlackLayouts.

It provides a parent class (SlackLayout) and a clear interface (#blocks) to access the layout intuitively and build the blocks you need without writing JSON or remembering slack-ruby-block-kit namespaces.

It also makes sense. Different classes (in Rails jobs, models) can use different layouts without having to couple it to the class itself.