Codebase

REST API api

The core backend and system of business logic — a Node.js/Express service over MongoDB that every other component depends on.

Repository
macaroni-kid-2.api (v1.5.8)
Runtime
Node.js 18.20.7, npm 10.8.2
Framework
Express, with express-restify-mongoose & express-async-errors
Data layer
Mongoose over MongoDB; mongoose-deep-populate
Auth
Passport (JWT + local), jsonwebtoken, bcryptjs, speakeasy (2FA/TOTP)
Process manager
PM2 — cluster mode, 4 instances (ecosystem.config.js)
Port
3000 (mapped to 8080 in the Docker setup)
API prefix
/api/v1/

Structure

32
Controllers
40
Models
39
Route files
24
Services

The app boots from app.jsbin/www. Middleware is registered around the router (middleware/), routes are wired in routes/, and request handling lives in controllers/ backed by Mongoose models/. Cross-cutting concerns (email, search, third-party APIs) live in services/.

Notable services

ServicePurpose
services/search.jsOpenSearch indexing & queries (Article / Business / Event)
services/sendGrid.js, services/email.jsTransactional email (SendGrid, SES via nodemailer)
services/ongage.jsOngage ESP integration
services/monday.jsMonday.com integration
services/connectionMonitor.jsMonitors data-store connections (used by the worker)

Notable endpoints

RoutePurpose
/api/v1/statistic/trackViewRecords a public pageview into TownViewCount
/api/v1/statistic/townViewCountAggregated pageview reporting (admin dashboards)
/api/v1/statistic/townRank, …/newsletterTotalByTownTown ranking & newsletter totals
/debug-sentrySentry test endpoint

Observability

Sentry is initialized in instrument.js (loaded before the app) with @sentry/node and profiling. Process-level unhandledRejection and uncaughtException handlers log diagnostic detail. Winston and Morgan provide application and request logging.

Deployment

Production runs under PM2 in cluster mode (4 instances) via ecosystem.config.js, which also defines a deploy target: user root on host 198.74.62.36 (Linode), pulling origin/master into /var/www/api, then npm install && pm2 startOrRestart. A Dockerfile (Node 18) is provided for containerized runs; cron/queue work runs in a separate worker process.

API vs. worker
The web-facing API process no longer runs cron jobs — those moved to the dedicated worker (npm run start:worker / Dockerfile.worker). The two share one codebase but run as separate processes.