Configuration
Complete guide to configuring CodeNotify Server.
Environment Variables
All configuration is done through environment variables in the .env file.
Server Configuration
# Server port (default: 3000)
PORT=3000
# Environment mode
NODE_ENV=development # development | production | testDatabase Configuration
# MongoDB connection string
MONGODB_URI=mongodb://localhost:27017/codenotify
# For MongoDB Atlas:
# MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/codenotify?retryWrites=true&w=majorityOptions:
- Local MongoDB:
mongodb://localhost:27017/codenotify - Docker MongoDB:
mongodb://mongo:27017/codenotify - MongoDB Atlas: Use connection string from Atlas dashboard
JWT Configuration
# Access token secret (change in production!)
JWT_SECRET=your-super-secret-jwt-key-min-32-characters-long
# Access token expiration
JWT_EXPIRES_IN=15m # 15 minutes
# Refresh token secret (different from JWT_SECRET!)
JWT_REFRESH_SECRET=your-super-secret-refresh-key-min-32-characters-long
# Refresh token expiration
JWT_REFRESH_EXPIRES_IN=7d # 7 daysSecurity Best Practices:
- Use strong, random secrets (min 32 characters)
- Different secrets for access and refresh tokens
- Never commit secrets to version control
- Rotate secrets periodically in production
Contest Sync Configuration
# Enable/disable automatic contest synchronization
CONTEST_SYNC_ENABLED=true
# Sync interval (cron expression)
# Default: Every 6 hours
CONTEST_SYNC_INTERVAL=0 */6 * * *
# Enable/disable automatic cleanup of old contests
CONTEST_CLEANUP_ENABLED=true
# Days to keep finished contests
CONTEST_CLEANUP_DAYS=90Cron Expression Examples:
0 */6 * * *- Every 6 hours0 */12 * * *- Every 12 hours0 0 * * *- Daily at midnight0 */1 * * *- Every hour
Notification Configuration
# Enable/disable notifications
NOTIFICATIONS_ENABLED=true
# Notification window in hours
# Contests starting within this window will trigger notifications
NOTIFICATION_WINDOW_HOURS=24
# Email configuration (using Resend)
RESEND_API_KEY=re_your_resend_api_key
EMAIL_FROM=noreply@codenotify.dev
# WhatsApp configuration (optional)
WHATSAPP_API_KEY=your_whatsapp_api_key
WHATSAPP_PHONE_NUMBER=+1234567890Platform Adapter Configuration
# Enable/disable specific platforms
CODEFORCES_ENABLED=true
LEETCODE_ENABLED=true
CODECHEF_ENABLED=true
ATCODER_ENABLED=true
# API timeouts (milliseconds)
PLATFORM_TIMEOUT=15000
# Retry attempts for failed requests
PLATFORM_RETRY_ATTEMPTS=3Configuration File
config/configuration.ts
NestJS configuration module loads environment variables:
export default () => ({
port: parseInt(process.env.PORT, 10) || 3000,
database: {
uri: process.env.MONGODB_URI || 'mongodb://localhost:27017/codenotify',
},
jwt: {
secret: process.env.JWT_SECRET,
expiresIn: process.env.JWT_EXPIRES_IN || '15m',
refreshSecret: process.env.JWT_REFRESH_SECRET,
refreshExpiresIn: process.env.JWT_REFRESH_EXPIRES_IN || '7d',
},
scheduler: {
contestSyncEnabled: process.env.CONTEST_SYNC_ENABLED === 'true',
contestSyncInterval: process.env.CONTEST_SYNC_INTERVAL || '0 */6 * * *',
contestCleanupEnabled: process.env.CONTEST_CLEANUP_ENABLED === 'true',
contestCleanupDays: parseInt(process.env.CONTEST_CLEANUP_DAYS, 10) || 90,
},
notifications: {
enabled: process.env.NOTIFICATIONS_ENABLED === 'true',
windowHours: parseInt(process.env.NOTIFICATION_WINDOW_HOURS, 10) || 24,
},
});Development vs Production
Development Configuration
NODE_ENV=development
PORT=3000
MONGODB_URI=mongodb://localhost:27017/codenotify-dev
# Use shorter expiration for testing
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
# Enable all features
CONTEST_SYNC_ENABLED=true
NOTIFICATIONS_ENABLED=true
# More frequent sync for testing
CONTEST_SYNC_INTERVAL=0 */1 * * * # Every hourProduction Configuration
NODE_ENV=production
PORT=3000
MONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net/codenotify
# Production secrets (use strong random strings)
JWT_SECRET=<generated-secret-min-32-chars>
JWT_REFRESH_SECRET=<different-generated-secret-min-32-chars>
# Standard expiration
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
# Enable production features
CONTEST_SYNC_ENABLED=true
NOTIFICATIONS_ENABLED=true
# Standard sync interval
CONTEST_SYNC_INTERVAL=0 */6 * * *
# Cleanup old contests
CONTEST_CLEANUP_ENABLED=true
CONTEST_CLEANUP_DAYS=90
# Production email
RESEND_API_KEY=<your-production-key>
EMAIL_FROM=noreply@yourdomain.comScheduled Jobs
Contest Synchronization
Schedule: Every 6 hours (configurable) Function: Syncs contests from all enabled platforms Configuration:
CONTEST_SYNC_ENABLED=true
CONTEST_SYNC_INTERVAL=0 */6 * * *Disable:
CONTEST_SYNC_ENABLED=falseContest Cleanup
Schedule: Daily at 2 AM UTC Function: Deletes contests older than specified days Configuration:
CONTEST_CLEANUP_ENABLED=true
CONTEST_CLEANUP_DAYS=90Disable:
CONTEST_CLEANUP_ENABLED=falseNotification Check
Schedule: Every 30 minutes Function: Checks for upcoming contests and sends notifications Configuration:
NOTIFICATIONS_ENABLED=true
NOTIFICATION_WINDOW_HOURS=24Disable:
NOTIFICATIONS_ENABLED=falseDatabase Configuration
MongoDB Options
MongooseModule.forRootAsync({
useFactory: () => ({
uri: process.env.MONGODB_URI,
retryWrites: true,
w: 'majority',
// Connection pool
maxPoolSize: 10,
minPoolSize: 5,
// Timeouts
serverSelectionTimeoutMS: 5000,
socketTimeoutMS: 45000,
}),
});Indexes
Indexes are automatically created on application start:
- Contest: platform, startTime, phase, platformId+platform (unique)
- User: email (unique), role, isActive
Email Configuration
Resend Setup
- Sign up at Resend
- Get API key from dashboard
- Verify domain (for production)
- Add to
.env:
RESEND_API_KEY=re_your_api_key
EMAIL_FROM=noreply@yourdomain.comEmail Templates
Emails are sent for:
- Contest notifications (upcoming contests)
- Account verification (optional)
- Password reset (optional)
Security Configuration
CORS
Configure allowed origins in main.ts:
app.enableCors({
origin: process.env.CORS_ORIGIN || 'http://localhost:3000',
credentials: true,
});Rate Limiting
Configure rate limits per endpoint:
@Throttle(100, 60) // 100 requests per 60 secondsHelmet
Security headers are enabled by default:
app.use(helmet());Logging
Log Levels
# Log level: error | warn | log | debug | verbose
LOG_LEVEL=logCustom Logger
const logger = new Logger('ModuleName');
logger.log('Info message');
logger.error('Error message', trace);
logger.warn('Warning message');
logger.debug('Debug message');Performance Tuning
Connection Pool
# MongoDB connection pool size
MONGODB_POOL_SIZE=10Cache Configuration
# Enable caching
CACHE_ENABLED=true
# Cache TTL (seconds)
CACHE_TTL=300 # 5 minutesMonitoring
Health Checks
# Enable health check endpoint
HEALTH_CHECK_ENABLED=trueAccess at: GET /contests/health
Metrics
# Enable metrics collection
METRICS_ENABLED=trueEnvironment-Specific Files
.env.development
NODE_ENV=development
PORT=3000
MONGODB_URI=mongodb://localhost:27017/codenotify-dev
JWT_SECRET=dev-secret-key
JWT_REFRESH_SECRET=dev-refresh-secret.env.production
NODE_ENV=production
PORT=3000
MONGODB_URI=mongodb+srv://...
JWT_SECRET=<strong-production-secret>
JWT_REFRESH_SECRET=<strong-production-refresh-secret>.env.test
NODE_ENV=test
PORT=3001
MONGODB_URI=mongodb://localhost:27017/codenotify-test
JWT_SECRET=test-secret
JWT_REFRESH_SECRET=test-refresh-secretValidation
Environment variables are validated on startup:
// Required variables
const requiredEnvVars = [
'MONGODB_URI',
'JWT_SECRET',
'JWT_REFRESH_SECRET',
];
requiredEnvVars.forEach((envVar) => {
if (!process.env[envVar]) {
throw new Error(`Missing required environment variable: ${envVar}`);
}
});Best Practices
✅ Do
- Use strong secrets (min 32 characters)
- Different secrets for access and refresh tokens
- Never commit
.envto version control - Use environment-specific files
- Validate required variables on startup
- Rotate secrets periodically
- Use MongoDB Atlas for production
- Enable all security features in production
❌ Don't
- Don't use default secrets in production
- Don't share secrets across environments
- Don't commit
.envfiles - Don't use weak passwords
- Don't disable security features
- Don't use same secret for JWT and refresh
Troubleshooting
Missing Environment Variables
# Error: JWT_SECRET is not defined
# Solution: Check .env file exists
ls -la .env
# Verify variable is set
cat .env | grep JWT_SECRETMongoDB Connection Failed
# Error: MongooseServerSelectionError
# Solutions:
# 1. Check MongoDB is running
sudo systemctl status mongod
# 2. Verify MONGODB_URI
echo $MONGODB_URI
# 3. Test connection
mongosh $MONGODB_URIInvalid Cron Expression
# Error: Invalid cron expression
# Solution: Validate cron expression
# Use: https://crontab.guru/Next Steps
- Quick Start - Make your first API request
- Architecture - Understand the system
- Authentication - Deep dive into auth

