A long-running Discord bot written in TypeScript that answers FireCMS and Firebase related questions using the gemini-3.5-flash model and the official FireCMS documentation.
- Knowledge-Backed Answers: Dynamically loads
llms.txt(the complete FireCMS docs) into the model's system context for 100% accurate, hallucination-free answers. - Thread & Reply Support: Follows conversation context within DMs, threads, and message replies.
- Auto-Chunking: Automatically splits answers exceeding Discord's 2000-character limit without breaking code blocks or words.
- Typing Indicator: Shows when the bot is processing/generating an answer.
To run the bot, you need to register an application on the Discord Developer Portal:
- Visit the Discord Developer Portal.
- Click New Application and give it a name (e.g.,
FireCMS Helper). - Navigate to the Bot tab on the left sidebar:
- Click Add Bot.
- Under Privileged Gateway Intents, enable:
- Guild Members Intent (Optional, but recommended)
- Presence Intent (Optional)
- Message Content Intent (
⚠️ Required to read incoming user messages)
- Click Reset Token and copy the bot token. Keep this safe (this is your
DISCORD_TOKEN).
- Navigate to the OAuth2 tab on the left sidebar, then click URL Generator:
- Under Scopes, select
bot. - Under Bot Permissions, select:
Read Messages/View ChannelsSend MessagesSend Messages in ThreadsRead Message HistoryAdd Reactions
- Copy the generated URL and open it in your browser to invite the bot to your Discord server.
- Under Scopes, select
Create a .env file in the discord-bot/ directory with the following variables:
# Your Discord bot token (from the developer portal)
DISCORD_TOKEN=your_discord_token_here
# Your Google Gemini API Key
GEMINI_API_KEY=your_gemini_api_key_here
# The Gemini model to use (defaults to gemini-3.5-flash if not specified)
GEMINI_MODEL=gemini-3.5-flash
# Optional: Comma-separated list of channel IDs where the bot is allowed to reply.
# If omitted or empty, the bot responds in all channels it can access.
ALLOWED_CHANNELS=From the root of the monorepo:
yarn installyarn discord-bot:dev# Build the package
yarn build
# Start the bot
yarn discord-botSince this bot maintains a persistent WebSocket connection to Discord, it needs to run continuously. We can achieve this on Cloud Run by configuring a minimum instance count of 1.
Set your GCP project ID and build the Docker container using Google Cloud Build:
# Set your GCP project ID
export PROJECT_ID="your-gcp-project-id"
# Submit build to Google Cloud Build (run from the monorepo root)
gcloud builds submit --tag gcr.io/$PROJECT_ID/firecms-discord-bot:latest .Deploy the image to Cloud Run as a service. We must set:
--no-cpu-throttling(ensures background tasks like websocket heartbeats run normally)--min-instances 1(keeps the container alive so it doesn't disconnect from Discord)- Secret or Env vars for
DISCORD_TOKENandGEMINI_API_KEY.
gcloud run deploy firecms-discord-bot \
--image gcr.io/$PROJECT_ID/firecms-discord-bot:latest \
--platform managed \
--region europe-west3 \
--min-instances 1 \
--no-cpu-throttling \
--set-env-vars="GEMINI_MODEL=gemini-3.5-flash" \
--set-secrets="DISCORD_TOKEN=DISCORD_TOKEN:latest,GEMINI_API_KEY=GEMINI_API_KEY:latest" \
--no-allow-unauthenticated(Note: If you prefer simple env variables instead of GCP Secret Manager secrets, you can replace --set-secrets with --set-env-vars="DISCORD_TOKEN=...,GEMINI_API_KEY=...")