CogSend
Self-hosted social scheduler for Mastodon, Bluesky, LinkedIn, Threads and X.
Write a draft, customize it per platform, then publish it now or schedule it.
Single-tenant: one admin account, on your own Cloudflare account, with your own provider credentials.
Install · Updating · Features · Documentation · Stack · Deploy guide · API · Contributing · Security
https://github.com/user-attachments/assets/4e1e623b-e862-4f70-8b48-b764590834f5
Features
- Thread editor: one card per post, images with alt text, a Global tab plus a tab per platform
- Pasting a long draft splits it into a thread that fits the tightest platform you selected, counted each platform's own way (graphemes, Mastodon's URL weighting)
- Link preview cards for URLs in a post
- Publish now with per-destination results, or schedule; cancel, reschedule and retry from Posts
- Retryable failures back off on their own — five attempts, then they park in Failed
- Insights: published against failed over 7, 30 or 90 days, per-account stats and why posts failed
- Disconnecting an account removes its scheduled posts, returns drafts that were still waiting, and keeps published history
- Credentials encrypted at rest (AES-256-GCM), with 2FA on the single admin account
- Personal API key for scripts and Shortcuts (
Settings → API access)
Install
Needs Node 22.12+ and a Cloudflare account with Workers, D1 and R2 available. R2 asks for a payment method on file even on the free tier.
git clone --depth 1 https://github.com/deepakness/cogsend.git cogsend
cd cogsend && npm install && npm run setup
setup is the whole install: wrangler login, the D1 database and the R2 bucket,
the secrets, your admin account, the migrations, the deploy, then one sign-in
against the live Worker to prove it works. Open the URL it prints, sign in, and
scan the QR with an authenticator app — and save the backup codes.
It is safe to re-run: resources, secrets and the account are reused, not replaced.
npm run setup -- --dry-run prints the plan without changing anything, and
docs/deploy.md lists every
command it runs. Lost the password or the authenticator later?
npm run admin:reset -- --all from your checkout
(Configuration → The login).
Updating
git pull && npm ci && npm run deploy:release
deploy:release runs the tests, applies migrations, builds and deploys. Your data
is in D1 and R2, not in the checkout, so a pull cannot touch it. Settings → Instance
and npm run doctor both report the running version and say when a newer release
is out; docs/deploy.md → Updating covers
release tags and rolling back.
Documentation
| Page | What is in it |
|---|---|
| Deploying | the install, what it does command by command, domains and URLs, updating and rolling back, backups, troubleshooting |
| Configuration | secrets, the instance name, APP_URL, keeping your deployment separate from upstream, the login and recovery |
| OAuth apps | LinkedIn, Threads and X app setup, and what each platform allows |
| Scheduling | the cron trigger, the free-plan trigger limit, external pingers, failure emails |
| API | personal API keys and worked examples (the full reference is in-app at /api) |
| Cloudflare Access | putting an extra gate in front of an instance |
| Development | local setup, the checks that must pass, code expectations |
Stack
SvelteKit 2 + Svelte 5 on Cloudflare Workers with Static Assets, D1 (SQLite) via
Drizzle, R2 for media, and a per-minute cron trigger — or any external cron
calling /api/internal/tick.
Comments