Back to docsRecipe
Recipe: Companion bot
Build a persistent Discord companion that remembers user context across sessions, enforces rate limits, and stays online 24/7 with Meridian's managed runtime.
Ingredients
- ●Meridian CLI v2.1+ installed and authenticated
- ●Discord bot token with Message Content intent
- ●Upstash Redis for session persistence
- ●Node.js 20 LTS runtime target
Step 1 — Scaffold
meridian init companion-bot --template discord-bare
cd companion-bot
meridian env set DISCORD_TOKEN "your-token-here"
meridian env set UPSTASH_REDIS_URL "redis://..."Step 2 — Session store
import { Redis } from "@upstash/redis";
const redis = new Redis({ url: process.env.UPSTASH_REDIS_URL });
export async function getSession(userId: string) {
const raw = await redis.get(`session:${userId}`);
return raw ? JSON.parse(raw as string) : { history: [] };
}
export async function saveSession(userId: string, data: object) {
await redis.set(`session:${userId}`, JSON.stringify(data), { ex: 86400 });
}Step 3 — Rate limiter
const buckets = new Map<string, { tokens: number; last: number }>();
export function checkRate(userId: string, limit = 5, windowMs = 60000) {
const now = Date.now();
let b = buckets.get(userId);
if (!b || now - b.last > windowMs) {
b = { tokens: limit, last: now };
buckets.set(userId, b);
}
if (b.tokens <= 0) return false;
b.tokens--;
return true;
}Step 4 — Deploy
meridian deploy --production
# Bot is now online 24/7 with persistent sessionsNext: Add slash command handlers with Meridian's built-in interaction router. See Recipe: Slash commands.