613
613parts an APC associate store
DISPATCH DASHBOARD · v0.6.0
Real-time dispatch · Browser PWA

where are the trucks
right now?

Browser-based dashboard for Preet and Himmat. Opens on any device — desktop at the office, phone at the counter, tablet anywhere. Live map shows both trucks. Stops mark themselves green or red as deliveries complete or fail. Refresh every 15 seconds. Same backend as the bot and driver app — three apps, one Worker.

Form factor
Browser PWA
Updates
15s polling
Auth
Admin PINs
Maps
Leaflet + OSM
Hardware
$0 (BYOD)
Hosting
$0/mo
The dashboard

one screen. everything that matters.

Top: tabs (Live · Exceptions · Report) and the auto-refresh status. Stats bar: today's totals at a glance. Main split: live map (left) + scrollable route lists per branch (right). Click any stop on either side to see customer, order, and call/navigate buttons in a slide-in drawer.

613
Live Exceptions · 1 Report
updated 4s ago · Preet · LOG OUT
17
Today's stops
11
Delivered
1
Exceptions
Pending
Revenue delivered
BV
1
2
3
4
5
6
7
8
9
KGN
1
2
3
4
5
6
7
8
© OpenStreetMap
belleville truck
himmat · last ping 3 min ago
5/9 done
$2,140 delivered
1
Marcus T.
23 Main St, Belleville
$264
✓ delivered
2
Sarah K.
456 Bridge St, Belleville
$1,489
✓ delivered
6
Lisa P.
88 Front St, Belleville
$389
pending
7
Kevin H.
12 Hwy 401 W, Trenton
$89
pending
kingston truck
driver_b · last ping 1 min ago
6/8 done
$2,147 delivered
5
Tom B.
88 King St E, Kingston
$329
! no one home
6
Anna J.
14 Princess St, Kingston
$249
✓ delivered
The full ecosystem

three apps. one backend. each role gets a dedicated tool.

All three apps share the same Cloudflare Worker (~3,500 lines). Different audiences, different surfaces, same source of truth.

CUSTOMERS

messenger bot

Customer DMs the FB page. Bot quotes a tire+rim package or a single part in 60 seconds. Stripe pay link. Dispatched to a driver's truck for delivery.

m.me/613parts
DRIVERS

driver tablet

10" tablet mounted in each truck. PIN login. Today's route loads at 8am, works offline in dead zones, syncs deliveries when signal returns. Photo + signature optional.

drive.613parts.ca
PREET + HIMMAT

dispatch dashboard

Browser PWA. Live map of both trucks, stop status, exception inbox, end-of-day report with CSV export. 15-second auto-refresh. Same admin PINs as the driver app.

dispatch.613parts.ca
Real-time data flow

driver tablet → server → dispatch screen.

Drivers' tablets ping their GPS every 60 seconds while online. Each delivery completion writes a server event. The dashboard polls one aggregating endpoint every 15 seconds and gets all of it back as a single JSON payload.

EVERY 60s
DRIVER TABLET
getCurrentPosition()
{lat, lng, accuracy} via Geolocation API
POST
/api/v1/driver/location
JWT-auth · driver app sends ping
SERVER → R2
driver-locations/{date}/{driver}.json
Overwritten each ping · most-recent wins
ON DELIVERY
DRIVER TABLET
Mark Delivered
Photo + signature + notes (optional)
POST
/api/v1/driver/delivery/.../complete
IndexedDB queue if offline · syncs when online
SERVER → R2
delivery-events/{date}/{order}.json
Photo to delivery-photos/ if present
EVERY 15s
DISPATCH PWA
setInterval(15000)
Polls while tab is visible
GET
/api/v1/dispatch/status
JWT-auth (admin role) · single endpoint
SERVER ← R2
Joins routes + events + locations
Returns full status for both branches
RENDER
React re-renders map + lists
Markers move · lists update · stats refresh
Backend extensions

two new endpoints. one role flag.

Worker stays at one project. Drivers gain a role field ('driver' | 'admin'). Two new endpoints added to the existing router. Admin-only access to the dispatch view; admin PINs same flow as drivers.

POST/api/v1/driver/location

Driver tablet sends GPS ping every 60s. Server writes to R2 at driver-locations/{date}/{driver_id}.json, overwriting each time. Most recent ping per branch is what dispatch sees.

Auth: Bearer JWT Body: {lat, lng, accuracy?, timestamp}
GET/api/v1/dispatch/status

Aggregates today's full state for both branches: routes joined to delivery events, latest driver locations, computed totals (revenue, completed/pending/exceptions), exception inbox cross-cut. One endpoint serves the entire dashboard.

Auth: Bearer JWT (admin role only) Returns: DispatchStatus (see types.ts)
worker/src/handlers/dispatch.ts
excerpt · branch aggregation
async function buildBranchStatus(env, date, branch): Promise<BranchStatus> {
  // Load route, delivery events (parallel), and latest location
  const routeKey = `deliveries/${date}/${branch}.json`;
  const routeObj = await env.CATALOG_BUCKET.get(routeKey);
  const route = routeObj ? await routeObj.json() : { stops: [] };

  const events = await Promise.all(
    route.stops.map(async stop => {
      const obj = await env.CATALOG_BUCKET.get(`delivery-events/${date}/${stop.order_id}.json`);
      return obj ? await obj.json() : null;
    }),
  );

  // Find latest location ping for this branch
  const locList = await env.CATALOG_BUCKET.list({ prefix: `driver-locations/${date}/` });
  let location = null;
  for (const obj of locList.objects) {
    const loc = await (await env.CATALOG_BUCKET.get(obj.key))?.json();
    if (loc?.branch === branch && (!location || loc.received_at > location.received_at)) {
      location = loc;
    }
  }

  // Combine + compute totals
  const stops = route.stops.map((stop, i) => ({
    ...stop,
    status: events[i]?.status ?? 'pending',
    event: events[i] ?? undefined,
  }));

  return {
    branch, location, stops,
    driver_id: location?.driver_id ?? null,
    driver_name: location ? findDriverById(location.driver_id)?.name ?? null : null,
    totals: computeTotals(stops),
  };
}
Project structure

three apps in three folders.

worker/ # Cloudflare Worker · all three apps share this └── src/ ├── handlers/ │ ├── search.ts · fulfillment.ts · generator.ts · driver.ts │ └── dispatch.ts NEW# GET /api/v1/dispatch/status ├── lib/ │ ├── auth.ts # EDIT · JWT now includes role │ └── drivers.ts # EDIT · added role: 'driver' | 'admin' └── index.ts # EDIT · routes for /location + /dispatch/status driver-app/ # Tablet PWA for delivery drivers └── src/ ├── App.tsx # EDIT · added 60s location ping loop └── lib/api.ts # EDIT · added postLocation() dispatch-app/ # NEW · browser dashboard for Preet/Himmat ├── package.json # React + Vite + Tailwind + Leaflet ├── vite.config.ts # PWA manifest + workbox ├── tailwind.config.js · tsconfig.json · index.html └── src/ ├── main.tsx · App.tsx · types.ts · styles.css ├── screens/ │ ├── LoginScreen.tsx # Admin-only PIN login │ ├── DashboardScreen.tsx # Map + lists + stop drawer · 306 lines │ ├── ExceptionInboxScreen.tsx # Cross-truck exception list with call buttons │ └── EndOfDayReportScreen.tsx # Daily totals + CSV download ├── components/ │ └── Map.tsx # Leaflet wrapper · truck pins + stop markers └── lib/ ├── api.ts # Fetch with admin JWT └── storage.ts # IndexedDB auth
17 new files in dispatch-app 1 new file in worker (dispatch.ts) 5 small edits across worker + driver-app ~1,200 new lines 2 new deps · leaflet + @types/leaflet
Total project state

three apps. ~4,700 lines. ~$15/mo + ~$720 hardware.

After 30 turns in this thread, you have a complete operational system. Customer-facing bot books deliveries. Driver tablets execute them. Dispatch dashboard supervises in real-time. All three sit on top of one Cloudflare Worker that costs $0/mo on the free tier.

~3,500 LINES
Cloudflare Worker

All endpoints · catalog generator · auth · 31 files

~1,400 LINES
Driver app PWA

Offline-first · 5 screens · IndexedDB queue · location pings

~1,000 LINES
Dispatch app PWA

Live map · 4 screens · 15s polling · CSV export

7 ARTIFACTS
Published spec docs

v2 spec · F-150 walkthrough · Worker code · catalog generator · test suite · driver app · this