You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
NestJS 11 REST API and WebSocket server for Spraada β a peer-to-peer tool rental marketplace. Handles authentication, tool listings, bookings, real-time messaging, notifications, media uploads, and email.
Passport-JWT (access + refresh tokens), Google OAuth 2.0
Password hashing
Argon2
Real-time
Socket.IO (@nestjs/websockets)
Media storage
AWS S3
Email
Nodemailer
Validation
class-validator + class-transformer
Containerisation
Docker Compose
Prerequisites
Node.js β₯ 18 (LTS recommended)
Docker Desktop β runs PostgreSQL and Redis locally
npm β₯ 9
Local Development Setup
1. Install dependencies
npm install
2. Configure environment
Create .env in the project root. Every variable listed below is required unless marked optional.
# ββ Database βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ# Local Docker instance (used during development)DATABASE_URL="postgresql://spraada_dev:spraada_dev_password@localhost:5435/spraada_dev_db?schema=public"# Production: use the pooler URL for runtime, and the direct URL for migrations# DATABASE_URL="postgresql://<user>:<password>@<pooler-host>:6543/postgres?pgbouncer=true"# DIRECT_URL="postgresql://<user>:<password>@<direct-host>:5432/postgres"# ββ Application ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββPORT=4444# HTTP server port (default: 4444)FRONTEND_URL=http://localhost:3000# Used for CORS and outbound email links# ββ JWT ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββJWT_SECRET=<random-256-bit-hex>JWT_EXPIRES_IN=600s# Access token TTLJWT_REFRESH_TOKEN=<random-256-bit-hex>JWT_REFRESH_EXPIRES_IN=7d# Refresh token TTL# ββ Google OAuth 2.0 βββββββββββββββββββββββββββββββββββββββββββββββββββββββββGOOGLE_CLIENT_ID=<your-google-client-id>GOOGLE_CLIENT_SECRET=<your-google-client-secret>GOOGLE_CALLBACK_URL=http://localhost:4444/auth/google/callback# ββ AWS S3 (media storage) βββββββββββββββββββββββββββββββββββββββββββββββββββAWS_ACCESS_KEY_ID=<your-access-key>AWS_SECRET_ACCESS_KEY=<your-secret-key>AWS_S3_BUCKET_REGION=eu-north-1AWS_S3_BUCKET_NAME=<your-bucket-name># ββ Email (SMTP) ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββEMAIL_HOST=<smtp-host>EMAIL_PORT=465EMAIL_SECURE=trueEMAIL_USER=<smtp-username>EMAIL_PASSWORD=<smtp-password>EMAIL_FROM="Spraada <no-reply@yourdomain.com>"# ββ Redis ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββREDIS_URL=redis://localhost:6379# Omit to fall back to in-memory cache
Secret generation β use openssl rand -hex 32 to generate each secret value.
3. Start infrastructure
# Bring up PostgreSQL (port 5435) and Redis (port 6379)
npm run db:dev:up
Set DATABASE_URL to the PgBouncer pooler connection string and DIRECT_URL to the direct connection string. Prisma uses directUrl for migration commands and url for all runtime queries.
NPM Scripts
Script
Description
npm run start:dev
Start with hot-reload (watch mode)
npm run start:debug
Start with Node.js debugger attached
npm run build
Compile TypeScript to dist/
npm run start:prod
Run compiled production build
npm run db:dev:up
Start PostgreSQL + Redis containers
npm run db:dev:rm
Stop and remove the DB container with its volume
npm run db:dev:restart
Full cycle: remove β start β deploy migrations
npm run prisma:dev:deploy
Run prisma migrate deploy (apply pending migrations)
npm run lint
ESLint with auto-fix
npm run format
Prettier over src/ and test/
npm run test
Jest unit tests
npm run test:e2e
Jest end-to-end tests
npm run test:cov
Jest with coverage report
API Reference
All protected endpoints require an Authorization: Bearer <access_token> header.
# Start both services
npm run db:dev:up
# View database logs
docker compose logs dev-db
# Open Prisma Studio (visual DB browser)
npx prisma studio
# Hard-reset database (development only β destroys all data)
npm run db:dev:rm && npm run db:dev:up && npx prisma migrate dev
Verify port 5435 is not bound by another process: lsof -i :5435.
Confirm DATABASE_URL in .env matches the Docker Compose credentials.
Run npm run db:dev:restart to perform a clean restart with migrations applied.
Prisma migration errors
# Re-generate the client after schema changes
npx prisma generate
# Inspect current migration state
npx prisma migrate status
# Reset all migrations (development only β destroys data)
npx prisma migrate reset
Redis connection errors
The cache module falls back to in-memory if REDIS_URL is not set. Ensure dev-redis is running (npm run db:dev:up) and REDIS_URL=redis://localhost:6379 is present in .env.
JWT errors
Confirm JWT_SECRET and JWT_REFRESH_TOKEN are set and non-empty.
Access tokens expire after JWT_EXPIRES_IN (default 600s). The frontend must call POST /auth/refresh-tokens to obtain a new pair before expiry.
The Authorization header must be Bearer <token> with a single space.
About
Spraada β π Connect with like-minded people, π¬ spark conversations, and π€ share tools for a pay.