- Go to Render and click New Web Service.
- Connect your fork of this repo and select
backend/as the root directory. - Build command:
npm install && npm run build - Start command:
npm start - Health check path:
/api/health- A healthy response:
{ "service": "stellar-bounty-board-backend", "status": "ok", ... }
- A healthy response:
- Ensure the port is set to
3001(or useprocess.env.PORTas Render provides). - Set production CORS variables (see CORS configuration below).
Railway is a popular alternative to Render that offers one-click GitHub repo deployment. It auto-detects Node.js projects and provides generous free tier limits.
- A Railway account (sign up with GitHub)
- Your fork of this repository
Click the button above or follow the manual steps below.
-
Create a New Project
- Go to Railway Dashboard
- Click New Project → Deploy from GitHub repo
- Select your fork of
stellar-bounty-board
-
Configure the Backend Service
- Railway will auto-detect the Node.js project in the root
- Set the Root Directory to
backend/ - Build command (auto-detected):
npm install && npm run build - Start command (auto-detected):
npm start - Railway assigns a
${{PORT}}environment variable automatically (overrides the default3001)
Variable Required Example Value Description GITHUB_WEBHOOK_SECRET✅ Yes your_webhook_secretSecret for GitHub webhook verification NODE_ENV✅ Yes (prod) productionEnvironment mode ALLOWED_ORIGINS✅ Yes (prod) https://bounty-board.vercel.appProduction frontend origin allowlist CORS_ORIGINS❌ No *orhttp://localhost:3000Development CORS origins (ignored in production) BOUNTY_STORE_PATH❌ No ./data/bounties.jsonBounty data file (default) BOUNTY_AUDIT_STORE_PATH❌ No ./data/audit.jsonAudit log file (default) LOG_LEVEL❌ No infoLogging level
The backend restricts browser cross-origin access in production using an explicit allowlist.
Set these on your backend host (Render, Railway, Docker, etc.):
NODE_ENV=production
ALLOWED_ORIGINS=https://bounty-board.vercel.appALLOWED_ORIGINSis a comma-separated list of frontend URLs allowed to call the API.- Requests from unrecognized browser origins receive HTTP 403 on CORS preflight (
OPTIONS). - If
ALLOWED_ORIGINSis unset in production, the server logs a warning and rejects browser origins.
Development defaults to permissive CORS (*) so any local frontend origin works without configuration.
Override with an explicit list when needed:
NODE_ENV=development
CORS_ORIGINS=http://localhost:3000CORS_ORIGINS and ALLOWED_ORIGINS are both honored in development; CORS_ORIGINS takes precedence.
- Backend:
/api/health(should return{ "status": "ok", ... }) - Frontend:
/(should load the React dashboard)
-
Build fails: Check Node.js version (18+), install all dependencies, and verify build commands.
-
API not reachable: Confirm backend is live and CORS is configured (
ALLOWED_ORIGINSin production). -
Frontend shows blank: Ensure correct output directory (
dist) and that the API URL is set.
- Docker and Docker Compose installed locally or on server
Run the entire stack locally using Docker Compose:
docker-compose up --buildThis starts:
- Backend:
http://localhost:3001/api - Frontend:
http://localhost:5173
Set environment variables in a .env.local file (in the project root):
SOROBAN_CONTRACT_ID=your-contract-id
SOROBAN_RPC_URL=https://rpc-futurenet.stellar.orgDocker Compose will pass these to the containers automatically.
- Backend source (
./backend/src) is mounted, so changes hot-reload during development - Frontend source (
./frontend/src) is mounted similarly - Data persists in
./backend/data/
Both services include health checks. The frontend waits for the backend to be healthy before starting:
docker-compose up --build
# Check service health
docker-compose psdocker build -t stellar-bounty-board-backend:latest .docker run -d \
-p 3001:3001 \
-e SOROBAN_CONTRACT_ID=your-contract-id \
-e SOROBAN_RPC_URL=https://rpc-futurenet.stellar.org \
-v /path/to/data:/app/data \
stellar-bounty-board-backend:latestdocker build -t stellar-bounty-board-frontend:latest ./frontenddocker run -d \
-p 80:5173 \
-e VITE_API_BASE_URL=https://your-backend.example.com/api \
stellar-bounty-board-frontend:latestBackend (Dockerfile):
NODE_ENV(default:production)PORT(default:3001)SOROBAN_CONTRACT_ID(required if indexing events)SOROBAN_RPC_URL(default:https://rpc-futurenet.stellar.org)
Frontend (frontend/Dockerfile):
VITE_API_BASE_URL(required): URL of your backend API
- Backend:
GET http://localhost:3001/api/health - Frontend:
GET http://localhost:5173(should load the React app)
Container fails to start:
- Check logs:
docker-compose logs backendordocker logs <container-id> - Ensure the root
package.jsonand all dependencies are present
API calls fail from frontend:
- Verify
VITE_API_BASE_URLis set correctly - Ensure backend container is healthy:
docker-compose ps - Check CORS settings: set
ALLOWED_ORIGINSto your deployed frontend URL whenNODE_ENV=production
Data not persisting:
- Verify the volume mount path:
docker volume lsanddocker volume inspect <volume-name> - Ensure the host directory has write permissions
Port conflicts:
- If ports 3001 or 5173 are in use, modify
docker-compose.yml:ports: - '3001:3001' # Change left side (host) port
- Check the ONBOARDING.md for local setup.
- See RUNBOOK.md for common operational tasks and emergency procedures.
- Open an issue or discussion in the repo for deployment help.