Skip to main content

Environment Variables

Jill Stingray uses environment variables for all configuration. Create a .env file in the project root with the following settings.

Required Variables

These variables are required for the bot to function:
DISCORD_TOKEN
string
required
Discord bot token from the Developer Portal.
index.js (Line 20)
const TOKEN = process.env.DISCORD_TOKEN;
Example:
DISCORD_TOKEN=MTIzNDU2Nzg5MDEyMzQ1Njc4OQ.GhIjKl.MnOpQrStUvWxYz1234567890AbCdEfGhIjKl
DATABASE_URL
string
required
PostgreSQL connection string for persistent data storage.
utils/db.js (Line 4)
connectionString: process.env.DATABASE_URL,
Format:
DATABASE_URL=postgresql://username:password@host:port/database_name
Examples:
# Local PostgreSQL
DATABASE_URL=postgresql://postgres:password@localhost:5432/jillbot

# Supabase
DATABASE_URL=postgresql://postgres:[password]@db.[project].supabase.co:5432/postgres

# Railway
DATABASE_URL=postgresql://postgres:[email protected]:5432/railway
The bot automatically creates all required tables on startup. No manual schema setup needed.

Optional API Keys

These variables enable specific features:
SUPABASE_URL
string
Supabase project URL for cloud storage (image uploads, palette generation).
utils/supabase.js (Line 5)
const supabaseUrl = process.env.SUPABASE_URL;
Example:
SUPABASE_URL=https://abcdefghijklmnop.supabase.co
Required for /palette command and any features that upload images to cloud storage.
SUPABASE_SERVICE_KEY
string
Supabase service role key for bypassing Row Level Security (RLS).
utils/supabase.js (Line 6)
const supabaseKey = process.env.SUPABASE_SERVICE_KEY || process.env.SUPABASE_KEY;
Example:
SUPABASE_SERVICE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
If not set, the bot falls back to SUPABASE_KEY (anon key). This may cause upload failures if your Supabase bucket has RLS enabled.
utils/supabase.js (Lines 8-10)
if (!process.env.SUPABASE_SERVICE_KEY) {
  console.warn("⚠️ WARNING: SUPABASE_SERVICE_KEY not found. Uploads might fail if Bucket RLS is not open.");
}
MAPILLARY_TOKEN
string
Mapillary API token for Geoguessr street imagery.
commands/geo.js (Line 24)
const MAPILLARY_TOKEN = process.env.MAPILLARY_TOKEN;
Get a token: Mapillary Developer PortalExample:
MAPILLARY_TOKEN=MLY|1234567890|abcdefghijklmnopqrstuvwxyz
Without this token:
  • Geoguessr falls back to cached locations from data/fallback_cache.json
  • If cache is empty, uses hardcoded Tokyo location
With this token:
  • Fetches random street-level imagery globally
  • Supports Africa, Asia, Americas, Europe, and Oceania regions
GROQ_API_KEY
string
Groq API key for AI-powered 8ball responses.
commands/8ball.js (Line 6)
const groq = new Groq({ apiKey: process.env.GROQ_API_KEY });
Get a key: Groq ConsoleExample:
GROQ_API_KEY=gsk_abcdefghijklmnopqrstuvwxyz1234567890
Only required for /8ball command. Other commands function normally without it.
BOT_OWNER_ID
string
Your Discord user ID for bot owner permissions.
utils/permissions.js (Line 3)
const BOT_OWNER_ID = process.env.BOT_OWNER_ID;
Find your ID:
  1. Enable Developer Mode in Discord (User Settings → Advanced)
  2. Right-click your username → Copy ID
Example:
BOT_OWNER_ID=123456789012345678
Owner-only commands include:
  • /purge - Bulk message deletion
  • /audit - System audit logs
  • Developer utilities
PORT
number
default:"8080"
HTTP server port for health checks and keep-alive.
index.js (Line 105)
.listen(process.env.PORT || 8080);
Example:
PORT=8080
The bot exposes a simple HTTP endpoint that responds with:
Jill Stingray is mixing drinks...

Example Configuration

# Minimal configuration - Core features only
DISCORD_TOKEN=your_discord_bot_token_here
DATABASE_URL=postgresql://user:password@host:5432/database
BOT_OWNER_ID=123456789012345678
PORT=8080

Feature Requirements

Different features require different environment variables:
Required:
  • DISCORD_TOKEN
  • DATABASE_URL
Enables:
  • All basic commands (/help, /ping, /userinfo, etc.)
  • Moderation tools (/mute, /role, /purge)
  • Activity tracking and regulars system
  • Custom role management
  • Trigger system
Required:
  • DISCORD_TOKEN
  • DATABASE_URL
Optional:
  • None (uses TheCocktailDB public API)
Enables:
  • /mix classic - Real-world cocktails
  • /mix special - VA-11 HALL-A drinks
  • /menu - Browse drink database
  • /tab - View drink order history
Data Files:
  • data/va11_drinks.json - VA-11 HALL-A drink recipes
  • data/images/*.png - Drink images
Required:
  • DISCORD_TOKEN
  • DATABASE_URL
Optional:
  • MAPILLARY_TOKEN - For live street imagery
Enables:
  • /geo host - Start Geoguessr game
  • /geo quit - End game
  • Interactive map navigation
  • Live scoring and leaderboards
Fallback Behavior:
commands/geo.js (Lines 476-485)
async getFailsafeLocation(updateStatus) {
  if (FALLBACK_CACHE && FALLBACK_CACHE.length > 0) {
    console.log("[Geo] Using Cache Hit.");
    return FALLBACK_CACHE[Math.floor(Math.random() * FALLBACK_CACHE.length)];
  }
  return this.getFallback(); // Tokyo, Japan
}
Required:
  • DISCORD_TOKEN
  • DATABASE_URL
  • SUPABASE_URL
  • SUPABASE_SERVICE_KEY
Enables:
  • /palette - Generate color palettes from images
  • Image upload to Supabase storage
  • Public URL generation
Canvas Dependency: Uses @napi-rs/canvas for image processing and palette extraction.
Required:
  • DISCORD_TOKEN
  • DATABASE_URL
  • GROQ_API_KEY
Enables:
  • /8ball - AI-powered fortune telling
  • Groq LLaMA model integration
Model:
model: "llama-3.3-70b-versatile"
Fallback: If Groq fails, uses static responses from data/8ball_responses.json

Database Configuration

The bot automatically creates these tables on startup:
CREATE TABLE IF NOT EXISTS guild_settings (
    guild_id TEXT PRIMARY KEY,
    admin_role_id TEXT,
    log_channel_id TEXT,
    command_rules JSONB DEFAULT '{}'::jsonb
);
See utils/db.js (Lines 8-133) for the complete database initialization code.

Supabase Setup

If using Supabase for image storage:
1

Create Supabase Project

Sign up at supabase.com and create a new project.
2

Create Storage Bucket

Go to Storage in the Supabase dashboard and create a new bucket:
  • Name: jill-stingray (or your preferred name)
  • Public: Yes (required for Discord embeds)
  • File size limit: 50MB
3

Get API Credentials

Go to Settings → API:
  • Copy Project URLSUPABASE_URL
  • Copy service_role keySUPABASE_SERVICE_KEY
Use the service_role key, not the anon key. The service role bypasses Row Level Security.
4

Configure Bucket Policy

If you prefer using the anon key, set up RLS policies:
-- Allow public uploads
CREATE POLICY "Public Upload"
ON storage.objects FOR INSERT
TO public
WITH CHECK (bucket_id = 'jill-stingray');

-- Allow public reads
CREATE POLICY "Public Read"
ON storage.objects FOR SELECT
TO public
USING (bucket_id = 'jill-stingray');

Validation

Verify your configuration:
# Print all environment variables (sanitized)
node -e "require('dotenv').config(); console.log({
  DISCORD_TOKEN: process.env.DISCORD_TOKEN ? '✅ Set' : '❌ Missing',
  DATABASE_URL: process.env.DATABASE_URL ? '✅ Set' : '❌ Missing',
  SUPABASE_URL: process.env.SUPABASE_URL || '⚠️ Optional',
  MAPILLARY_TOKEN: process.env.MAPILLARY_TOKEN || '⚠️ Optional',
  GROQ_API_KEY: process.env.GROQ_API_KEY || '⚠️ Optional',
  BOT_OWNER_ID: process.env.BOT_OWNER_ID || '⚠️ Not set'
})"

Security Best Practices

Never commit .env files to version control!Add to .gitignore:
.gitignore
.env
.env.local
.env.production

Rotate Tokens

Regenerate Discord bot tokens and API keys if exposed

Use Service Role

Always use Supabase service_role key for server-side operations

Restrict Database

Use SSL and IP whitelisting for production databases

Environment Variables

Use platform environment variables in production, not .env files

Next Steps

Server Setup

Configure admin roles and server-specific settings

Commands

Browse the complete command reference

Features

Explore drink mixing and other features

Deployment

Deploy to production with Railway, Heroku, or VPS

Build docs developers (and LLMs) love