diff --git a/python/README.md b/python/README.md
index af51b37..749ee24 100644
--- a/python/README.md
+++ b/python/README.md
@@ -28,7 +28,7 @@ This release conforms to the shared cross-language slackblocks specification.
pip install slackblocks
```
-`slackblocks 2.x` requires Python 3.10 or newer. Users on Python 3.8 / 3.9 should pin to the `1.x` line — see the [Compatibility](https://nicklambourne.github.io/slackblocks/latest/usage/compatibility/) page.
+`slackblocks 2.x` requires Python 3.10 or newer. Users on Python 3.8 / 3.9 should pin to the `1.x` line — see the [Compatibility](https://nicklambourne.github.io/slackblocks/usage/compatibility) page.
## Quickstart
@@ -108,18 +108,18 @@ The `**` operator unpacks `slackblocks` `Message` objects directly into the SDK
- **Tighter type signatures**: `Literal` narrowing on `Button.style`, `ColumnSettings.align`, `ConversationFilter.include`; `@overload` on `Text.to_text` so the return type narrows on `allow_none`.
- **Modern annotation syntax** (`list[X]`, `X | Y`) throughout.
-Existing 1.x code continues to work unchanged; see the [Migration Guide](https://nicklambourne.github.io/slackblocks/latest/usage/migration/) for the full diff.
+Existing 1.x code continues to work unchanged; see the [Migration Guide](https://nicklambourne.github.io/slackblocks/usage/migration) for the full diff.
## Documentation
- **Full docs:**
-Typed Block Kit construction with eager, path-aware validation and conformance with the shared cross-language slackblocks specification.
+
+
+
+[](https://www.npmjs.com/package/@nicklambourne/slackblocks)
+[](https://www.npmjs.com/package/@nicklambourne/slackblocks)
+[](https://github.com/nicklambourne/slackblocks/actions)
+[](https://nicklambourne.github.io/slackblocks)
+
+> **Build Slack messages in TypeScript — without writing JSON by hand.**
+
+`slackblocks` is a typed, validating TypeScript wrapper around the Slack
+[Block Kit API](https://docs.slack.dev/block-kit/). It exists because Block Kit JSON is
+verbose, easy to get subtly wrong, and unpleasant to maintain in source control.
+
+This release conforms to the shared cross-language slackblocks specification.
+
+## Why `slackblocks`?
+
+- **Concise** — `sectionBlock({ text: "Hello, *world*!" })` instead of a 10-line JSON object.
+- **Validated** — character limits, required fields, mutually-exclusive options, and
+ element-type restrictions are enforced at construction time, with a typed error
+ hierarchy (`LengthError`, `MissingRequiredError`, …), so you find out *before* hitting
+ Slack's API.
+- **Typed** — strict factory inputs reject typo'd and excess properties at compile time;
+ what you get back is the plain Slack-shaped object, ready for the wire.
+- **Drop-in compatible** with the official [`@slack/web-api`](https://www.npmjs.com/package/@slack/web-api)
+ and [Bolt](https://www.npmjs.com/package/@slack/bolt) — pass a `message(...)` payload
+ straight to `client.chat.postMessage(payload)`.
+- **The same library in two languages** — the Python
+ [`slackblocks`](https://pypi.org/project/slackblocks/) shares the blocks, the
+ validation rules, and the version number; a shared conformance corpus keeps both
+ emitting the same Slack JSON.
+- **Self-contained** — a single ESM module with no runtime imports.
+
+## Installation
```bash
npm install @nicklambourne/slackblocks
```
+Requires Node `20.19+` or `22.12+`. The package ships as ESM; on these Node versions
+CommonJS consumers can `require()` it directly.
+
+## Quickstart
+
```ts
import {
+ actionsBlock,
button,
dividerBlock,
+ headerBlock,
message,
- mrkdwn,
sectionBlock,
} from "@nicklambourne/slackblocks";
const payload = message({
- channel: "C0123456",
+ channel: "#general",
+ text: "Build #482 passed", // plain-text fallback for notifications
blocks: [
+ headerBlock({ text: "Build #482 passed :white_check_mark:" }),
sectionBlock({
- text: mrkdwn("*Deploy complete* :rocket:"),
- accessory: button({
- text: "View logs",
- actionId: "logs",
- url: "https://example.com/logs",
- }),
+ 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" }),
+ ],
+ }),
],
});
```
-Factory inputs use idiomatic camelCase and return plain Slack-shaped objects with snake_case keys. Factories validate eagerly; pass `{ validate: false }` as the final argument for Slack features that have moved ahead of this package's limits registry.
+`payload` can be sent in one line with the official Slack SDK:
+
+```ts
+import { WebClient } from "@slack/web-api";
+
+const client = new WebClient(process.env.SLACK_API_TOKEN);
+await client.chat.postMessage(payload);
+```
+
+
+
+