Nuxt Module
mbl-whereabout · v1.0.2 npm

Delivery tracking, live.

mbl-whereabout adds real-time driver tracking to any Nuxt 4 app — GPS updates from the driver, a live MapLibre map for the customer, and optional road snapping via Valhalla. Requires mbl-auth for Supabase config.

Try it live

Two demo pages are live — open the driver page on your phone and watch the tracking map update in real time.

How it works
1

Driver opens order page

Browser Geolocation API starts. GPS coordinates are posted to your server every few seconds.

2

Server stores location

Optionally snapped to the nearest road via Valhalla, then written to the locations table.

3

Customer sees it live

Supabase Realtime pushes the update. The MapLibre marker moves instantly — no polling.

Install

terminal
npm install @madebylars.com/mbl-whereabout maplibre-gl

Configuration

nuxt.config.ts
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@madebylars.com/mbl-auth', '@madebylars.com/mbl-whereabout'],
  css: ['maplibre-gl/dist/maplibre-gl.css'],
  vite: {
    optimizeDeps: { include: ['maplibre-gl', 'cookie'] },
  },
  // optional — road snapping via self-hosted Valhalla
  mblWhereabout: {
    valhallaUrl: 'http://localhost:8002',
  },
})

What you get

📍

Live driver GPS

useDriverLocation starts the browser Geolocation API and pushes updates to your server on every position change.

🗺️

Customer tracking map

useOrderTracking subscribes to Supabase Realtime. useDeliveryMap mounts a MapLibre map and moves the driver marker in real time.

🛣️

Road snapping

Optional Valhalla integration snaps GPS noise to the nearest road before storing. Self-host with the included docker-compose.yml.

🔐

Built on mbl-auth

Reuses your existing Supabase config — no extra credentials. Driver routes are automatically protected by the auth middleware.

Auto-mode for drivers

Add definePageMeta({ driverTracking: true }) and the plugin starts and stops GPS automatically on mount and leave.

🗂️

Minimal schema

Three tables: drivers, orders, locations. The SQL is provided — paste it into the Supabase SQL editor and you're done.

Database setup

Run this once in your Supabase SQL editor. If you enable RLS on locations, add a SELECT policy so the customer map can read rows.

supabase/sql/whereabout.sql
-- Run in your Supabase SQL editor
create table drivers (
  id uuid primary key default gen_random_uuid(),
  user_id uuid,
  name text,
  created_at timestamptz default now()
);

create table orders (
  id uuid primary key default gen_random_uuid(),
  customer_id uuid,
  driver_id uuid references drivers(id),
  status text default 'pending',
  created_at timestamptz default now()
);

create table locations (
  id uuid primary key default gen_random_uuid(),
  order_id uuid references orders(id) unique,
  driver_id uuid references drivers(id),
  lat double precision not null,
  lng double precision not null,
  accuracy float,
  snapped_lat double precision,
  snapped_lng double precision,
  updated_at timestamptz default now()
);

Driver page

Add the meta flag for auto-mode, or call useDriverLocation() manually for full control.

pages/driver/[orderId].vue
<script setup lang="ts">
// Auto-mode: add the meta flag and the plugin handles everything
definePageMeta({ driverTracking: true })

// Or control it manually:
const { start, stop, isTracking, error } = useDriverLocation()
await start('order-uuid')
</script>

Customer tracking page

useOrderTracking subscribes to Supabase Realtime. useDeliveryMap mounts the MapLibre map and moves the marker on every update.

pages/order/[orderId]/track.vue
<template>
  <div id="delivery-map" style="width: 100%; height: 500px;" />
</template>

<script setup lang="ts">
const route = useRoute()
const { driverLocation } = useOrderTracking(route.params.orderId as string)
useDeliveryMap('delivery-map', { driverLocation, zoom: 15 })
</script>

Module options

OptionDefaultDescription
valhallaUrl'http://localhost:8002'Road-snapping endpoint. Omit to skip snapping.
tileUrlOpenStreetMapMap tile URL passed to MapLibre GL.