Skip to content

Repository files navigation

ParcelStats

AI-powered community-driven parcel tracking. Predict delivery dates with confidence intervals using machine learning and collective shipment data.

More people track = more data = better predictions for everyone.

Features

  • 25+ International Carriers — USPS, UPS, FedEx, DHL, Royal Mail, Canada Post, and more
  • AI ETA Predictions — XGBoost-powered delivery predictions with confidence intervals
  • Route Analysis — Historical route patterns and carrier performance stats
  • Cyber-themed UI — Dark mode, neon accents, maps, and real-time updates
  • Google OAuth — Secure authentication, no passwords
  • Community Intelligence — Every tracked shipment improves the model
  • Self-hosted — Full Docker stack, deploy anywhere

Architecture

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   Traefik    │────▶│   Next.js    │────▶│ Python ML    │
│  (Proxy/SSL) │     │  (Frontend + │     │  (Predictions│
│              │     │   Node API)  │     │   + Scraping)│
└──────────────┘     └──────┬───────┘     └──────┬───────┘
                            │                     │
                     ┌──────▼─────────────────────▼──────┐
                     │     PostgreSQL + TimescaleDB       │
                     │     (Shipments, Predictions,       │
                     │      Routes, Events)               │
                     └────────────────────────────────────┘
                                         │
                                  ┌──────▼───────┐
                                  │    Redis      │
                                  │ (Cache/Queue) │
                                  └──────────────┘

Quick Start

Prerequisites

  • Docker + Docker Compose
  • Google OAuth credentials (setup guide)

1. Clone and Configure

git clone https://github.com/YOUR_USERNAME/ParcelStats.git
cd ParcelStats
cp .env.example .env

2. Edit .env

DOMAIN=localhost
DB_PASSWORD=your_secure_password
NEXTAUTH_SECRET=openssl rand -base64 32
NEXTAUTH_URL=https://your-domain.com
# Shared secret between frontend and ML service (openssl rand -hex 32)
INTERNAL_API_KEY=your_internal_api_key
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret

# Optional carrier API credentials. Required for reliable USPS, UPS, and FedEx tracking.
USPS_WEB_TOOLS_USER_ID=your_usps_web_tools_user_id
UPS_CLIENT_ID=your_ups_client_id
UPS_CLIENT_SECRET=your_ups_client_secret
FEDEX_CLIENT_ID=your_fedex_client_id
FEDEX_CLIENT_SECRET=your_fedex_client_secret

3. Launch

docker compose up -d

Visit https://localhost (or your domain).

4. Seed Carriers (first run)

docker exec -i parcelstats-postgres psql -U parcelstats -d parcelstats < database/seed/carriers.sql

Google OAuth Setup

  1. Go to Google Cloud Console
  2. Create a new project
  3. Enable "Google+ API"
  4. Go to CredentialsCreate CredentialsOAuth Client ID
  5. Application type: Web application
  6. Add authorized redirect URI: https://your-domain.com/api/auth/callback/google
  7. Copy the Client ID and Client Secret to your .env

Deployment (Unraid)

ParcelStats is designed to run as a Docker stack on Unraid:

  1. Install the Compose Manager plugin on Unraid
  2. Upload the project to your preferred location (e.g., /mnt/user/appdata/parcelstats/)
  3. Copy and edit .env as described above
  4. In the Unraid UI, go to the Compose tab and deploy

Prebuilt images (no building on the server)

Every push to main publishes images to GHCR (ghcr.io/kurue/parcelstats-frontend, ghcr.io/kurue/parcelstats-ml-service). Use docker-compose.prod.yml to pull them instead of building locally:

docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d

The repo checkout is still needed for the compose file and the database/*.sql init scripts, but no Node/Python build happens on the server. If the GHCR packages are private, run docker login ghcr.io with a GitHub token (read:packages) first.

All data persists in Docker volumes. Back up the postgres-data volume regularly.

Production checklist (e.g. ps.kurue.com)

  1. Point your domain's DNS at the server and terminate TLS at your reverse proxy (Traefik, NPM, or SWAG on Unraid), forwarding to the frontend on port 3000.
  2. Set in .env:
    • NEXTAUTH_URL=https://ps.kurue.com
    • NEXTAUTH_SECRET (generate: openssl rand -base64 32)
    • INTERNAL_API_KEY (generate: openssl rand -hex 32)
    • GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET with redirect URI https://ps.kurue.com/api/auth/callback/google
    • ADMIN_EMAILS=you@gmail.com — grants access to the /admin dashboard
    • A strong DB_PASSWORD
  3. The compose file binds Postgres, Redis, and the ML service to 127.0.0.1 only; the frontend (port 3000) is the only service your proxy needs to reach.

Admin Dashboard

Users listed in ADMIN_EMAILS see an Admin link in the navbar (/admin) with system stats, scraper health, model versions and accuracy, prediction volume by model version, and retrain controls.

Carrier Support

Carrier Method Countries
USPS Web Tools API US
UPS OAuth Track API US
FedEx OAuth Track API US
DHL Express API + Scrape Global
Royal Mail Playwright UK
Canada Post Playwright CA
Australia Post Playwright AU
Deutsche Post Playwright DE
DHL Parcel DE Playwright DE
GLS Playwright EU
Hermes Playwright DE
China Post Playwright CN
Yanwen Playwright CN
Japan Post Playwright JP
India Post Playwright IN
Correos Playwright ES
Poste Italiane Playwright IT
La Poste Playwright FR
PostNord Playwright SE/DK/NO/FI
Swiss Post Playwright CH
An Post Playwright IE
NZ Post Playwright NZ
Singapore Post Playwright SG
Pos Malaysia Playwright MY
Thai Post Playwright TH

Adding a new carrier: Open a Carrier Request issue or submit a PR with a new scraper in ml-service/services/scraper/.

Carrier API notes: USPS, UPS, and FedEx block or redirect unauthenticated server-side tracking requests in many environments. Set USPS_WEB_TOOLS_USER_ID, UPS_CLIENT_ID + UPS_CLIENT_SECRET, and FEDEX_CLIENT_ID + FEDEX_CLIENT_SECRET before starting the stack. Without those values, matching shipments are marked carrier_setup_required instead of retrying into tracking_exception.

UPS defaults to the production API host https://onlinetools.ups.com. Set UPS_BASE_URL=https://wwwcie.ups.com for the UPS customer integration environment. FedEx defaults to https://apis.fedex.com; set FEDEX_BASE_URL=https://apis-sandbox.fedex.com for sandbox credentials.

ML Prediction Model

How it Works

  1. Data Collection — Every tracked shipment's events, origin, destination, carrier, and timing are stored
  2. Feature Engineering — Carrier, regions, service type, weight, seasonal patterns, day of week
  3. Training — Three XGBoost models predict:
    • Median ETA — Most likely delivery date
    • P10 bound — 10th percentile (optimistic)
    • P90 bound — 90th percentile (conservative)
  4. Confidence Score — Calculated from the spread between P10 and P90
  5. Retraining — Automatic weekly retraining as data grows

ParcelStats does not create fallback, synthetic, or baseline ETAs. If there is not enough real completed shipment history for a carrier or lane, the app shows no prediction until enough user-submitted shipments have been delivered and used for training.

Improving Predictions

  • Track more real packages → more training data
  • Different carriers and routes → better generalization
  • Delivered shipments with real carrier events are the only training source
  • Over time, confidence intervals narrow as the model learns patterns

Project Structure

ParcelStats/
├── docker-compose.yml          # Full Docker stack
├── frontend/                   # Next.js app
│   ├── src/
│   │   ├── app/                # Pages + API routes
│   │   ├── components/         # React components
│   │   └── lib/                # Auth, DB, utilities
│   ├── drizzle.config.ts       # ORM config
│   └── Dockerfile
├── ml-service/                 # Python FastAPI
│   ├── routers/                # API endpoints
│   ├── services/
│   │   ├── predictor.py        # ML inference
│   │   ├── trainer.py          # Model training
│   │   └── scraper/            # Carrier scrapers
│   ├── database/               # SQLAlchemy models
│   └── Dockerfile
├── database/
│   ├── init.sql                # Schema
│   └── seed/                   # Carrier data
└── traefik/                    # Reverse proxy config

Tech Stack

Component Technology
Frontend Next.js 14, React, TailwindCSS
Backend API Next.js API Routes, Drizzle ORM
ML Service Python, FastAPI, XGBoost, scikit-learn
Database PostgreSQL + TimescaleDB
Scraping Playwright, httpx, BeautifulSoup
Auth NextAuth.js v5 (Google OAuth)
Maps Leaflet + OpenStreetMap
Cache Redis
Proxy Traefik
Deployment Docker Compose

Development

Frontend

cd frontend
npm install
npm run dev

ML Service

cd ml-service
python -m venv venv
source venv/bin/activate  # or venv\Scripts\activate on Windows
pip install -r requirements.txt
playwright install chromium
uvicorn main:app --reload --port 8000

Database Migrations

cd frontend
npm run db:generate    # Generate migration from schema changes
npm run db:migrate     # Apply migrations

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

See CONTRIBUTING.md for details.

License

MIT License — see LICENSE for details.

Roadmap

  • WebSocket real-time tracking updates
  • Email/push notifications
  • Mobile app (React Native)
  • Public API for third-party integrations
  • Route map visualization with animated paths
  • Carrier reliability scores
  • Neural network models for complex routes
  • Multi-language support
  • Dark/light theme toggle
  • Package photo OCR for auto-tracking-number detection

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages