Skip to content

Configuration ​

Complete guide to configuring CodeNotify Server.

Environment Variables ​

All configuration is done through environment variables in the .env file.

Server Configuration ​

bash
# Server port (default: 3000)
PORT=3000

# Environment mode
NODE_ENV=development  # development | production | test

Database Configuration ​

bash
# 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=majority

Options:

  • Local MongoDB: mongodb://localhost:27017/codenotify
  • Docker MongoDB: mongodb://mongo:27017/codenotify
  • MongoDB Atlas: Use connection string from Atlas dashboard

JWT Configuration ​

bash
# 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 days

Security 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 ​

bash
# 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=90

Cron Expression Examples:

  • 0 */6 * * * - Every 6 hours
  • 0 */12 * * * - Every 12 hours
  • 0 0 * * * - Daily at midnight
  • 0 */1 * * * - Every hour

Notification Configuration ​

bash
# 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=+1234567890

Platform Adapter Configuration ​

bash
# 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=3

Configuration File ​

config/configuration.ts ​

NestJS configuration module loads environment variables:

typescript
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 ​

bash
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 hour

Production Configuration ​

bash
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.com

Scheduled Jobs ​

Contest Synchronization ​

Schedule: Every 6 hours (configurable) Function: Syncs contests from all enabled platforms Configuration:

bash
CONTEST_SYNC_ENABLED=true
CONTEST_SYNC_INTERVAL=0 */6 * * *

Disable:

bash
CONTEST_SYNC_ENABLED=false

Contest Cleanup ​

Schedule: Daily at 2 AM UTC Function: Deletes contests older than specified days Configuration:

bash
CONTEST_CLEANUP_ENABLED=true
CONTEST_CLEANUP_DAYS=90

Disable:

bash
CONTEST_CLEANUP_ENABLED=false

Notification Check ​

Schedule: Every 30 minutes Function: Checks for upcoming contests and sends notifications Configuration:

bash
NOTIFICATIONS_ENABLED=true
NOTIFICATION_WINDOW_HOURS=24

Disable:

bash
NOTIFICATIONS_ENABLED=false

Database Configuration ​

MongoDB Options ​

typescript
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 ​

  1. Sign up at Resend
  2. Get API key from dashboard
  3. Verify domain (for production)
  4. Add to .env:
bash
RESEND_API_KEY=re_your_api_key
EMAIL_FROM=noreply@yourdomain.com

Email Templates ​

Emails are sent for:

  • Contest notifications (upcoming contests)
  • Account verification (optional)
  • Password reset (optional)

Security Configuration ​

CORS ​

Configure allowed origins in main.ts:

typescript
app.enableCors({
  origin: process.env.CORS_ORIGIN || 'http://localhost:3000',
  credentials: true,
});

Rate Limiting ​

Configure rate limits per endpoint:

typescript
@Throttle(100, 60)  // 100 requests per 60 seconds

Helmet ​

Security headers are enabled by default:

typescript
app.use(helmet());

Logging ​

Log Levels ​

bash
# Log level: error | warn | log | debug | verbose
LOG_LEVEL=log

Custom Logger ​

typescript
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 ​

bash
# MongoDB connection pool size
MONGODB_POOL_SIZE=10

Cache Configuration ​

bash
# Enable caching
CACHE_ENABLED=true

# Cache TTL (seconds)
CACHE_TTL=300  # 5 minutes

Monitoring ​

Health Checks ​

bash
# Enable health check endpoint
HEALTH_CHECK_ENABLED=true

Access at: GET /contests/health

Metrics ​

bash
# Enable metrics collection
METRICS_ENABLED=true

Environment-Specific Files ​

.env.development ​

bash
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 ​

bash
NODE_ENV=production
PORT=3000
MONGODB_URI=mongodb+srv://...
JWT_SECRET=<strong-production-secret>
JWT_REFRESH_SECRET=<strong-production-refresh-secret>

.env.test ​

bash
NODE_ENV=test
PORT=3001
MONGODB_URI=mongodb://localhost:27017/codenotify-test
JWT_SECRET=test-secret
JWT_REFRESH_SECRET=test-refresh-secret

Validation ​

Environment variables are validated on startup:

typescript
// 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 ​

  1. Use strong secrets (min 32 characters)
  2. Different secrets for access and refresh tokens
  3. Never commit .env to version control
  4. Use environment-specific files
  5. Validate required variables on startup
  6. Rotate secrets periodically
  7. Use MongoDB Atlas for production
  8. Enable all security features in production

❌ Don't ​

  1. Don't use default secrets in production
  2. Don't share secrets across environments
  3. Don't commit .env files
  4. Don't use weak passwords
  5. Don't disable security features
  6. Don't use same secret for JWT and refresh

Troubleshooting ​

Missing Environment Variables ​

bash
# Error: JWT_SECRET is not defined

# Solution: Check .env file exists
ls -la .env

# Verify variable is set
cat .env | grep JWT_SECRET

MongoDB Connection Failed ​

bash
# Error: MongooseServerSelectionError

# Solutions:
# 1. Check MongoDB is running
sudo systemctl status mongod

# 2. Verify MONGODB_URI
echo $MONGODB_URI

# 3. Test connection
mongosh $MONGODB_URI

Invalid Cron Expression ​

bash
# Error: Invalid cron expression

# Solution: Validate cron expression
# Use: https://crontab.guru/

Next Steps ​

Built with ❤️ for competitive programmers worldwide.