LoadMind is a web platform for freight load matching and shipment management. It supports two user roles:
- Shippers can post shipments, enter pickup and delivery addresses, request price suggestions, track shipment status, and review shipment history.
- Carriers can browse AI-ranked loads, review pickup and delivery routes on a map, assign loads to fleet vehicles, and manage fleet information.
The product is designed around the common logistics workflow where a shipper creates a load, a carrier accepts and assigns it, and both sides confirm pickup and delivery.
- Role-based authentication for Carrier and Shipper users.
- The same email account can be used for both roles. The active portal depends on the role selected during login.
- Carrier AI Load Matcher page with load cards, route information, objective sorting/filter controls, and assignment actions.
- Carrier assignment only shows vehicles that are theoretically capable of taking the load, based on vehicle status, schedule conflict, capacity, and trailer dimensions.
- Carrier Route Optimizer page for selecting a truck, adding marketplace/custom stops, and calculating an optimized stop order.
- Carrier Fleet Management page for registering vehicles and trailers, including required-field markers and numeric validation for fuel consumption and trailer capacity/dimensions.
- Shipper shipment posting flow with route, cargo, schedule, AI price suggestion, editable accepted price, and optional load notes.
- Shipper dashboard support for posted loads, cancelled load restore, active shipments, and confirmation actions.
- Shipper history page showing fulfilled shipments with route, category, date filters, list/grid view, and summary statistics.
- OpenStreetMap-based address selection:
- map pin selector for address fields,
- manual address entry with autocomplete candidates,
- full street addresses are written back into form fields instead of raw coordinates.
- Small route maps on load cards showing pickup and delivery points.
- Backend API for load creation, load cancellation/restoration, load assignment, pickup confirmation, delivery confirmation, and price insight suggestions.
These screenshots show selected LoadMind workflows for both carrier and shipper users. They are not exhaustive; run the frontend and backend locally to explore the full product experience.
| Sign in | Carrier AI Load Matcher |
|---|---|
![]() |
![]() |
| Carrier Fleet Management | Carrier Route Optimizer |
|---|---|
![]() |
![]() |
| Shipper Dashboard | Shipper Post Shipment |
|---|---|
![]() |
![]() |
| Shipper Price Insights | Shipper Shipment History |
|---|---|
![]() |
![]() |
| Register Vehicle Modal |
|---|
![]() |
- React 18
- TypeScript
- Vite
- Tailwind CSS
- shadcn/Radix UI components
- React Query
- Supabase Auth
- Leaflet and OpenStreetMap
- Python 3.11+
- FastAPI
- Pydantic Settings
- Supabase integration
- Celery and Redis scaffold
- XGBoost, pandas, and NumPy for pricing/matching support
LoadMind/
├── Backend/ # FastAPI backend service
├── Frontend/ # React/Vite frontend application
├── ScreenShots/ # README product screenshots rendered by GitLab
├── .gitlab-ci.yml # Current GitLab CI configuration
├── .gitignore
└── README.md
Install these tools before running the project locally:
- Python 3.11 or newer
- Node.js and npm. Node 20 LTS is recommended for consistent frontend dependency installs.
- Git
- Docker Desktop, optional but recommended if you want to run Redis with Docker Compose
- A Supabase project with the required database tables and authentication enabled
Create local .env files for the frontend and backend. Do not commit real secrets to Git.
Create Frontend/.env:
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=your-supabase-anon-key
VITE_BACKEND_URL=http://localhost:8000Create Backend/.env:
APP_NAME=LoadMind API
ENV=development
DEBUG=true
FRONTEND_URL=http://localhost:8080
HOST=0.0.0.0
PORT=8000
REDIS_URL=redis://localhost:6379/0
CELERY_BROKER_URL=redis://localhost:6379/0
CELERY_RESULT_BACKEND=redis://localhost:6379/1
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-supabase-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-supabase-service-role-key
ORS_API_KEY=your-openrouteservice-keySUPABASE_SERVICE_ROLE_KEY should only be used by trusted backend code. In GitLab, store it in Settings > CI/CD > Variables as a masked/protected variable if it is needed by a pipeline.
Run the backend and frontend in separate terminal windows.
cd Backend
python3.11 -m venv .venv
source .venv/bin/activate
pip install -e .
uvicorn app.main:app --host 0.0.0.0 --port 8000Check the backend:
curl http://localhost:8000/healthExpected response:
{
"status": "ok",
"env": "development",
"instance_id": "...",
"started_at": "..."
}Redis and the Celery worker power the optional background-worker stack. You only need these when you want to run asynchronous jobs (e.g. offloading heavy model or routing work to a worker).
Start Redis and the worker separately:
cd Backend
docker compose up -d redis
docker compose up -d workerOr start the full stack (API + Redis + worker) together:
cd Backend
docker compose up --buildcd Frontend
npm install --legacy-peer-deps
npm run dev -- --host 0.0.0.0 --port 8080Open the application in the browser:
http://localhost:8080
If port 8080 is already in use, start Vite on another port:
npm run dev -- --host 0.0.0.0 --port 5173- Open
http://localhost:8080/auth. - Choose either Carrier or Shipper.
- Sign in or create an account with Supabase Auth.
- The selected role controls which portal opens after login.
The same email can be used as both a carrier and a shipper. Choose the role you want to use when logging in.
- Go to
/carrier. - Review recommended loads in AI Load Matcher.
- Use the current location address field manually or select a location with the map pin button.
- Review the small route map on each load card. Pickup and delivery points are shown on OpenStreetMap.
- Click Assign Load and choose a fleet vehicle.
- Use the pickup and delivery confirmation actions when the shipment progresses.
- Go to
/shipper. - Open
/shipper/post. - Enter route information, cargo details, pickup/dropoff times, optional load notes, and cargo dimensions if known.
- Pickup and delivery addresses can be typed manually with autocomplete or selected using the map pin button.
- Request an AI price suggestion, adjust the suggested price if needed, and accept the price.
- Submit the shipment so carriers can see it in the load marketplace.
- Track active, posted, cancelled, and fulfilled shipments from the dashboard and history pages.
The frontend calls the backend using VITE_BACKEND_URL, defaulting to http://localhost:8000.
Useful routes include:
GET /healthGET /api/v1/loads/openPOST /api/v1/loadsPOST /api/v1/loads/{load_id}/assignPOST /api/v1/loads/{load_id}/cancelPOST /api/v1/loads/{load_id}/restorePOST /api/v1/loads/{load_id}/confirm-pickupPOST /api/v1/loads/{load_id}/confirm-deliveryPOST /api/v1/price-insights/suggest
Most API routes require a Supabase access token from the logged-in user.
Assessment support documents are stored in:
docs/AI_MODEL.md- AI/ML model choice, integration, alternatives, and limitations.docs/DEMO_DATA.md- repeatable Supabase demo seed data instructions.docs/VALIDATION.md- validation plan, technical checks, and model validation approach.docs/RISK_SECURITY.md- privacy, security, AI/model risk, third-party service risk, and MVP limitations.
The login page also includes a short user-facing Privacy Policy dialog. That dialog is a simplified user explanation, while the files in docs/ provide fuller internal assessment support for the MVP.
Frontend:
cd Frontend
npm run test
npm run lint
npm run buildBackend:
cd Backend
python3.11 -m pip install -e .
python3.11 -m py_compile app/main.py app/api/schemas/loads.py app/api/schemas/price_insights.pyThe backend also includes a pricing validation script at scripts/validate_pricing_model.py. It shows per-scenario rows by default. Use --hide-rows only when you want a shorter metrics-only output.
The current .gitlab-ci.yml intentionally runs a backend-only check.
Reason:
- The available GitLab runner is currently a shell executor.
- The shell runner has Python 3.12 available, so it can install and compile the backend.
- The same runner does not have
npminstalled, so frontend jobs fail withnpm: command not found. - GitLab
image: node:...only works with Docker/Kubernetes-style executors. It does not install Node.js on a shell runner. - The old Docker runner is not currently available, so the frontend CI job is disabled for now.
Current backend pipeline behavior:
- uses the
fit2107runner tag, - installs the backend package with
python3.12 -m pip install -e ., - compiles the backend entrypoint and core schemas with
python3.12 -m py_compile, - caches pip downloads under
Backend/.cache/pip/.
When a Docker runner or a shell runner with Node/npm is available, frontend CI can be added back with jobs such as:
frontend_check:
stage: test
image: node:22
script:
- cd Frontend
- npm ci --legacy-peer-deps
- npm run buildDo not add both fit2099 and fit2107 tags to one job unless the runner has both tags. In GitLab CI, job tags are matched with AND logic, not OR logic.
Use:
npm install --legacy-peer-depsCheck that:
- the backend is running on
http://localhost:8000, Frontend/.envcontainsVITE_BACKEND_URL=http://localhost:8000,Backend/.envcontainsORS_API_KEY=your-openrouteservice-api-key,- the backend
FRONTEND_URLmatches the Vite dev server URL.
Check:
- project runners or instance runners are enabled for the project,
- the job tag matches an online runner,
- the runner is allowed to run untagged jobs if the job has no tag.
That means the job is running on a shell runner without Node/npm. Use a Docker runner with a Node image, or ask the runner administrator to install Node.js on the shell runner.
- Do not commit
.env, cache folders, build outputs, or dependency folders. - Keep generated files such as
node_modules/,dist/,.cache/,.vite/, and Python__pycache__/out of Git. - Keep address fields user-readable. Store or display full street addresses where the UI asks for an address, not raw latitude/longitude values.
- Note:
Frontend/package-lock.jsonis currently ignored in.gitignoreto avoid excessive diff noise from mechanical npm rewrites.








