Slack bot that hosts HTML/ZIP files with channel-based access control. Only members of the Slack channel where content was shared can view it.
src/
index.ts # Main entry point, routing
types.ts # Shared TypeScript types
auth/ # Authentication
oauth.ts # Slack OAuth2 flow
session.ts # Session management (KV-backed)
middleware.ts # Auth middleware
slack/ # Slack integration
events.ts # Event handling (app_mention)
api.ts # Slack API helpers
signature.ts # Request signature verification
types.ts # Slack-specific types
storage/ # Data storage
r2.ts # R2 upload/download
metadata.ts # Page metadata (channel, uploader)
zip.ts # ZIP extraction
viewer/ # Content viewing
serve.ts # Serve files from R2
access.ts # Channel membership verification
npm install# Create R2 bucket
wrangler r2 bucket create htmlez-content
# Create KV namespaces
wrangler kv:namespace create SESSIONS
wrangler kv:namespace create METADATACopy the KV namespace IDs from the output and update wrangler.toml.
Go to https://api.slack.com/apps and create a new app.
OAuth & Permissions > Bot Token Scopes:
channels:history- Read channel messagesgroups:history- Read private channel messagesfiles:read- Download fileschat:write- Post messagesapp_mentions:read- Receive mentions
OAuth & Permissions > User Token Scopes:
identity.basic- Get user identityidentity.team- Get user's team
OAuth & Permissions > Redirect URLs:
Add: https://htmlez.YOUR_SUBDOMAIN.workers.dev/auth/callback
Install to Workspace and copy:
- Bot User OAuth Token (
xoxb-...) - From Basic Information: Client ID, Client Secret, Signing Secret
# Bot token for API calls
wrangler secret put SLACK_BOT_TOKEN
# paste xoxb-... token
# Signing secret for webhook verification
wrangler secret put SLACK_SIGNING_SECRET
# OAuth credentials (for user login)
wrangler secret put SLACK_CLIENT_ID
wrangler secret put SLACK_CLIENT_SECRETSet your:
ACCOUNT_ID- Find in Cloudflare dashboard URLWORKER_URL- Your worker's public URL- KV namespace IDs from step 2
wrangler deploy- Go to Event Subscriptions in your Slack app
- Enable Events
- Request URL:
https://htmlez.YOUR_SUBDOMAIN.workers.dev/slack/events - Subscribe to bot events:
app_mention - Save and reinstall if prompted
/invite @htmlez
- Upload an HTML or ZIP file to a Slack channel
- Mention
@htmlezin the channel - The bot replies with a secure link
- Only members of that channel can view the page (they'll need to sign in with Slack)
- When content is uploaded, we store the channel ID as metadata
- When someone tries to view, they must authenticate via Slack OAuth
- We check if the authenticated user is a member of the original channel
- If yes, serve the content. If no, show "Access Denied"
# Start local dev server
wrangler dev
# Expose to internet for Slack webhooks
npx ngrok http 8787Update your Slack app's Request URL to the ngrok URL during development.
| Path | Description |
|---|---|
/ |
Home page |
/health |
Health check |
/slack/events |
Slack webhook endpoint |
/auth/slack |
Start OAuth flow |
/auth/callback |
OAuth callback |
/auth/logout |
Clear session |
/view/{pageId} |
View uploaded content |
/view/{pageId}/{path} |
View specific file in ZIP |