From slack
Guides developers in building and validating Slack Block Kit layouts for messages, modals, and Home tabs. Provides block references, JSON generation, and schema validation.
How this skill is triggered — by the user, by Claude, or both
Slash command
/slack:block-kit [message | modal | home-tab][message | modal | home-tab]The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Help the developer build a rich Block Kit layout. If `$0` is provided, it specifies the target surface (`message`, `modal`, or `home-tab`).
Help the developer build a rich Block Kit layout. If $0 is provided, it specifies the target surface (message, modal, or home-tab).
This skill walks through surface selection, layout planning, JSON generation, and validation. Block types, elements, and fields come from the live docs (see Source of Truth below) — discover them and read each component's schema there, never from memory.
Common Block Kit mistakes (and why): A few errors recur often enough to flag up front. Most others are caught by
blocks.validatein Step 5, so lean on validation rather than memorizing rules.
"type": "text"is not a thing. Text is a composition object:{ "type": "plain_text", "text": "..." }or{ "type": "mrkdwn", "text": "..." }.markdownis a block type, not a text type. Amarkdownblock holds standard markdown; text objects inside other blocks usemrkdwn(see mrkdwn vs. themarkdownblock in Step 4). Slack'smrkdwnis*bold*/_italic_/~strike~, not**bold**.- Messages need a top-level
textfallback.blocks.validatewon't flag a missing one, but notifications and screen readers display it instead of the blocks — so summarize what the layout conveys rather than leaving it empty.
Every block, element, and composition object is documented on docs.slack.dev. Append .md to any reference URL to fetch it as markdown with WebFetch (no auth required).
https://docs.slack.dev/reference/block-kit.md. WebFetch it to confirm a type exists and to get the link to its page.https://docs.slack.dev/reference/block-kit/blocks/<slug>-block.mdhttps://docs.slack.dev/reference/block-kit/block-elements/<slug>-element.mdhttps://docs.slack.dev/reference/block-kit/composition-objects/<slug>.mddatepicker maps to date-picker-element.md, and every *_select menu (static_select, users_select, multi_channels_select, and so on) is documented on select-menu-element.md. When unsure of a slug, follow the link from the master index rather than building the URL by hand.https://docs.slack.dev/messaging/formatting-message-text.md, modals at https://docs.slack.dev/surfaces/modals.md, and Home tabs at https://docs.slack.dev/surfaces/app-home.md.Never use a block type, element, or field you have not seen on a live page.
If the developer's request is specific enough to determine both the target surface and the desired layout, collapse Steps 1-4 into a single pass:
$0 or contextFast-path indicators (skip the full workflow):
Full-workflow indicators (use Steps 1-7):
If the developer provides existing Block Kit JSON (pasted inline, in a file, or referenced from code), enter Modification Mode instead of the full creation workflow:
Parse the existing structure:
"type": "modal" = modal, "type": "home" = home tab, bare blocks array = messageAsk what changes they want:
Apply changes while preserving:
block_id values (these are referenced in app interaction handlers)action_id values (these map to event listeners)Validate the modified JSON: proceed to Step 5 (validation)
Detection: If the developer's message contains a JSON array starting with [{"type": or a view object with "blocks":, enter Modification Mode automatically. If they say "edit", "update", "modify", or "change" in reference to existing blocks, ask them to provide the current JSON.
If $0 is provided and matches one of message, modal, or home-tab, use it directly.
Otherwise, ask the developer using AskUserQuestion:
Once the surface is determined, use the correct payload structure for it:
{ "text": "Fallback text", "blocks": [...] } object posted via chat.postMessage (and friends). The text field is the notification/accessibility fallback. For message text formatting (mrkdwn, mentions, dates), see https://docs.slack.dev/messaging/formatting-message-text.md.{ "type": "modal", "title": ..., "blocks": [...] }). For the full view object structure, lifecycle, and the rule that submit is required when the view contains any input block, see https://docs.slack.dev/surfaces/modals.md.{ "type": "home", "blocks": [...] }) published via views.publish. For structure and behavior, see https://docs.slack.dev/surfaces/app-home.md.Ask the developer to describe what they want their layout to look like or accomplish.
If they need inspiration, suggest examples — several map directly onto a ready-made template in references/common-patterns.md (named in parentheses), which you can start from in Step 3:
Get enough detail to plan the layout before generating any JSON.
Based on the developer's description:
https://docs.slack.dev/reference/block-kit.md) to confirm the block and element types you plan to use exist and to grab links to their pages.references/common-patterns.md (the one local reference file) if the request matches a common pattern; start from the template instead of building from scratch.1. header: "Weekly Report"
2. section: Summary text with a datepicker accessory
3. divider
4. section: Status fields (Name, Role, Team)
5. actions: "Approve" button (primary) and "Reject" button (danger)
Surface constraints to check:
input blocks, the modal payload must include a submit fieldtable block per messageblocks.validate in Step 5 confirm it. It is the authoritative check.Once the layout is approved, build each block from its live doc page, fetching each page's fields table (required vs optional, constraints) and JSON example with WebFetch. The URL patterns are in Source of Truth above; the one slug to remember is that every *_select menu (static_select, users_select, multi_channels_select, …) lives on select-menu-element.md. Fetch pages as you need them and reuse what you have already fetched — don't re-fetch the same page for every block of the same type. Then build the payload block-by-block and wrap it in the surface structure from Step 1.
Guidelines:
action_id values (e.g., "approve_report_btn" not "action_1") — they identify the element in your interaction handlersblock_id values where the developer will need them for interaction handlingtitle, submit, close, and callback_id; for home tabs, the type: "home" wrappermrkdwn text for rich formatting, plain_text where required (headers, labels, modal title)mrkdwn vs. the markdown block: section and context blocks format text with Slack's mrkdwn (*bold*, _italic_, ~strike~, `code`) — use these for short, interactive layouts. The separate markdown block (Messages only) renders standard markdown (**bold**, headings, tables, numbered lists) and is meant for AI/LLM-generated or long-form content that already exists in standard markdown. Reach for it when the developer has such content or needs those features in the message body; there is a cumulative 12,000-character limit across all markdown blocks in one message.
Accessibility is easy to skip and hard to retrofit, so build it in now:
alt_text (what the image shows, not just "image"), and make sure image-heavy layouts also carry the key information as texttext fallback (notifications and screen readers show it instead of the blocks)header blocks for logical section headings — they convey document structure to assistive techPresent the complete payload to the developer in the Step 1 surface structure.
Always validate. blocks.validate is a public Web API method, so no auth token is required.
The authoritative reference for this method (its parameters, auth requirements, and response/error shape) is the live doc. WebFetch it before relying on any detail here: https://docs.slack.dev/reference/methods/blocks.validate.md. It documents the accepted parameters (blocks for a message's blocks array, view for a modal/home-tab view, message for a full message payload; send exactly one) and the response shape.
Prefer the Slack CLI when it's available, since it reuses the slack-cli skill's CLI detection and needs no token wrangling. If the CLI isn't installed, fall back to curl. Both call the same public method and return the same response, so Step 5b applies either way.
Path A: Slack CLI (preferred).
Use the slack-developer:slack-cli skill, Step 1: Detect the Slack CLI, to check whether the public CLI is installed and resolve its command (SLACK_CMD).
If the CLI is available, use the slack-developer:slack-cli skill, Step 4: Calling Web API Methods (slack api), to invoke it. That step covers the SLACK_CMD api <method> key=value … syntax. Run SLACK_CMD api --help first to confirm the syntax and the flag that skips authentication. blocks.validate needs no token, so call it without authentication. Don't hard-code that flag from memory; read it from the help output so this stays correct if it's ever renamed. Pass the payload as a positional key=value argument: blocks=<JSON array> for messages, or view=<JSON view object> for modals and home tabs.
Path B: curl (fallback, when the CLI isn't installed).
POST to the endpoint with the Bash tool. The API uses form-urlencoded encoding, so pass the JSON directly as the parameter value.
For messages, send the blocks array as a form-encoded parameter:
curl -s -X POST 'https://slack.com/api/blocks.validate' \
-d 'blocks=[ ... the blocks array ... ]'
For modals and home tabs, send the complete view object in the view field:
curl -s -X POST 'https://slack.com/api/blocks.validate' \
-d 'view={ "type": "modal", "title": ..., "blocks": [...] }'
For large payloads, if the JSON is complex or contains special characters, write it to a temp file to avoid shell escaping issues:
curl -s -X POST 'https://slack.com/api/blocks.validate' \
--data-urlencode "blocks@/tmp/blocks.json"
Success:
{ "ok": true }
Tell the developer their blocks are valid.
Failure:
{
"ok": false,
"error": "invalid_blocks",
"errors": [
{
"code": "missing_field",
"message": "missing required field: type",
"field": "type",
"pointer": "/0"
}
]
}
When validation fails:
pointer is a JSON pointer to the offending node (e.g., /0 = first block, /2/elements/1 = second element of the third block, /0/text/type = the type field of the first block's text object). message describes the problem, and constraint (when present) names the rule that failed and its expected values.https://docs.slack.dev/reference/methods/blocks.validate.md) and the relevant block/element/composition-object page you fetched in Steps 3-4."ok": true.If validation fails 3 times on the same error:
https://app.slack.com/block-kit-builderPresent the validated payload, then help the developer put it to use.
Building the payload is this skill's job; sending it (chat.postMessage, views.open, views.publish, and the token/scope handling around them) belongs to the Web API layer. To call the right method — via the Slack CLI, raw curl, or a Bolt SDK — use the slack-developer:slack-api skill, Step 4: Call the Method (Manage), passing this payload as the method's blocks argument (messages) or view argument (modals and home tabs). That skill matches the argument names to the SDK or HTTP call so we don't duplicate them here.
Offer a Block Kit Builder link so the developer can see a live preview and tweak visually: https://app.slack.com/block-kit-builder. Builder needs an object ({ "blocks": [...] } or a full view object), not a bare array. Suggest this proactively when the developer says something is "not quite right" but can't articulate what, when the layout has 10+ blocks, or when iteration isn't converging.
Ask whether the developer wants to add, modify, remove, or reorder blocks, or build a layout for a different surface. If they want to change the layout you just produced, re-enter Modification Mode (it preserves their block_id/action_id values); for a fresh layout, loop back to Step 3.
blocks.validate. Sending it lives in the Web API layer (slack-developer:slack-api), and CLI detection/auth in slack-developer:slack-cli.blocks.validate needs no auth — it's a public method, so it works without a token whether you call it via the CLI or curl. Always validate before finalizing (Step 5).npx claudepluginhub anthropics/claude-plugins-official --plugin slackGuides mrkdwn syntax, message structure, thread etiquette, and tone for effective Slack messages in dev workflows.
Provides formatting and etiquette guidance for composing clear Slack messages using markdown, useful when sending messages via MCP tools.
Recommends and installs shadcn/ui components plus 1,338 premium ShadcnBlocks and 1,189 free components for React/Next.js + Tailwind frontends like landing pages, dashboards, heroes, and pricing sections.