Skip to main content

Overview

JOIP Web Application requires various environment variables for database connections, API integrations, authentication, and feature configuration. This page provides a comprehensive reference for all supported variables.
On Replit, configure all environment variables in the Secrets tab (Tools → Secrets). Never commit secrets to version control.

Required Variables

These variables are essential for the application to function:

Database Configuration

DATABASE_URL
string
required
PostgreSQL connection string in standard format.Format: postgresql://username:password@host:port/databaseExample:
DATABASE_URL="postgresql://joip_user:[email protected]/joip_production?sslmode=require"
Neon Example:
DATABASE_URL="postgresql://joip_user:[email protected]/neondb?sslmode=require"
Ensure SSL mode is enabled (?sslmode=require) for production databases.

Session Security

SESSION_SECRET
string
required
Secret key for signing session cookies. Must be cryptographically secure.Recommended: 32+ random charactersExample:
SESSION_SECRET="a7f9c2e8b4d1f6e3a9c5b8d2f7e4a1c6b9e2f5a8d3c7b1e4f9a2c5d8e1b4f7a3"
Generate secure secret:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Supabase Storage

SUPABASE_URL
string
required
Your Supabase project URL.Format: https://[project-id].supabase.coExample:
SUPABASE_URL="https://xyzabcdefg123456.supabase.co"
Find this in your Supabase project settings under “API”.
SUPABASE_ANON_KEY
string
required
Supabase anonymous (public) API key for client-side operations.Example:
SUPABASE_ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Find this in Supabase project settings under “API” → “Project API keys”.
SUPABASE_SERVICE_KEY
string
required
Supabase service role key for server-side storage operations.Example:
SUPABASE_SERVICE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Keep this secret! Service key has full access to your Supabase project. Never expose in client code.

Reddit API Integration

REDDIT_CLIENT_ID
string
required
Reddit application client ID for content fetching.Example:
REDDIT_CLIENT_ID="AbCdEf123456"
Obtain from: https://www.reddit.com/prefs/apps
REDDIT_CLIENT_SECRET
string
required
Reddit application client secret.Example:
REDDIT_CLIENT_SECRET="xYz789-AbC123_dEf456"
Create a “script” type application on Reddit for server-side API access.

Replit OIDC Authentication

Required for production deployment on Replit:
REPLIT_DOMAINS
string
Comma-separated list of domains where your Repl is accessible.Example (single domain):
REPLIT_DOMAINS="joip-production.replit.app"
Example (multiple domains):
REPLIT_DOMAINS="app.joip.io,joip-production.replit.app,joip-backup.replit.app"
Behavior:
  • Application prioritizes app.joip.io if present
  • Falls back to first domain in list
  • Used for OAuth callback URL generation
  • Enables Replit OIDC authentication when set
REPL_ID
string
Your Replit project ID (automatically populated by Replit).Example:
REPL_ID="abc123-xyz789-def456"
Required for Replit OIDC authentication in production.
ISSUER_URL
string
Replit OIDC issuer URL (standard value).Value:
ISSUER_URL="https://identity.util.repl.co"
This value is consistent across all Replit deployments.

AI Providers

Caption Generation

At least one AI provider is required for caption generation:
OPENROUTER_API_KEY
string
OpenRouter API key for AI caption generation (primary provider).Example:
OPENROUTER_API_KEY="sk-or-v1-abc123xyz789..."
Models used:
  • Manual Editor: google/gemini-2.5-pro (contextual captions)
  • Fallback: google/gemini-2.5-flash-lite
  • Smart Captions: gemini-2.5-flash-lite
Obtain from: https://openrouter.ai/
OPENAI_API_KEY
string
OpenAI API key (alternative to OpenRouter).Example:
OPENAI_API_KEY="sk-abc123xyz789..."
Falls back to this provider if OpenRouter fails.

AI Undress (Image Editing)

XAI_API_KEY
string
xAI API key (primary provider for AI Undress feature).Example:
XAI_API_KEY="xai-abc123xyz789..."
Model used: grok-imagine-image-pro (via /v1/images/edits)
FREEPIK_API_KEY
string
Freepik API key (fallback provider for AI Undress).Example:
FREEPIK_API_KEY="fpk_abc123xyz789..."
Model used: Seedream 4.5 Edit
UNDRESS_PRIMARY_PROVIDER
enum
default:"xai"
Primary AI Undress provider selection.Options: xai | freepikExample:
UNDRESS_PRIMARY_PROVIDER="xai"
Defaults to xai if not specified.
XAI_UNDRESS_MODEL
string
default:"grok-imagine-image-pro"
Optional xAI model override for AI Undress.Example:
XAI_UNDRESS_MODEL="grok-imagine-image-pro"
REPLICATE_API_TOKEN
string
Replicate API token (dormant/legacy backend for AI Undress).Example:
REPLICATE_API_TOKEN="r8_abc123xyz789..."
This credential is currently not used in active AI Undress flows.

Optional Features

Imgchest Import

IMGCHEST_API_KEY
string
Imgchest API key for importing existing JOIP galleries.Example:
IMGCHEST_API_KEY="imgchest_abc123xyz789"
Required for “Import JOIP from Imgchest” feature.

Payment Providers

PayGate (Credit Cards)

PAYGATE_MERCHANT_WALLET
string
PayGate merchant wallet address for credit card payments.Example:
PAYGATE_MERCHANT_WALLET="0xABC123..."
PAYGATE_CALLBACK_URL
string
PayGate callback URL for payment notifications.Example (local dev with ngrok):
PAYGATE_CALLBACK_URL="https://abc123.ngrok.io/api/payments/callback"
Production: Auto-detected from REPLIT_DOMAINS

Telegram Stars

TELEGRAM_BOT_TOKEN
string
Telegram bot token for Telegram Star payments.Example:
TELEGRAM_BOT_TOKEN="123456:ABC-DEF123456..."
Obtain from: https://t.me/BotFather
TELEGRAM_WEBHOOK_SECRET
string
Secret for verifying Telegram webhook signatures.Example:
TELEGRAM_WEBHOOK_SECRET="your_secure_random_string"
Required in production when TELEGRAM_BOT_TOKEN is set.
TELEGRAM_BOT_USERNAME
string
default:"OfficialJoipBot"
Telegram bot username (without @).Example:
TELEGRAM_BOT_USERNAME="OfficialJoipBot"
TELEGRAM_CHANNEL_ID
string
Telegram channel ID for membership features.Example:
TELEGRAM_CHANNEL_ID="-1001234567890"

Thirdweb (Crypto Checkout)

THIRDWEB_CLIENT_ID
string
Thirdweb client ID for crypto checkout.Example:
THIRDWEB_CLIENT_ID="abc123xyz789"
THIRDWEB_WEBHOOK_SECRET
string
Secret for verifying Thirdweb webhook signatures.Example:
THIRDWEB_WEBHOOK_SECRET="whsec_abc123xyz789"
THIRDWEB_SELLER_WALLET
string
EVM wallet address for receiving Thirdweb payments.Format: Must be valid EVM address (0x…)Example:
THIRDWEB_SELLER_WALLET="0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
Must be a valid 40-character hexadecimal EVM address.

Payblis

PAYBLIS_MERCHANT_KEY
string
Payblis merchant key.Example:
PAYBLIS_MERCHANT_KEY="merchant_abc123"
PAYBLIS_SECRET_KEY
string
Payblis secret key for API authentication.Example:
PAYBLIS_SECRET_KEY="sk_abc123xyz789"
PAYBLIS_SANDBOX
boolean
default:"auto"
Enable Payblis sandbox mode.Values: true | falseExample:
PAYBLIS_SANDBOX="false"
Defaults to true in development, false in production.

Application Settings

NODE_ENV
enum
default:"development"
Node.js environment mode.Options: development | productionExample:
NODE_ENV="production"
Behavior:
  • development: Enables detailed error messages, Vite HMR
  • production: Optimized builds, minimal logging
PORT
number
default:"5000"
Server listening port.Example:
PORT=5000
Always use port 5000 on Replit. Changing this may break deployment.
JOIP_INTERNAL_PORT
number
Optional override for internal localhost callbacks/proxy calls.Example:
JOIP_INTERNAL_PORT=5000
Defaults to PORT when omitted.
UPLOAD_DIR
string
default:"./uploads"
Local directory for file uploads (legacy).Example:
UPLOAD_DIR="./uploads"
All uploads now use Supabase Storage. This setting is mostly unused.
HOST_URL
string
Explicit host URL override.Example:
HOST_URL="https://app.joip.io"
Auto-detected from REPLIT_DOMAINS in production.

Database Connection Tuning

Optional settings for optimizing PostgreSQL connection pooling:
DB_POOL_MAX
number
default:"20"
Maximum number of database connections in pool.Example:
DB_POOL_MAX=20
DB_POOL_MIN
number
default:"2"
Minimum number of database connections in pool.Example:
DB_POOL_MIN=2
DB_POOL_IDLE
number
default:"10000"
Idle timeout in milliseconds before closing connection.Example:
DB_POOL_IDLE=10000
DB_CONNECT_TIMEOUT
number
default:"10"
Connection timeout in seconds.Example:
DB_CONNECT_TIMEOUT=10
DB_MAX_LIFETIME
number
default:"3600"
Maximum connection lifetime in seconds.Example:
DB_MAX_LIFETIME=3600
DB_STATEMENT_TIMEOUT
number
default:"30000"
Statement timeout in milliseconds.Example:
DB_STATEMENT_TIMEOUT=30000
DB_QUERY_TIMEOUT
number
default:"20000"
Query timeout in milliseconds.Example:
DB_QUERY_TIMEOUT=20000

Logging Configuration

LOG_LEVEL
enum
default:"info"
Application logging level.Options: error | warn | info | debugExample:
LOG_LEVEL="info"
Levels:
  • error: Only critical errors
  • warn: Errors and warnings
  • info: Normal operation info (recommended for production)
  • debug: Detailed debugging information

Environment Validation

The application validates all environment variables on startup (server/environmentConfig.ts:89):
export function validateEnvironmentSetup() {
  const errors: string[] = [];
  const warnings: string[] = [];

  // Required variables
  if (!process.env.DATABASE_URL) {
    errors.push('DATABASE_URL is required');
  }

  if (!process.env.SUPABASE_URL) {
    errors.push('SUPABASE_URL is required');
  }

  // ... additional validation
}
Startup Behavior:
  • Errors: Application may fail to start or have limited functionality
  • Warnings: Application starts but some features are disabled
Check console logs on startup for validation results.

Configuration Examples

# Required
DATABASE_URL="postgresql://user:[email protected]/db?sslmode=require"
SESSION_SECRET="a7f9c2e8b4d1f6e3a9c5b8d2f7e4a1c6"
SUPABASE_URL="https://xyz123.supabase.co"
SUPABASE_ANON_KEY="eyJhbGciOi..."
SUPABASE_SERVICE_KEY="eyJhbGciOi..."
REDDIT_CLIENT_ID="AbCdEf123"
REDDIT_CLIENT_SECRET="xYz789-AbC123"

# Replit OIDC
REPLIT_DOMAINS="app.joip.io,joip.replit.app"
REPL_ID="abc123-xyz789"
ISSUER_URL="https://identity.util.repl.co"

# AI Providers
OPENROUTER_API_KEY="sk-or-v1-..."
XAI_API_KEY="xai-..."
FREEPIK_API_KEY="fpk-..."

# Application
NODE_ENV="production"
PORT=5000

Security Best Practices

Critical Security Rules:
  • Never commit .env files to Git
  • Use Replit Secrets for all sensitive values
  • Rotate secrets periodically (every 90 days)
  • Use different secrets for dev/staging/prod
  • Audit access to Replit Secrets regularly

Secret Generation

Generate cryptographically secure secrets:
# Session secret (32 bytes)
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# Webhook secret (16 bytes)
node -e "console.log(require('crypto').randomBytes(16).toString('hex'))"

# UUID v4
node -e "console.log(require('crypto').randomUUID())"

Environment Files

Never track environment files in Git:
# .gitignore
.env
.env.local
.env.production
.env.development
*.env

Troubleshooting

Missing Required Variables

Symptom: Application fails to start with validation errors Solution:
  1. Check startup logs for specific missing variables
  2. Add all required variables to Replit Secrets
  3. Restart the application

Invalid Variable Format

Symptom: “Invalid format” warnings on startup Solution:
  1. Verify variable format matches documentation
  2. Check for extra spaces or quotes
  3. Validate URLs include protocol (https://)

Features Not Working

Symptom: Specific features disabled or failing Solution:
  1. Check for related warnings in startup logs
  2. Verify optional variables are set correctly
  3. Test connectivity to external services

Next Steps

Deploy on Replit

Complete Replit deployment guide

Database Setup

Configure PostgreSQL and Neon

Storage Configuration

Setup Supabase Storage

Build docs developers (and LLMs) love