Tightknit turns Slack into a complete community platform with events, gamification, analytics, SEO, and branded spaces. Trusted by teams at Amplitude, Mixpanel, Clay, and more.
翻訳待ち
ソーシャルTypeScript · ShellGitHub @TightknitAIオンライン所有者未確認
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Template app — Slack Block Kit Builder UI on Cloudflare Workers, sending messages via slack-hono.
翻訳待ち
Loading the full README.
Read the full README ↗A Vite + React SPA on Cloudflare Workers that uses block-kitchen to compose Slack messages and post them via slack-hono + slack-web-api-client. Validates every send against slack-block-kit-validator for defense in depth.
/ — drag blocks, edit them in popovers, preview them in real time./slack/install → /slack/oauth_redirect for installing the app into a workspace (bot token stored in KV)./slack/user-install → /slack/user-oauth-redirect for "send as me" support (user token stored in a separate KV).GET /api/slack/channels → { channels, truncated } (paging is capped — see Channel loading)GET /api/slack/emojis (workspace custom emoji via emoji.list, normalized to { name, url, alias }[])GET /api/slack/me/can-send-as-userPOST /api/slack/messages/send (validates blocks, picks bot vs user token, calls chat.postMessage)/slack/events ingress wired through slack-hono — empty by default, ready for you to add slash commands, events, and actions.You'll need a Slack workspace where you can install apps. Options:
pnpm install
pnpm run setup:kv
Five namespaces are created:
SLACK_INSTALLATIONS — bot tokens, keyed by team IDSLACK_USER_INSTALLATIONS — user tokens, keyed by team_id:user_idSLACK_OAUTH_STATE — short-lived OAuth state tokensSLACK_MODAL_VIEWS — composed modal view payloads (7-day TTL), keyed by short IDSLACK_SESSIONS — server-side sessions that bind a browser to a workspace and user, keyed by an opaque session IDPaste the IDs from the output into wrangler.jsonc (five placeholders).
pnpm run dev:tunnel
Copy the tunnel URL from the output (e.g. https://xxx-yyy-zzz.trycloudflare.com).
Quick tunnels generate a fresh URL every restart. For a fixed URL during dev, run
pnpm run setup:tunnel <hostname>once (requires a domain on Cloudflare).
pnpm run setup:manifest https://xxx-yyy-zzz.trycloudflare.com
Updates manifest.json with your tunnel URL, copies it to your clipboard, and opens api.slack.com/apps/new. Choose From an app manifest, paste, Next → Create.
Grab Signing Secret, Client ID, Client Secret from your app's Basic Information page.
cp .dev.vars.example .dev.vars
# fill in the values
Restart the dev server to pick up the new secrets.
pnpm run install-app
Opens /slack/install on your tunnel. After OAuth completes, the app sets a workspace-identity cookie and redirects you to /, where the builder is ready to use.
Drag a header + section block into the canvas, click Send, pick a channel, hit confirm — your first Block Kit message lands in Slack.
Stuck? Run
pnpm run setup:doctorfor a preflight that audits KV ids,.dev.vars, manifest URL substitution, interactivity, and bot scopes, and prints a punch list of what still needs doing.
The builder's send dialog has a Send as me toggle. The first time you flip it on, the SPA detects you don't have a user token yet and shows a Sign in with Slack link — that takes you through a second OAuth round-trip (/slack/user-install) that issues a user token with chat:write,im:write scopes. After that round-trip, future sends with the toggle on are posted as you instead of the bot.
User tokens live in their own KV (SLACK_USER_INSTALLATIONS) keyed by team_id:user_id. Revoking happens by deleting the row.
The builder's emoji picker and live preview resolve your workspace's custom emoji. On mount the SPA calls GET /api/slack/emojis, which proxies Slack's emoji.list (using the bot token) and normalizes the response into the shape block-kitchen's customEmojis prop expects:
type CustomEmoji = {
name: string; // codename between colons — `:partyparrot:` → "partyparrot"
url: string | null; // hosted image for a real custom emoji, null for an alias
alias: string | null; // target codename when this entry aliases another, else null
};
Slack returns a { name: value } map where value is either an image URL or alias:<target>; the worker splits that into the url / alias fields. The SPA hands the resulting array straight to <BlockKitchen customEmojis={…} /> (see src/client/App.tsx) — a plain prop, resolved up front, rather than a lazy loader like loadChannels / loadSendAsUserStatus / onSend. With it set, the picker gains a Custom category and the preview renders :custom: directives as the workspace image (aliases fall back to their target).
This is the beginning of the README. Read the rest at the original. Read the full README ↗