NHS hospital Proof of Delivery system for tracking consignment receipts and deliveries.
| Receipt order | Label generated | Stores view |
|---|---|---|
![]() |
![]() |
![]() |
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Frontend │ │ Mobile │ │ Backend │
│ (Expo Web) │────▶│ (Expo RN) │────▶│ (FastAPI) │
│ │ │ │ │ │
│ Stores clerk │ │ Delivery │ │ SQLite DB │
│ + Admin UI │ │ drivers │ │ + uploads │
└──────────────┘ └──────────────┘ └──────────────┘
Frontend — Web SPA used by stores clerks to receipt consignments and generate QR labels, and by admins to manage users, locations, and view analytics.
Mobile — React Native app used by delivery drivers to scan QR codes, photograph deliveries, capture signatures, and record GPS coordinates.
Backend — REST API handling authentication, consignment/delivery CRUD, label generation (ZPL + PNG), file uploads, and analytics.
- Python 3.12+
- Node.js 20+
- npm
cd backend
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtOn first run you'll be prompted to create an admin account:
uvicorn backend.main:app --host 0.0.0.0 --port 8000The API is served at http://localhost:8000. Interactive docs at /docs.
cd frontend
cp ../.env.example .env # Edit EXPO_PUBLIC_API_URL if needed
npm install
npx expo start --webOpens at http://localhost:8081. Routes:
/— Stores clerk interface (receipt, labels, history)/admin— Admin dashboard (users, locations, analytics)
cd mobile
cp ../.env.example .env # Set EXPO_PUBLIC_API_URL to your LAN IP
npm install
npx expo startScan the QR code with Expo Go on your device.
cp .env.example .env # Set POD_SECRET_KEY and POD_ADMIN_PASSWORD
docker compose up -dServes the frontend and proxies the API via Caddy with automatic TLS. See docker-compose.yml.
| Variable | Component | Description | Default |
|---|---|---|---|
POD_SECRET_KEY |
Backend | JWT signing key | Auto-generated .secret_key file |
CORS_ORIGINS |
Backend | Allowed CORS origins (comma-separated) | * |
EXPO_PUBLIC_API_URL |
Frontend/Mobile | Backend URL | http://localhost:8000 |
DATABASE_URL |
Backend | SQLAlchemy database URL | sqlite+aiosqlite:///backend/pod.db |
POD_ADMIN_USERNAME |
Backend | Admin account username (first run) | admin |
POD_ADMIN_PASSWORD |
Backend | Admin account password (first run, min 6 chars) | — |
See .env.example for a full template.
backend/ Python FastAPI + SQLAlchemy + SQLite
main.py App entry point, middleware, routes
models.py SQLAlchemy models (User, Delivery, Consignment, DeliveryLocation)
schemas.py Pydantic request/response schemas
auth.py JWT + bcrypt auth
services/ Business logic layer
utils/ Pagination, datetime helpers, rate limiting
frontend/ Expo Router web SPA
app/index.tsx Stores clerk UI
app/admin.tsx Admin dashboard
lib/ API client, auth context, helpers
mobile/ Expo React Native app
App.tsx Auth gate + tab navigation
src/screens/ Login, delivery wizard (4 steps), history, detail
src/components/ Shared UI components
- Stores clerk receipts a consignment via the frontend → generates a QR label
- Consignment is printed/labelled and status set to "at stores"
- Driver scans the QR code with the mobile app → status changes to "out for delivery"
- Driver takes a photo, captures recipient name + signature → submits delivery
- Consignment auto-marked "delivered" with timestamp and delivery evidence






