This is the backend service for Evvnt MVP.
- Node.js (current repo uses Node 18, but some dev dependencies may warn; Node 20+ recommended)
- PostgreSQL (running locally)
cd backend
cp .env.example .env
npm installInstall and start PostgreSQL locally (for example on macOS: brew install postgresql@16 and brew services start postgresql@16). Create two databases — app and tests:
createdb evvnt
createdb evvnt_e2eCopy .env from .env.example and .env.test from .env.test.example. Point DATABASE_URL in .env at evvnt and in .env.test at evvnt_e2e; adjust user/password to match your Postgres install.
This repo uses Prisma with SQL migrations under prisma/migrations/ (including Event Planner / FinanceEntry.metadata in 20260409100000_add_event_planner_and_finance_metadata).
With Postgres running, apply migrations to both databases:
cd backend
npm run db:setupThat runs db:wait (TCP check using DATABASE_URL from .env), then db:migrate (.env) and db:migrate:test (.env.test). Alternatively: npx prisma migrate deploy with DATABASE_URL set for each database, or apply the SQL files in prisma/migrations/ in order.
cd backend
npm run devHealth check: GET http://localhost:4000/health
| Layer | Location | Needs Postgres |
|---|---|---|
| Unit | test/unit/ |
No |
| Integration | test/integration/ |
Yes (skipped if DB down) |
| E2E (HTTP) | test/e2e/ |
Partial (smoke tests always run) |
cd backend
cp .env.test.example .env.test
# Ensure DATABASE_URL in .env.test targets evvnt_e2e, then:
npm run db:setup # if you have not migrated both DBs yet
npm test # all tests
npm run test:coverage # same + v8 coverage → ./coverage/ (lcov, html, json-summary)
npm run test:watch # watch modeE2E and integration suites reset data with TRUNCATE — use a dedicated test database.
If Postgres is not running, unit tests and HTTP smoke tests still run; DB-backed cases are skipped and a warning is printed.
In CI, fail when the database must be present: REQUIRE_E2E_DB=1 npm test.
Email delivery is stored in the Notification table. If SMTP is configured (see Mailgun notes in .env.example: US smtp.mailgun.org, EU smtp.eu.mailgun.org, full postmaster@… as SMTP_USER, verified EMAIL_FROM domain), email notifications are attempted immediately. Failed sends store SMTP_SEND_FAILED: … on the notification row. Failed notifications can be retried by running the worker:
cd backend
npm run worker:notificationsAuth emails (verification, OTP, password reset) log delivery failures to stderr as [evvnt:auth-mail] delivery_failed … (recipient is partially masked).
SMTP probe (ops): set SMTP_HEALTH_SECRET in env, then:
curl -sS -H "x-smtp-probe-secret: $SMTP_HEALTH_SECRET" "http://localhost:4000/health/smtp"Returns { ok: true, data: { smtp: "verified" } } when the server can complete an SMTP handshake (no email is sent). If the secret env var is unset or the header does not match, the route responds 404 so the probe is not advertised.
- New project on Railway → Deploy from GitHub → select this repo.
- Root directory: set the service Root Directory to
backend(the folder that containspackage.jsonandrailway.json). - PostgreSQL: add a PostgreSQL plugin (or database) and link it to the API service so Railway injects
DATABASE_URL. - Variables (service → Variables), set at least:
JWT_ACCESS_SECRET— long random string (16+ chars)JWT_REFRESH_SECRET— different long random stringAPP_PUBLIC_URL— public URL of the API (e.g.https://your-service.up.railway.app) for auth email links- Optional:
PAYSTACK_SECRET_KEY, SMTP vars,SMTP_HEALTH_SECRET(for/health/smtpprobe — see Notifications worker), etc. (see.env.example)
railway.json runs npx prisma migrate deploy as pre-deploy, then npm start. The app listens on PORT (set automatically by Railway).
Health check: GET /health (configured in railway.json).
- Human-readable list and full request index:
docs/API.md - Swagger UI:
http://localhost:4000/api/docs(withnpm run dev) - OpenAPI JSON:
http://localhost:4000/api/openapi.json - Postman: import
docs/postman/Evvnt.postman_collection.json