nicklambourne / slackblocks
Native, validated Slack Block Kit values for PHP
Package info
github.com/nicklambourne/slackblocks
Language:Rust
pkg:composer/nicklambourne/slackblocks
Requires
- php: >=8.2
- php-64bit: >=8.2
- ext-json: *
- ext-pcre: *
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-master
- v2.7.0
- dev-codex/elixir-6-docs
- dev-codex/elixir-5-release
- dev-codex/elixir-4-sending
- dev-codex/elixir-3-quality
- dev-codex/elixir-2-contract
- dev-codex/elixir-1-foundation
- dev-codex/readme-language-accordions
- dev-codex/readme-badge-colours
- dev-codex/php-release-followup
- dev-codex/php-release-2.7.0
- dev-codex/php-5-release
- dev-codex/php-4-docs
- dev-codex/php-2-parity
- dev-codex/php-3-integrations
This package is auto-updated.
Last update: 2026-10-11 13:13:43 UTC
README
Build Slack messages in Python, TypeScript, Go, Java, C#, Ruby, Rust, or PHP — without writing JSON by hand.
Anyone who has built a non-trivial Slack message knows the drill: a wall of nested
Block Kit JSON, five levels deep, where a typo'd
field name or an over-long string sails silently through your code and only blows up
when Slack rejects the API call. slackblocks replaces that JSON with typed objects
that assemble it for you — and that complain at construction time, in your editor and
your tests, rather than in production.
Why slackblocks?
- Concise —
SectionBlock("Hello, *world*!")/SectionBlock.builder().markdownText("Hello, *world*!").build()/new SectionBlock(text: "Hello, *world*!")instead of a ten-line JSON object. - Validated up front — character limits, required fields, mutually-exclusive options, and element-type restrictions are enforced when you construct the block, so you find out before hitting Slack's API.
- Typed — full type hints and
py.typedin Python, strict types in TypeScript, compile-checked concrete fluent builders in Go and Java, and typed constructors with nullable annotations in C#, RBS signatures in Ruby, and consuming builders with typed role enums in Rust, and readonly classes with backed enums in PHP. - Plays well with established Slack clients — unpack a
Messagestraight intoclient.chat_postMessage(**message)withslack-sdk, pass a payload directly to@slack/web-api, pass Go block builders directly toslack-go/slack, pass Java blocks directly to the official Slack Java SDK, serialize C# values withSystem.Text.Json, callto_jsonon Ruby values, use Serde with Rust values, or pass PHP JSON to JoliCode, cURL or Laravel. - One contract across eight implementations — the same blocks, validation rules, and version numbers in Python, TypeScript, Go, Java, C#, Ruby, Rust, and PHP. A shared conformance corpus keeps the implementations emitting the same Slack JSON.
- Everything Block Kit ships today — all current blocks and elements, rich text, modals and Home tabs, and the 2025 block families (tables, cards, carousels, charts).
- Light — zero runtime dependencies in Python, a self-contained ESM module on npm,
one direct Go dependency (
slack-go/slack), Java integration through the official Slack model interfaces, no dependencies beyond .NET itself in C#, Ruby's default JSON gem, Serde/serde_json in Rust, and only built-in JSON/PCRE extensions in PHP.
Installation
TypeScript / JavaScript (Node 20.19+ or 22.12+, ESM)
npm install @nicklambourne/slackblocks
Go (1.22+)
go get github.com/nicklambourne/slackblocks/go/v2
Java (17+)
<dependency> <groupId>io.github.nicklambourne</groupId> <artifactId>slackblocks</artifactId> <version>2.7.0</version> </dependency>
C# (.NET 8+)
dotnet add package Slackblocks
Ruby (3.3+)
gem install slackblocks
Rust (1.85+, edition 2024)
cargo add slackblocks@2.7.0 cargo add serde_json
PHP (8.2+, 64-bit)
composer require nicklambourne/slackblocks:^2.7
PHP support begins with coordinated version 2.7.0. See the PHP package guide for native usage and development setup.
Quickstart
Python
A CI notification:
from slackblocks import ( ActionsBlock, Button, DividerBlock, HeaderBlock, Message, SectionBlock, ) message = Message( channel="#general", text="Build #482 passed", # plain-text fallback for notifications blocks=[ HeaderBlock("Build #482 passed :white_check_mark:"), SectionBlock( fields=[ "*Branch*\n`main`", "*Author*\n@nick", "*Duration*\n3m 12s", "*Tests*\n1,247 passed", ], ), DividerBlock(), ActionsBlock( elements=[ Button(text="View build", action_id="view", url="https://ci.example.com/482"), Button(text="Re-run", action_id="rerun", value="482", style="primary"), ], ), ], )
Send it in one line with the official Slack SDK — the ** operator unpacks
Message objects directly into the call, no to_dict() boilerplate:
import os from slack_sdk import WebClient client = WebClient(token=os.environ["SLACK_API_TOKEN"]) client.chat_postMessage(**message)
TypeScript / JavaScript
import { ActionsBlock, Button, DividerBlock, HeaderBlock, Message, SectionBlock, } from "@nicklambourne/slackblocks"; const payload = Message() .channel("#general") .text("Build #482 passed") // plain-text fallback for notifications .blocks( HeaderBlock().text("Build #482 passed :white_check_mark:"), SectionBlock().fields( "*Branch*\n`main`", "*Author*\n@nick", "*Duration*\n3m 12s", "*Tests*\n1,247 passed", ), DividerBlock(), ActionsBlock().elements( Button().text("View build").actionId("view").url("https://ci.example.com/482"), Button().text("Re-run").actionId("rerun").value("482").style("primary"), ), ) .build();
import { WebClient } from "@slack/web-api"; const client = new WebClient(process.env.SLACK_API_TOKEN); await client.chat.postMessage(payload);
Go
client := slack.New(os.Getenv("SLACK_API_TOKEN")) _, _, err := client.PostMessageContext( context.Background(), "C0123456", slack.MsgOptionText("Build #482 passed", false), slack.MsgOptionBlocks( slackblocks.NewHeaderBlock().Text("Build #482 passed :white_check_mark:"), slackblocks.NewSectionBlock().Fields( "*Branch*\n`main`", "*Tests*\n1,247 passed", ), slackblocks.NewDividerBlock(), ), )
Java
SectionBlock block = SectionBlock.builder() .markdownText("Build #482 passed :white_check_mark:") .build(); var client = Slack.getInstance().methods(System.getenv("SLACK_API_TOKEN")); client.chatPostMessage(ChatPostMessageRequest.builder() .channel("C0123456") .text("Build #482 passed") .blocks(List.of(block)) .build());
C#
using Slackblocks.Blocks; using Slackblocks.Elements; using Slackblocks.Payloads; var message = new MessagePayload( "C0123456", text: "Build #482 passed", // plain-text fallback for notifications blocks: [ new HeaderBlock("Build #482 passed :white_check_mark:"), new SectionBlock(fields: ["*Branch*\n`main`", "*Tests*\n1,247 passed"]), new DividerBlock(), new ActionsBlock([new ButtonElement("View build", "view", url: "https://ci.example.com/482")]), ]); // POST message.ToJson() to chat.postMessage with HttpClient and a bot token.
Ruby
require "slackblocks" message = Slackblocks::MessagePayload.new( channel: "#general", text: "Build #482 passed", # plain-text fallback for notifications blocks: [ Slackblocks::HeaderBlock.new(text: "Build #482 passed :white_check_mark:"), Slackblocks::SectionBlock.new( fields: [ "*Branch*\n`main`", "*Author*\n@nick", "*Duration*\n3m 12s", "*Tests*\n1,247 passed" ] ), Slackblocks::DividerBlock.new, Slackblocks::ActionsBlock.new( elements: [ Slackblocks::ButtonElement.new( text: "View build", action_id: "view", url: "https://ci.example.com/482" ), Slackblocks::ButtonElement.new( text: "Re-run", action_id: "rerun", value: "482", style: :primary ) ] ) ] ) puts message.to_json
Rust
The same validated construction in Rust uses consuming builders and native errors:
use slackblocks::{HeaderBlock, MessagePayload, SectionBlock}; fn main() -> Result<(), Box<dyn std::error::Error>> { let message = MessagePayload::builder("C01234567") .text("Build #482 passed") .block(HeaderBlock::builder().text("Build #482 passed").build()?) .block(SectionBlock::builder().fields(["*Branch*\n`main`", "*Status*\nPassed"]).build()?) .build()?; println!("{}", serde_json::to_string(&message)?); Ok(()) }
Values own their data, getters borrow, and clone().into_builder() supports
editing without mutating the original. See the Rust package guide
and Rust API reference.
PHP
The same construction in PHP uses readonly classes and named arguments:
<?php declare(strict_types=1); require 'vendor/autoload.php'; use Slackblocks as S; $message = new S\MessagePayload( channel: 'C0123456789', text: 'Build #482 passed', blocks: [ new S\HeaderBlock('Build #482 passed'), new S\SectionBlock(fields: ["*Branch*\n`main`", "*Tests*\n1,247 passed"]), new S\ActionsBlock(elements: [ new S\ButtonElement(text: 'View build', actionId: 'view', url: 'https://ci.example.com/482'), ]), ], ); echo $message->toJson();
See the PHP package guide, sending integrations, and PHP API reference.
Documentation
- Full docs: https://nicklambourne.github.io/slackblocks/
- Installation
- Using Blocks — every block type with code in all eight languages, the JSON it produces, and screenshots.
- Sending Messages
- Recipe Book — end-to-end recipes for build notifications, approval requests, modals, and more.
- API Reference — Python, TypeScript, Go, Java, C#, Ruby, and Rust, PHP.
- Migrating from 1.x · Troubleshooting & FAQ
- Changelogs: Python · TypeScript · Go · Java · C# · Ruby · Rust · PHP
- Roadmap — including the TypeScript legacy API removal planned for v3.0.
Repository layout
python/— the established Python package (slackblockson PyPI).typescript/— the TypeScript package (@nicklambourne/slackblockson npm).go/— the Go v2 module (github.com/nicklambourne/slackblocks/go/v2).java/— the Java artifact (io.github.nicklambourne:slackblockson Maven Central).csharp/— the .NET package (Slackblockson NuGet).ruby/— the Ruby gem (slackblockson RubyGems from 2.5.0).php/— native PHP values and Composer package (nicklambourne/slackblockson Packagist from 2.7.0).rust/— the Rust crate (slackblockson crates.io from 2.6.0).spec/— the shared conformance contract: fixtures, invalid cases, limits, and capability coverage that all eight implementations are tested against.docs/— the Docusaurus documentation site.
Download statistics
The Downloads badge sums all-time counts from PyPI (via Pepy), npm, NuGet, RubyGems, crates.io, and Packagist. Go and Maven Central have no comparable public all-time download counters and are excluded. Registry counting rules differ; these counts include automated downloads and do not represent unique users. The total refreshes hourly and shows unavailable if any contributing count is missing or more than 24 hours old.
Licensing
slackblocks is dual-licensed under MIT and
BSD-3-Clause. Use whichever fits your project — this makes it
safe to vendor into projects under either license.
Contributing
Contributions are welcome. Python development uses uv from
python/; TypeScript and the docs site use pnpm from the repository
root:
git clone https://github.com/nicklambourne/slackblocks.git cd slackblocks/python uv sync --group dev uv run pytest test/unit test/conformance test/docs cd .. pnpm install pnpm --filter @nicklambourne/slackblocks test cd go go test -race -cover ./... cd ../java ./mvnw clean verify cd ../csharp dotnet test cd ../ruby bundle install bundle exec ruby -I test -e 'Dir[File.expand_path("test/*_test.rb")].sort.each { |path| require path }'
For the full development guide — testing conventions, the conformance-fixture workflow, docstring style, and the release process — see the Contributing page.
Adding a newly released Slack component or field? Follow the in-repo Adding New Block Kit Features for the shared contract, implementation, test, and documentation checklist.
Adding a new language? Follow the in-repo language implementation guide for native API design, parity, testing, documentation, packaging and release integration.
Bug reports and feature requests: https://github.com/nicklambourne/slackblocks/issues.
