Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions apps/backend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# ============================================================
# StellarBounty Backend Configuration
# ============================================================

# App
NODE_ENV=development
PORT=4000

# Database (required)
DATABASE_URL=postgresql://user:password@localhost:5432/stellarbounty

# JWT (required - generate with: openssl rand -base64 32)
JWT_SECRET=your-super-secret-key-at-least-32-chars-long

# Stellar Network
STELLAR_NETWORK=testnet
STELLAR_HORIZON_URL=https://horizon-testnet.stellar.org
SOROBAN_RPC_URL=https://rpc-futurenet.stellar.org

# Smart Contract (optional for development)
BOUNTY_CONTRACT_ID=

# Frontend URL (for CORS)
FRONTEND_URL=http://localhost:3000
60 changes: 60 additions & 0 deletions apps/backend/src/config/env.validation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import * as Joi from 'joi';

export const envValidationSchema = Joi.object({
// App
NODE_ENV: Joi.string()
.valid('development', 'production', 'test')
.default('development'),
PORT: Joi.number().default(4000),

// Database
DATABASE_URL: Joi.string()
.uri()
.required()
.messages({
'string.uri': 'DATABASE_URL must be a valid URI (e.g., postgresql://user:pass@localhost:5432/db)',
'any.required': 'DATABASE_URL is required. Set it in your .env file.',
}),

// JWT
JWT_SECRET: Joi.string()
.min(32)
.required()
.messages({
'string.min': 'JWT_SECRET must be at least 32 characters long',
'any.required': 'JWT_SECRET is required. Generate one with: openssl rand -base64 32',
}),

// Stellar
STELLAR_NETWORK: Joi.string()
.valid('public', 'testnet', 'futurenet')
.default('testnet')
.messages({
'any.only': 'STELLAR_NETWORK must be one of: public, testnet, futurenet',
}),

STELLAR_HORIZON_URL: Joi.string()
.uri()
.optional()
.default('https://horizon-testnet.stellar.org'),

SOROBAN_RPC_URL: Joi.string()
.uri()
.optional()
.default('https://rpc-futurenet.stellar.org'),

// Contract
BOUNTY_CONTRACT_ID: Joi.string()
.optional()
.allow('')
.pattern(/^C[A-Z2-7]{55}$/)
.messages({
'string.pattern.base': 'BOUNTY_CONTRACT_ID must be a valid Stellar contract ID (starts with C, 56 chars)',
}),

// Frontend URL (for CORS)
FRONTEND_URL: Joi.string()
.uri()
.optional()
.default('http://localhost:3000'),
});