image cache on cloudflare r2
L4 Development Memory#
Commands#
Development#
bun run dev # Start local development server
bun run deploy # Deploy to Cloudflare
bun run types # Generate TypeScript types
Wrangler#
wrangler r2 bucket create l4-images # Create R2 bucket
wrangler secret put AUTH_TOKEN # Set auth token for API uploads
wrangler secret put SLACK_BOT_TOKEN # Set Slack bot token
wrangler secret put SLACK_SIGNING_SECRET # Set Slack signing secret
Project Structure#
/src/index.ts- Worker with Slack bot and upload endpoint/wrangler.toml- Cloudflare Workers configuration/manifest.yaml- Slack app manifest for easy setup
What It Does#
Slack CDN bot for Cloudflare Workers:
- Automatically uploads files posted in Slack to R2
- Returns public URLs in thread
- Uses custom emoji reactions for status (:spinny_fox: → :good_move: or :rac-concern:)
- Also supports direct API uploads with auth token
- Images served with transformations via Cloudflare's edge
Endpoints#
Public#
GET /i/:key?w=800&h=600&f=webp&q=85&fit=scale-down- Serve image with transformations
Slack#
POST /slack/events- Slack Events API endpoint- Listens for
messageevents with files - Downloads files from Slack
- Uploads to R2 with random filename
- Posts URLs in thread
- Listens for
API (requires Authorization: Bearer <AUTH_TOKEN>)#
POST /upload- Upload image (multipart form-data withfilefield)- Returns:
{"success": true, "url": "https://.../i/xxx.jpg"}
- Returns:
Image URL Parameters#
w- widthh- heightf- format (auto, webp, avif, jpeg)q- quality (1-100)fit- fit mode (scale-down, contain, cover, crop, pad)
Environment Variables#
Config (wrangler.toml):
PUBLIC_URL- Public URL of the service (e.g., https://l4.dunkirk.sh)ALLOWED_CHANNELS- Comma-separated Slack channel IDs (e.g., "C12345,C67890"). Leave empty to allow all channels.
Secrets:
AUTH_TOKEN- Auth token for API uploadsSLACK_BOT_TOKEN- Slack bot user OAuth tokenSLACK_SIGNING_SECRET- Slack app signing secret
Bindings#
IMAGES- R2 bucket for image storage
Slack Setup#
Option 1: Using Manifest (Easy)#
- Go to api.slack.com/apps
- Click "Create New App" → "From an app manifest"
- Select your workspace
- Paste contents of
manifest.yaml - Update the request URL if needed
- Install app to workspace
- Copy "Bot User OAuth Token" and "Signing Secret"
- Set secrets in Workers:
wrangler secret put SLACK_BOT_TOKEN wrangler secret put SLACK_SIGNING_SECRET
Option 2: Manual Setup#
- Create Slack app at api.slack.com/apps
- Enable Event Subscriptions, set URL to
https://l4.dunkirk.sh/slack/events - Subscribe to bot events:
message.channels,message.groups,message.im,message.mpim - Add OAuth scopes:
files:read,reactions:write,chat:write - Install app to workspace
- Set secrets in Workers
Usage Examples#
# API upload
curl -X POST https://l4.dunkirk.sh/upload \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "file=@image.jpg"
# Slack: Just post a file in a channel where the bot is invited
Emoji Reactions#
:spinny_fox:- Uploading in progress:good_move:- Upload succeeded:rac-concern:- Upload failed