Site for users, worker for Discord
The production site is a static Vite build. It needs only a Supabase project URL and a public anon/publishable key at build time. It never serves the Discord token and never needs the Supabase service-role key.
Users sign in with Discord. The directory includes only servers where their Discord account has Administrator permission and the KeyCord bot is installed. Each server row reports the bot gateway connection state. The separate bot.mjs process runs continuously on your bot server. It reads the Discord token from Supabase Vault, consumes queued actions, publishes safe status, and streams activity through Supabase Realtime.
You deploy the frontend and worker independently. They must use the same Supabase project and workspace ID. A “Worker offline” status means the worker has not published a recent heartbeat; it is not a website setup step.
Configure Supabase once
- Create a Supabase project and run the complete
supabase/keycord.sqlfile in its SQL Editor. If you already ran an older version, run the updated file again; it also clears queued OAuth credentials after each command completes. - Run
supabase/20261005_developer_support.sqlafter the base schema to enable the private support inbox and developer-only identity checks. - In Supabase Auth settings, enable new user signups and the Discord provider, then add your deployed site origin to allowed redirect URLs.
- Enter your Discord OAuth client ID and secret in Supabase Auth. Add Supabase’s callback URL to the Discord application’s OAuth2 redirect URLs. KeyCord requests the
identifyandguildsscopes so it can verify the signed-in Discord identity and server permissions. - Users sign up and sign in through Discord only. No email login or Google provider is used. A first sign-in asks for a display name.
- No email invitation or membership SQL is required. The server directory is restricted to guilds where the current Discord user has Administrator permission and the bot is installed.
Supabase Vault connection
Run the statement in the Supabase SQL Editor. Rotate it there too; do not paste it into the site or frontend build environment.
Developer-only bot controls
Only Discord accounts linked to developer IDs 930813224088141855 and 1212171442691776584 can change the bot status and description. Everyone else sees those controls locked.
The same identity check is enforced in Supabase row-level security and again in the bot worker. Workspace membership roles do not grant this permission.
Build for any static host
Copy .env.frontend.example to .env.local for a local build, or set the values in your static host's build settings. Set VITE_SITE_URL to your canonical production origin so Discord sign-in returns to the deployed site. These VITE_ variables are intentionally public: browser users can inspect them. Supabase Auth and row-level security protect workspace data.
Publish the generated dist/ directory. The included public/_redirects supports clean page URLs on hosts that use Netlify-style redirects; configure equivalent rewrites on other hosts for /composer, /docs, and the other page paths. For local development, use npm run dev.
In Supabase Auth URL Configuration, set the Site URL to your deployed origin and add it to allowed redirect URLs. For Discord's Developer Portal, configure Supabase's callback URL (https://<project-ref>.supabase.co/auth/v1/callback), not the website URL. Keep the public anon key only in site configuration; never use the service-role key here.
Run bot.mjs on a persistent server
Use Node.js 22 or newer. Copy index.js, bot.mjs, package.json, and package-lock.json to the bot host. The small index.js entrypoint supports hosts that default to node index.js. Install production dependencies and set the private environment values through that host's secret manager:
The service-role key must never be put in a browser bundle, static host environment, or source control. The worker retrieves the encrypted Discord token from Vault and normally connects the Gateway automatically. Keep it running with systemd, Docker, or your process manager of choice. Check its logs if Settings shows “Worker offline.”
Set KEYCORD_AUTOCONNECT=false if you prefer to start the Discord Gateway from the signed-in dashboard. The worker still needs to stay online to process commands.
Bot application and permissions
Create an application in the Discord Developer Portal, add a bot, and save its token in Supabase Vault as shown above. Enable Message Content Intent only if incoming message text should appear in the activity feed.
Invite the bot only to servers where it should operate. Begin with View Channels, Send Messages, Embed Links, and Read Message History. Add Add Reactions, Manage Messages, or Manage Channels only for modules that need them.
Focused pages, shared live state
Dashboard and Analytics
Worker health, gateway status, activity, delivery counts, queue signals, and uptime.
Composer and Campaigns
Send messages or rich embeds, and run bounded one-pass sequences with pacing and optional shuffle.
Servers
Browse guilds and text channels, inspect recent messages, then hand IDs to an action.
Automation
Set bot presence, react with Unicode or selected-server emojis, and broadcast to a limited set of channels. The emoji picker includes the standard emoji set; personal custom image uploads are stored privately in Supabase.
Moderation
Edit channels, delete one explicitly selected message, or purge a bounded number of bot messages, user messages, or both. User-message deletion requires the bot to have Manage Messages.
Settings and Docs
Inspect access, Supabase connectivity, worker heartbeat, Discord gateway status, and permission guidance.
Keep each credential in its lane
- Frontend: Supabase URL and anon/publishable key only. Authenticated users can read workspace status and enqueue the allow-listed bot actions.
- Developer-only bot presence: only Discord IDs
930813224088141855and1212171442691776584can change status and description. RLS and the worker both verify the linked Discord identity. - Supabase Vault: encrypted Discord bot token, retrievable only by the server-side service role.
- Bot host: Supabase service-role key in a private environment/secret manager. It is a powerful credential; rotate it immediately if exposed.
- Public registration: anyone can create an account and use regular modules. Workspace admin roles do not grant developer-only controls.
The frontend never connects directly to Discord. It inserts a command into Supabase, then receives completion through database reads and live state through Realtime.