Skip to main content

A fast way to build Block Kit interfaces in Python

Project description

blockkit-logo

Build status PyPI version Downloads


Documentation: https://blockkit.botsignals.co

Source Code: https://github.com/imryche/blockkit


BlockKit for Python

Build beautiful Slack UIs fast. Fluent API with type hints, validation, and zero dependencies.

pip install blockkit

Here's the thing

Building Slack apps shouldn't feel like writing JSON by hand. It's tedious. It's error prone. And honestly? It's a waste of your time.

You know what you want to build. Your editor should help you build it. That's what BlockKit for Python does.

Before

This is what you're probably doing now:

# Building a simple approval message. What could go wrong?
message = {
    "blocks": [{
        "type": "section",
        "text": {
            "type": "mrkdwn",  # 🤔 or was it "markdown"?
            "text": "Please approve *Alice's* expense report for $42"
        },
        "accessory": {
            "type": "button",
            "text": {
                "type": "plain_text",  # 😕 wait, why can't buttons use mrkdwn?
                "text": "Approve"      # 🤞 hope this isn't too long
            },
            "action_id": "approve_button",
            "style": "green",  # ❌ is it "green"? "success"? "primary"?
            "confirm": {       # 🤔 what's the structure again?
                "title": {
                    "type": "plain_text",
                    "text": "Are you sure?"
                },
                "text": {
                    "type": "plain_text",
                    "text": "This action cannot be undone"
                },
                "confirm": {
                    "type": "plain_text",
                    "text": "Yes, approve"
                }
                # ❌ forgot the required "deny" field
            }
        }
    }],
    "thread_ts": 1234567890  # ❌ wait, should this be a string?
}

# Three bugs. Deeply nested JSON. Good luck debugging this.

Nest some JSON. Guess field names. Cross your fingers. Test it. Get an error. Try again. Sound familiar?

After

Here's the same thing:

from blockkit import Message, Section, Button, Confirm

message = (
    Message()
    .add_block(
        Section("Please approve *Alice's* expense report for $42")  # ✅ Markdown detected automatically
        .accessory(
            Button("Approve")
            .action_id("approve_button")
            .style(Button.PRIMARY)  # ✅ Class constants prevent typos
            .confirm(
                Confirm()
                .title("Are you sure?")
                .text("This action cannot be undone")
                .confirm("Yes, approve")
                .deny("Cancel")  # ✅ Can't forget required fields
            )
        )
    )
    .thread_ts(1234567890)  # ✅ Converts types automatically
    .build()  # ✅ Validates everything: types, lengths, required fields
)

# Clean. Readable. BlockKit catches errors before you event send it to Slack.

Done. No guessing. No runtime surprises. Your editor helped you write it.

The difference

The library knows Slack's rules, so you don't have to memorize them. Your editor autocompletes everything. Validation happens immediately.

When something's wrong, you'll know right away - not after deploying.

Real example

Let's build something real. An approval flow:

from blockkit import Modal, Section, Input, PlainTextInput, RadioButtons, Option

modal = (
    Modal()
    .title("Expense Approval")
    .add_block(Section("*New expense request from Alice*"))
    .add_block(
        Input("Amount").element(
            PlainTextInput().initial_value("$42.00").action_id("amount")
        )
    )
    .add_block(
        Input("Decision").element(
            RadioButtons()
            .add_option(Option("Approve ✅", "approve"))
            .add_option(Option("Reject ❌", "reject"))
            .action_id("decision")
        )
    )
    .submit("Submit")
    .build()
)

That's it. Clear, readable, and it works the first time.

Why we built this

We got tired of:

  • Reading Slack's docs for the 100th time
  • Building UIs that are impossible to refactor
  • Shipping "perfect" JSON that Slack rejects for mysterious reasons

So we fixed it. One library. No dependencies. Just better.

Want more?

Check out blockkit.botsignals.co for the full docs. Or don't. The code is pretty self-explanatory.


Made by Botsignals

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

blockkit-2.0.4.tar.gz (65.8 kB view details)

Uploaded Source

Built Distribution

blockkit-2.0.4-py3-none-any.whl (19.3 kB view details)

Uploaded Python 3

File details

Details for the file blockkit-2.0.4.tar.gz.

File metadata

  • Download URL: blockkit-2.0.4.tar.gz
  • Upload date:
  • Size: 65.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.7.17

File hashes

Hashes for blockkit-2.0.4.tar.gz
Algorithm Hash digest
SHA256 c44ecc5c7db705dc53fe12148bee0f05c872bec25e4b385ecb076e66d581af55
MD5 95ac44a2bc71b2e2847c2db1057451b5
BLAKE2b-256 1d8587d5dca526e54e85cd3ae5b7a0dd632c2af33824a9b11832e8d8511ea6ca

See more details on using hashes here.

File details

Details for the file blockkit-2.0.4-py3-none-any.whl.

File metadata

  • Download URL: blockkit-2.0.4-py3-none-any.whl
  • Upload date:
  • Size: 19.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.7.17

File hashes

Hashes for blockkit-2.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 747c7e88ca79babb97ce6ed60cc25051059bdef7544d57128710f0bff7328f85
MD5 162d775826c20a3a9dfc09fe41ec4969
BLAKE2b-256 1b3d35338d58577f9835efa05ea81ac5fbf61a92c75b3ffc2c76a4b57d9efe58

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page