Ship Quote is a multi-tier shipping rate comparison platform built on the MERN stack (MongoDB, Express 5, React, Node.js). The backend exposes a versioned REST API atDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/plantasur-dev/ship-quote/llms.txt
Use this file to discover all available pages before exploring further.
/api/v1 that aggregates quotes from both static database records and live external carrier APIs, then returns a unified, normalized response. The React frontend consumes this API via Axios and displays a comparison UI. An optional observability stack (Loki, Promtail, Grafana) sits alongside the application services.
Repository Layout
The monorepo is divided into four top-level directories, each with a clearly scoped responsibility.Separation of Concerns
The backend follows a layered architecture where each layer has one responsibility and only communicates with the layer directly below it.Controllers
Receive HTTP requests, delegate to services, and send the HTTP response. They do not contain business logic — they only translate between the HTTP layer and the service layer.
Services
Contain all business logic.
rates.service.js is the main orchestrator: it resolves scope, filters agencies, and fans out to providers in parallel.Providers
Implement the two rate-fetching strategies — static (reads from MongoDB via the in-memory cache) and api (calls external carrier HTTP endpoints). Both produce the same intermediate result shape.
Models
Mongoose schemas that define the MongoDB collections:
Agency, Location, PalletType, Zone, ZoneRules, and Rate. See Data Models for full schemas.schemaValidation— rejectsPOST/PATCH/PUTrequests that arrive with no body.rateDestinationValidation+rateItemsValidation— validates postal codes, country codes, and every item’s dimensions before the request reaches a controller.
The Two-Provider Model
Every active agency in the database is tagged with atype field: static, api, or hybrid. The rate engine uses this tag to route each agency to the correct provider.
Promise.all. The results are merged into a single flat array before being returned to the controller.
| Provider | Data Source | Latency Profile |
|---|---|---|
| Static | In-memory Map built from MongoDB at startup | Sub-millisecond lookups (O(1)) |
| API | Live HTTP requests to external carrier endpoints | Network-bound; per-carrier timeouts apply |
In-Memory Caching Layer
To avoid repeated database queries on every rate comparison,cache.service.js loads all zones, zone rules, rates, and pallet types from MongoDB once at server startup and indexes them into a hierarchy of Map objects, one per agency.
ratesByKey map uses a composite key "type|zoneName|palletTypeId" so a specific rate document can be retrieved in O(1) without scanning any arrays. sortedPalletTypes is pre-sorted by maxWeight then maxHeight so the pallet-matching algorithm only needs a single linear pass.
If
getAgencyTariffs() is called before loadAgencyTariffs() has completed, it throws "Data store not initialized". The bootstrap sequence ensures loading completes before the HTTP server starts accepting connections.Bootstrap and Seed Process
On first run the database is empty. Thenpm run seed command executes bootstrap.js, which sequentially seeds agencies, zones, pallet types, and rates for each bundled carrier.
loadAgencyTariffs() picks up the new documents.
React Frontend
Theweb/ directory contains a React 18 + Vite application. It connects to the API through a single Axios instance whose baseURL is injected at build time via the VITE_API_URL environment variable.
/dist and the API’s Express server serves those static files. During local development both processes run independently: npm run dev in api/ (port 3000) and npm run dev in web/ (port 5173).
Observability Stack
Theinfra/monitoring/ directory contains Docker Compose service definitions for the optional logging and metrics pipeline.
Loki
Log aggregation backend. The Express API’s Winston logger ships structured JSON logs to Loki via Promtail.
Promtail
Log collection agent. Reads Docker container logs and forwards them to Loki.
Grafana
Visualisation layer on top of Loki. Accessible at
http://localhost:3001 when the full Docker Compose stack is running.Morgan
HTTP request logger middleware wired into Express that emits per-request log lines in a format compatible with the Loki pipeline.