RideKit
Docs/Getting started/Installation

Installation

How to set up the backend for local development. (Production deployment is covered in Deployment.)

Prerequisites

Tool Version Notes
Node.js 20.5+ (LTS 20 recommended) Pinned via backend/.nvmrc. The app refuses older versions (engines field).
PostgreSQL 14+ with PostGIS Spatial queries (dispatch, geofencing) need PostGIS.
Redis 7+ Cache, OTP, BullMQ queues, Socket.IO adapter.
Docker optional For one-command infra via docker-compose.yml.

From the repo root:

docker compose up -d        # starts Postgres+PostGIS and Redis

Option B — local Postgres + Redis

Ensure both are running, then create the database:

createdb taxi_platform

PostGIS and the other extensions are enabled automatically by the first migration — you do not need to CREATE EXTENSION manually.

Backend setup

cd backend
nvm use                     # picks Node 20 from .nvmrc
npm install
cp .env.example .env        # then edit .env (see below)
npm run migration:run       # creates schema + seeds RBAC roles
npm run start:dev           # http://localhost:3000/api ; Swagger at /docs

Environment configuration

Every option lives in .env.example, fully commented. The ones you must set:

Variable Purpose Notes
DB_* Postgres connection Match your local/Docker creds.
REDIS_* Redis connection
JWT_ACCESS_SECRET / JWT_REFRESH_SECRET Token signing Min 32 chars. Generate with node -e "console.log(require('crypto').randomBytes(48).toString('base64url'))". The app refuses to boot in production with a placeholder value.
STORAGE_DRIVER local (dev) or s3 (prod)
DEFAULT_CURRENCY / DEFAULT_LOCALE / DEFAULT_TIMEZONE / DEFAULT_COUNTRY Per-install localization (country-agnostic, spec 1A)

Provider credentials (all optional — graceful fallback)

Third-party integrations are off by default and degrade gracefully when unconfigured (never crash, never block a ride). Configure them in the admin Providers page (encrypted at rest) or via these env fallbacks:

Area Env fallbacks Unconfigured behaviour
SMS TWILIO_* / MSG91_* (+ smsProvider setting) OTP logged to console
Email Resend/SMTP creds (+ emailProvider setting) logged, not sent
Storage (prod) S3_* / R2 endpoint local disk
Payouts RAZORPAYX_* manual rail
Call masking TWILIO_ACCOUNT_SID / TWILIO_AUTH_TOKEN / TWILIO_PROXY_SERVICE_SID (+ callMaskingProvider setting) direct dial
E-invoicing (per country) GSP_* (India), ZATCA_*, CFDI_PAC_*, NFSE_* deterministic local invoice — see E-INVOICING.md

White-label / branding (mobile apps)

Each app's app.config.ts reads these (defaults preserved):

Variable Purpose
APP_NAME / APP_SCHEME / IOS_BUNDLE_ID / ANDROID_PACKAGE / EAS_PROJECT_ID identity
APP_ICON / APP_ADAPTIVE_ICON / APP_SPLASH / APP_ICON_BG icons & splash — see BRANDING-ASSETS.md
EXPO_PUBLIC_API_URL / EXPO_PUBLIC_SOCKET_URL / GOOGLE_MAPS_API_KEY connectivity (prod build fails fast on localhost/LAN URLs)

Google Maps API key restriction (Android package + SHA-1, iOS bundle) must be set up in Google Cloud Console per the key you supply.

First-run verification

curl http://localhost:3000/api/health
# {"status":"ok","info":{"database":{"status":"up"},"redis":{"status":"up"}}}

If status is error, the failing dependency (DB or Redis) is shown in the error object — check that service before anything else.

Migrations

npm run migration:run        # apply pending
npm run migration:revert     # roll back the last one
npm run migration:generate   # scaffold from entity changes

Seeding — creating your first admin

The migrations seed reference data (markets, roles, permissions, vehicle types) but deliberately create no users. A fresh install therefore has nobody who can sign in to the admin panel, so this step is required:

cd backend
npm run migration:run   # must come first
npm run seed            # creates the first super_admin

The seed prints the exact login details when it finishes, for example:

Log in to the admin panel
  Phone     +919955000001
  Role      super_admin
  Market    IN · INR · Asia/Kolkata

Sign in at the admin panel with that phone number and OTP 000000. 000000 is a development master code that works only while no real SMS provider is configured; it stops working the moment you connect Twilio/MSG91 in Admin → Settings → Providers, after which the real SMS code is required.

The default phone is derived from your active market's dial code. Override it (and anything else) with environment variables:

Variable Purpose
ADMIN_PHONE Admin login phone, E.164. Default: derived from the active market (India → +919955000001)
ADMIN_EMAIL Optional admin email
ADMIN_NAME Display name. Default Platform Admin
ADMIN_PASSWORD Optional — also enables POST /api/auth/login for this account

npm run seed is idempotent and safe on a production database: it adds no fake data, and re-running it never duplicates or errors. If the phone already belongs to an account, that account is granted super_admin (the seed warns when it promotes an existing user).

Demo data (optional)

npm run seed -- --demo

Adds a believable month of operations on top: 5 drivers with vehicles and approved KYC, 5 riders, 24 rides across every status, ratings, promo redemptions, payouts, and the double-entry ledger history those rides imply — so the dashboard, reports, payouts and driver-earnings screens show real numbers instead of zeros. Everything respects the active market: currency, map center, dial codes, driver/vehicle names and the commission cap all come from your configured country, not from hardcoded defaults.

Demo rides created in the requested state are picked up by the normal dispatch loop while the backend is running, so they transition to no_drivers after the offer timeout unless a driver app accepts them.

Cleanup

npm run seed -- --clean-demo   # remove everything --demo created
npm run seed -- --clean-junk   # remove leftovers from manual testing
npm run seed -- --help         # full flag reference

Neither runs as part of a normal seed — nothing is ever deleted implicitly.

--clean-demo removes exactly the rows --demo creates (their ids are derived from a fixed namespace, so real data can't match) and rebuilds the affected ledger account balances from the surviving postings. Your admin account is kept.

--clean-junk deletes placeholder and duplicated vehicle types left over from manual testing, and clears a support_email whose domain matches neither your brand nor a normal mailbox provider (a value carried over from another install). It refuses to delete anything still referenced by real data and prints every action it takes.


Admin panel

The Next.js 14 operator console. It is a separate app from the backend and runs on its own port.

cd admin
npm install
npm run dev                  # http://localhost:3200

For production:

npm run build && npm start   # also :3200

Pointing it at the backend

The admin talks to the backend over HTTP; set the base URL if the backend isn't on the default:

Variable Default Notes
NEXT_PUBLIC_API_BASE http://localhost:3000/api Must include the /api suffix. Baked in at build time — changing it requires a rebuild, not just a restart.

The backend must allow the admin's origin. Add it to CORS_ORIGINS in the backend environment (comma-separated), e.g. CORS_ORIGINS=http://localhost:3200,https://admin.yourdomain.com.

Logging in

There is no password: the admin uses the same phone + OTP flow as the apps. Use the phone printed by npm run seed (see Seeding above) and OTP 000000 while the SMS provider is still the dev log provider. Once a real provider (Twilio/MSG91) is configured, 000000 stops working and a real SMS is sent — that switch is automatic, there is no flag to remember.

If the login screen rejects your account, it means the user exists but carries no admin role or permissions. Re-run npm run seed.

Mobile apps (rider + driver)

Both are Expo SDK 54 apps and need a dev client — they use native modules (maps, background location, push, Razorpay) that Expo Go cannot load.

cd mobile/rider          # or mobile/driver
npm install
cp env.example .env.development

Then edit .env.development and set EXPO_PUBLIC_API_URL / EXPO_PUBLIC_SOCKET_URL to your machine's LAN IP — not localhost, which on a phone means the phone itself:

ipconfig getifaddr en0       # macOS: your LAN IP

Run it:

npx expo start --dev-client  # rider defaults to :8081, driver to :8082

Ports: run the rider on 8081 and the driver on 8082 (--port 8082) so both can run at once.

Building the dev client

The first run needs a native build (once per machine, per app):

npx expo prebuild            # generates ios/ and android/
npx expo run:ios             # or: npx expo run:android

GOOGLE_MAPS_API_KEY must be set before prebuild — the key is written into android/app/src/main/AndroidManifest.xml at generation time, so setting it afterwards leaves Android maps blank. See each app's ENV.md.

A production build refuses to start if the API/socket URLs are missing, point at localhost or a LAN address, or if the Maps key is empty. That guard is deliberate — it is what stops a store binary shipping pointed at a dev machine.

Ports at a glance

Service Port Start command
Backend API 3000 cd backend && npm run start:dev
Admin panel 3200 cd admin && npm run dev
Rider app (Metro) 8081 cd mobile/rider && npx expo start --dev-client
Driver app (Metro) 8082 cd mobile/driver && npx expo start --dev-client --port 8082
PostgreSQL 5432 Docker or local
Redis 6379 Docker or local
source: docs/installation/README.md (ships identically in the product zip)