Create a .gitignore file in the project root:
# Dependencies
node_modules/
# Environment
.env
.env.local
.env.production
# Logs
logs/
*.log
# OS files
.DS_Store
Thumbs.db
# IDE
.vscode/
.idea/
# Build
dist/
cd LexAI
git init
git add .
git commit -m "feat: initial commit — LexAI backend v1.1.0"- Go to github.com/new
- Set Repository name to
LexAI - Set visibility to Public or Private
- Do NOT init with a README (we already have one)
- Click Create repository
git remote add origin https://github.com/YOUR_USERNAME/LexAI.git
git branch -M main
git push -u origin mainVisit https://github.com/YOUR_USERNAME/LexAI — you should see all files.
You need accounts on:
- Render (free tier available)
- MongoDB Atlas (free M0 cluster)
- Redis Cloud or Upstash Redis (free tier)
- CloudAMQP (free Lemur plan for RabbitMQ)
- Create a free cluster at cloud.mongodb.com
- Create a database user with a strong password
- Add
0.0.0.0/0to the IP whitelist (for Render's dynamic IPs) - Copy the connection string:
mongodb+srv://user:password@cluster.mongodb.net/lexai
- Create a free Redis instance
- Copy the host, port, and password
- Create a free Lemur instance at cloudamqp.com
- Copy the AMQP URL:
amqps://user:password@host/vhost
- Go to dashboard.render.com
- Click New + → Web Service
- Connect your GitHub account and select the
LexAIrepository - Configure the service:
| Setting | Value |
|---|---|
| Name | lexai-api |
| Region | Oregon (US West) or closest to you |
| Branch | main |
| Root Directory | (leave blank) |
| Runtime | Node |
| Build Command | npm install |
| Start Command | node server.js |
| Plan | Free |
- Click Create Web Service
- Click New + → Background Worker
- Connect the same
LexAIrepository - Configure:
| Setting | Value |
|---|---|
| Name | lexai-worker |
| Branch | main |
| Build Command | npm install |
| Start Command | node worker.js |
| Plan | Free |
Go to each service's Environment tab and add these variables:
# App
NODE_ENV=production
PORT=3000
API_VERSION=v1
# MongoDB Atlas
MONGO_URI=mongodb+srv://lexai_user:YourPassword123@cluster0.abc123.mongodb.net/lexai
# Redis
REDIS_HOST=your-redis-host.redis.cloud
REDIS_PORT=12345
REDIS_PASSWORD=YourRedisPassword123
# RabbitMQ
RABBITMQ_URL=amqps://user:password@rattlesnake.rmq.cloudamqp.com/user
ANALYSIS_QUEUE=lexai.analysis.queue
ALERT_QUEUE=lexai.alert.queue
DLX_EXCHANGE=lexai.dlx
# PASETO (generate a strong random string — at least 32 chars)
# Use: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
PASETO_LOCAL_SECRET=a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8
PASETO_ACCESS_EXPIRY=15m
PASETO_REFRESH_EXPIRY=7d
PASETO_REFRESH_COOKIE_MAX_AGE_MS=604800000
# OpenRouter AI
OPENROUTER_API_KEY=sk-or-v1-your-openrouter-api-key-here
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
AI_PRIMARY_MODEL=meta-llama/llama-3.1-8b-instruct:free
AI_FALLBACK_MODEL=mistralai/mistral-7b-instruct:free
# Rate Limiting
RATE_LIMIT_WINDOW_MS=60000
RATE_LIMIT_MAX=100
# File Upload
MAX_FILE_SIZE_MB=5
ALLOWED_MIME_TYPES=application/pdf,application/vnd.openxmlformats-officedocument.wordprocessingml.document,text/plain
# CORS (add your frontend URL)
ALLOWED_ORIGINS=https://your-frontend.vercel.app,http://localhost:5173
# Email (use Ethereal for testing, or your SMTP provider)
SMTP_HOST=smtp.ethereal.email
SMTP_PORT=587
SMTP_USER=your-ethereal-user
SMTP_PASS=your-ethereal-password
EMAIL_FROM=noreply@lexai.io
Important: Both the
lexai-apiandlexai-workerservices need the same environment variables since they share the same codebase and connect to the same databases.
- Render will auto-deploy when you push to
main - Watch the Logs tab for startup messages
- Wait for
🚀 LexAI API server running on port 3000to appear
After the first deployment, open the Render Shell tab for lexai-api and run:
ADMIN_EMAIL=admin@lexai.io ADMIN_PASSWORD=Admin@Secure123 node scripts/seed.jsYour live URL will be:
https://lexai-api.onrender.com
Test it:
curl https://lexai-api.onrender.com/healthExpected response:
{
"status": "ok",
"services": { "mongodb": "up", "redis": "up", "rabbitmq": "up" },
"timestamp": "2026-02-22T18:00:00.000Z",
"uptime": 120
}Cause: Missing required env vars.
Fix: Check all env vars are set in Render dashboard. Especially MONGO_URI, RABBITMQ_URL, PASETO_LOCAL_SECRET, and OPENROUTER_API_KEY.
Cause: MongoDB Atlas IP whitelist blocking Render's IPs.
Fix: Go to Atlas → Network Access → Add 0.0.0.0/0 to allow all IPs (required for free tier).
Cause: Redis connecting to localhost instead of cloud Redis.
Fix: Ensure REDIS_HOST and REDIS_PORT are set to your cloud Redis instance, not localhost defaults.
Cause: Wrong RabbitMQ URL format.
Fix: Use amqps:// (with 's') for CloudAMQP. Format: amqps://user:password@host/vhost
Cause: Start command path issue.
Fix: Set start command to node server.js (not node src/server.js — server.js is in root).
Cause: Render free tier spins down after 15 minutes of inactivity. Fix: This is expected behavior. First request after inactivity takes longer. For always-on, upgrade to paid tier ($7/month).
Cause: Frontend URL not in ALLOWED_ORIGINS.
Fix: Add your deployed frontend URL to ALLOWED_ORIGINS env var.
Cause: lexai-worker background worker not running.
Fix: Check that both lexai-api and lexai-worker are deployed and running. They're separate services.
| Service | Free Limit |
|---|---|
| Render Web Service | 750 hours/month, spins down after 15min inactivity |
| Render Background Worker | 750 hours/month |
| MongoDB Atlas M0 | 512 MB storage, shared cluster |
| Redis Cloud | 30 MB, 1 database |
| CloudAMQP Lemur | 1M messages/month, 20 connections |
| OpenRouter | Free models have rate limits (~10 req/min) |