npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@madebylars.com/mbl-plan

v1.0.2

Published

Trip planning and multi-stop route management add-on for mbl-transport

Readme

@madebylars.com/mbl-plan

npm version npm downloads License Nuxt

A premium Nuxt 4 module in the MadeByLars ecosystem that adds trip planning and multi-stop route management to mbl-transport.

Enable dispatchers to group multiple orders into a single trip for one vehicle and driver. A trip has an ordered list of stops — each stop is a pickup or delivery for a specific order.


Overview

mbl-plan is a feature-flagged add-on. It is only active for tenants where a superadmin has enabled it. When inactive, mbl-transport behaves exactly as today. When active, the order flow gains a new planned status between confirmed and assigned.

Order flow

Without mbl-plan (default)
  confirmed → assigned → collected → in_transit → delivered

With mbl-plan enabled for tenant
  confirmed → planned → assigned → collected → in_transit → delivered

planned means the order has been added to a trip but the trip has not yet been dispatched to the driver. Once the dispatcher sends the trip, all orders in it move to assigned simultaneously via an atomic Postgres RPC call.


Feature flag

The flag lives in tenant.tenants.features (jsonb column). Enable planning for a tenant:

UPDATE tenant.tenants
  SET features = '{"planning": true}'
  WHERE id = '<tenant-uuid>';

The Supabase custom_access_token_hook injects the features object into the JWT so every client and server handler can check it without an extra DB query.


Installation

npm install @madebylars.com/mbl-plan

Add the module to your nuxt.config.ts:

export default defineNuxtConfig({
  modules: ['@madebylars.com/mbl-plan'],
})

The module auto-imports all composables and registers its locale strings under the mblPlan.* namespace (requires @nuxtjs/i18n).


Database migration

Run migrations/003_add_planning.sql against your Supabase project. It:

  1. Adds features jsonb to tenant.tenants
  2. Adds planned to the transport.orders status check constraint
  3. Creates transport.trips and transport.trip_stops tables with indexes and RLS
  4. Creates transport.dispatch_trip(p_trip_id) — atomic dispatch RPC
  5. Creates transport.reorder_stops(p_trip_id, p_ordered_stop_ids) — atomic reorder RPC
  6. Creates transport.check_trip_completion() trigger — auto-completes a trip when all stops are marked done

Also extend custom_access_token_hook with the snippet in the migration file to inject features into JWT claims.


Composables

All composables are auto-imported. They call the app's own /api/* endpoints — never Supabase directly.

usePlanFeature()

Check whether the planning feature is enabled for the current tenant. Read from the JWT — no extra request.

const { isEnabled } = usePlanFeature()
// isEnabled: Ref<boolean>

if (isEnabled.value) {
  // show planning UI
}

useTrips(filters?)

Reactive list of trips. All filters are optional.

const { data, pending, error, refresh } = useTrips({
  date: '2026-06-07',      // ISO date — filter by planned_date
  status: 'draft',
  driverId: '...',
  vehicleId: '...',
})
// data: Ref<Trip[]>

useTrip(tripId)

Single trip with its ordered stop list, order summaries, driver, and vehicle.

const { data, pending, error, refresh } = useTrip(tripId)
// data: Ref<TripWithStops | null>

useTripActions()

Imperative actions for creating and managing trips.

const { createTrip, updateTrip, deleteTrip, dispatchTrip, completeTrip } = useTripActions()

// Create a new draft trip
const trip = await createTrip({
  vehicleId: '...',
  driverId: '...',
  plannedDate: '2026-06-07',
  notes: 'Morning run',
})

// Atomically dispatch: sets trip → dispatched, all orders → assigned
await dispatchTrip(trip.id)

dispatchTrip calls POST /api/trips/[id]/dispatch, which runs the transport.dispatch_trip() Postgres function in a single transaction.

useStopActions()

Add, remove, reorder, and complete individual stops.

const { addStop, removeStop, reorderStops, completeStop } = useStopActions()

// Add a stop — creates both pickup and delivery stops for the order
// and moves the order to 'planned'
await addStop(tripId, orderId, 'pickup')

// Reorder — single RPC call, no race conditions
await reorderStops(tripId, ['stop-id-1', 'stop-id-3', 'stop-id-2'])

// Mark a stop done — triggers auto-completion when all stops are done
await completeStop(stopId)

useDriverTrip()

Driver-facing composable. Returns the active dispatched trip for the current driver with stops ordered by sequence.

const { data, pending, error } = useDriverTrip()
// data: Ref<TripWithStops | null>

const { completeStop } = useStopActions()
await completeStop(stopId)

TypeScript types

import type {
  Trip,
  TripStop,
  TripWithStops,
  TripStopWithOrder,
  TripStatus,       // 'draft' | 'dispatched' | 'in_progress' | 'completed'
  StopType,         // 'pickup' | 'delivery'
  CreateTripInput,
  UpdateTripInput,
  TripsFilters,
  OrderAddress,
  DriverSummary,
  VehicleSummary,
} from '@madebylars.com/mbl-plan'

i18n

Locale strings are registered under the mblPlan.* namespace. English and Swedish are included. Add more by extending @nuxtjs/i18n in the host app.

// Access in templates
$t('mblPlan.actions.dispatch')        // 'Dispatch trip'
$t('mblPlan.status.in_progress')      // 'In progress'
$t('mblPlan.feature.disabled')        // 'Trip planning is not enabled for your account'

| Key | en | sv | |---|---|---| | mblPlan.status.draft | Draft | Utkast | | mblPlan.status.dispatched | Dispatched | Skickad | | mblPlan.status.in_progress | In progress | Pågående | | mblPlan.status.completed | Completed | Avslutad | | mblPlan.stopType.pickup | Pickup | Upphämtning | | mblPlan.stopType.delivery | Delivery | Leverans | | mblPlan.actions.createTrip | Create trip | Skapa tur | | mblPlan.actions.addStop | Add stop | Lägg till stopp | | mblPlan.actions.dispatch | Dispatch trip | Skicka tur | | mblPlan.actions.completeStop | Mark stop done | Markera stopp klart |


mbl-transport integration

API endpoints to implement

| Method | Path | Description | |---|---|---| | GET | /api/trips | List trips (?date, ?status, ?driverId, ?vehicleId) | | POST | /api/trips | Create draft trip | | GET | /api/trips/driver/active | Active trip for the authenticated driver | | GET | /api/trips/[id] | Trip + stops + order summaries | | PATCH | /api/trips/[id] | Update trip metadata (draft only) | | DELETE | /api/trips/[id] | Delete trip (draft only) | | POST | /api/trips/[id]/dispatch | Atomic dispatch via transport.dispatch_trip() RPC | | POST | /api/trips/[id]/complete | Mark trip completed | | POST | /api/trips/[id]/stops | Add stop (creates pickup + delivery, moves order → planned) | | DELETE | /api/trips/[id]/stops/[stopId] | Remove a stop | | POST | /api/trips/[id]/stops/reorder | Reorder via transport.reorder_stops() RPC | | POST | /api/stops/[stopId]/complete | Mark stop done | | PATCH | /api/admin/tenants/[id]/features | Superadmin — toggle feature flags |

New pages

/dispatcher/planning — gated behind usePlanFeature().isEnabled

  • Left panel: confirmed orders for today/upcoming dates with "Add to trip" button
  • Right panel: trip builder with vehicle/driver/date selector, stop list with up/down reorder, and "Dispatch" button (disabled until ≥1 stop)
  • Centre: mbl-fleetmap component with numbered stop pins in sequence order

/driver/trip — gated behind usePlanFeature().isEnabled

  • Trip header (vehicle, planned date, total stops)
  • Ordered stop list with type badge, address, order ref, "Mark done" button
  • Completed stops shown with strikethrough and timestamp
  • Map showing remaining stops only

Modified pages

/admin/tenants/[id] — add a toggle to enable/disable trip planning per tenant. Calls PATCH /api/admin/tenants/[id]/features. JWT picks up the change on the user's next session refresh.

/orders/[id] — when an order has status planned or was assigned via a trip, show a planning context block:

This order is part of trip #TRP-0012
Vehicle: Ford Transit — AB 123 CD  |  Driver: Erik Svensson
Planned: 3 stops — stop 2 of 3

Order status badges and filter dropdowns — add planned as a display value using mblPlan.status i18n strings.

What does NOT change

  • mbl-auth, mbl-order, mbl-whereabout, mbl-fleetmap — untouched
  • The assigned → collected → in_transit → delivered flow is unchanged for both planned and unplanned orders
  • Tenants without features.planning: true never see the planned status or any planning UI

File structure

src/
  module.ts                        # Module definition, composable auto-imports, i18n hook
  types.ts                         # All exported TypeScript types
  runtime/
    composables/
      usePlanFeature.ts            # Feature flag from JWT
      useTrips.ts                  # Reactive trip list
      useTrip.ts                   # Single trip with stops
      useTripActions.ts            # Create / update / delete / dispatch / complete
      useStopActions.ts            # Add / remove / reorder / complete stops
      useDriverTrip.ts             # Driver-facing active trip
    locales/
      en.ts                        # English strings
      sv.ts                        # Swedish strings
migrations/
  003_add_planning.sql             # Run once against the target Supabase project

Development

# Install dependencies
npm install

# Generate type stubs
npm run dev:prepare

# Develop with the playground
npm run dev

# Build the playground
npm run dev:build

# Run ESLint
npm run lint

# Run Vitest
npm run test
npm run test:watch

# Release new version
npm run release