Blocks
Delivery Tracker Block
ReviewedA working post-purchase tracker with API-backed courier events, persistent instructions, customer actions, and delivered-state proof.
Commerce
Live delivery tracker
Copy the responsive status-first experience and repository-local API contract into commerce, marketplace, logistics, field service, or appointment products that need customer-facing delivery updates.
<script setup>
import { computed, onMounted, ref, watch } from 'vue';
import {
DomAlert,
DomAvatar,
DomBadge,
DomButton,
DomDialog,
DomEmptyState,
DomProgress,
DomSelect,
DomStatusPill,
DomTextareaInput,
DomTextInput,
DomToggle,
} from '@getdom/studio/vue';
const dropoffOptions = [
{ label: 'Leave with reception', value: 'reception', description: 'The courier can hand the parcel to reception staff.' },
{ label: 'Meet at the entrance', value: 'entrance', description: 'Meet the courier at the building entrance.' },
{ label: 'Leave at the front desk', value: 'front-desk', description: 'Use the staffed front desk or concierge.' },
{ label: 'Call on arrival', value: 'call-on-arrival', description: 'The courier must call before completing delivery.' },
];
const orders = ref([]);
const selectedOrderId = ref('ord_20482');
const order = ref(null);
const feedback = ref(null);
const loadError = ref('');
const instructionDialogOpen = ref(false);
const dialogMode = ref('instructions');
const dropoff = ref('reception');
const accessCode = ref('');
const deliveryNote = ref('');
const contactless = ref(true);
const isLoading = ref(true);
const isSaving = ref(false);
const isResolving = ref(false);
const isSyncing = ref(false);
let orderRequestSequence = 0;
const orderOptions = computed(() => orders.value.map((item) => ({
value: item.id,
label: `Order ${item.number}`,
description: `${item.statusLabel} · ${item.etaLabel}`,
actionRequiredCount: item.actionRequiredCount,
})));
const openException = computed(() => order.value?.openExceptions?.[0] || null);
const currentCheckpoint = computed(() => order.value?.activeCheckpoint || null);
const isDelivered = computed(() => order.value?.status === 'delivered');
const activeCheckpointIndex = computed(() => order.value?.activeCheckpointIndex || 0);
const dropoffLabel = computed(() => dropoffOptions.find((option) => option.value === order.value?.instructions?.dropoff)?.label || 'Not set');
const orderTotal = computed(() => (order.value?.items || []).reduce((total, item) => total + item.price, 0));
const accessCodeValid = computed(() => /^[A-Za-z0-9-]{4,12}$/.test(accessCode.value.trim()));
const instructionsDirty = computed(() => {
if (!order.value) return false;
return dropoff.value !== order.value.instructions.dropoff
|| accessCode.value.trim() !== order.value.instructions.accessCode
|| deliveryNote.value.trim() !== order.value.instructions.note
|| contactless.value !== order.value.instructions.contactless;
});
const dialogTitle = computed(() => dialogMode.value === 'exception' ? 'Send the entry code' : 'Edit delivery instructions');
const dialogDescription = computed(() => dialogMode.value === 'exception'
? 'We will send these instructions directly to the courier and clear the delivery blocker.'
: 'Changes are validated by the order API and remain available after this preview reloads.');
watch(selectedOrderId, (orderId, previousOrderId) => {
if (orderId && previousOrderId && orderId !== previousOrderId) loadOrder(orderId);
});
onMounted(loadOrders);
/**
* Requests JSON from the delivery tracker API and promotes non-success
* responses into ordinary JavaScript errors for consistent recovery UI.
*
* @param {string} url API route.
* @param {RequestInit} [options] Fetch options.
* @returns {Promise<Record<string, unknown>>} Parsed response payload.
*/
async function requestJson(url, options = {}) {
const response = await fetch(url, {
...options,
headers: {
Accept: 'application/json',
...(options.body ? { 'Content-Type': 'application/json' } : {}),
...(options.headers || {}),
},
});
const payload = await response.json().catch(() => ({}));
if (!response.ok) throw new Error(payload.error || `Request failed with status ${response.status}.`);
return payload;
}
/**
* Loads the order catalog before hydrating the initially selected delivery.
*
* @returns {Promise<void>}
*/
async function loadOrders() {
isLoading.value = true;
loadError.value = '';
try {
const payload = await requestJson('/api/block-demos/delivery-tracker/orders');
orders.value = Array.isArray(payload.orders) ? payload.orders : [];
if (!orders.value.length) throw new Error('No tracked deliveries are available.');
if (!orders.value.some((item) => item.id === selectedOrderId.value)) {
selectedOrderId.value = orders.value[0].id;
}
await loadOrder(selectedOrderId.value);
} catch (error) {
loadError.value = error instanceof Error ? error.message : 'Could not load your deliveries.';
isLoading.value = false;
}
}
/**
* Loads one delivery while ignoring stale responses after a quick order switch.
*
* @param {string} orderId Canonical order identifier.
* @returns {Promise<void>}
*/
async function loadOrder(orderId) {
const requestSequence = ++orderRequestSequence;
isLoading.value = true;
loadError.value = '';
feedback.value = null;
try {
const payload = await requestJson(`/api/block-demos/delivery-tracker/${encodeURIComponent(orderId)}`);
if (requestSequence !== orderRequestSequence) return;
applyOrder(payload.order);
} catch (error) {
if (requestSequence !== orderRequestSequence) return;
loadError.value = error instanceof Error ? error.message : 'Could not load this delivery.';
} finally {
if (requestSequence === orderRequestSequence) isLoading.value = false;
}
}
/**
* Applies one complete API order and refreshes the editable instruction draft.
*
* @param {Record<string, unknown>} nextOrder API order payload.
* @returns {void}
*/
function applyOrder(nextOrder) {
order.value = nextOrder;
dropoff.value = nextOrder.instructions.dropoff;
accessCode.value = nextOrder.instructions.accessCode;
deliveryNote.value = nextOrder.instructions.note;
contactless.value = nextOrder.instructions.contactless;
syncOrderSummary(nextOrder.orderSummary);
}
/**
* Refreshes selector metadata after a delivery mutation.
*
* @param {Record<string, unknown>} summary Updated order summary.
* @returns {void}
*/
function syncOrderSummary(summary) {
orders.value = orders.value.map((item) => (item.id === summary.id ? { ...item, ...summary } : item));
}
/**
* Opens the instruction dialog with a general or exception-resolution intent.
*
* @param {'instructions'|'exception'} mode Dialog workflow.
* @returns {void}
*/
function openInstructions(mode = 'instructions') {
dialogMode.value = mode;
if (order.value) {
dropoff.value = order.value.instructions.dropoff;
accessCode.value = order.value.instructions.accessCode;
deliveryNote.value = order.value.instructions.note;
contactless.value = order.value.instructions.contactless;
}
feedback.value = null;
instructionDialogOpen.value = true;
}
/**
* Saves the current instruction draft through the order API.
*
* @returns {Promise<void>}
*/
async function saveInstructions() {
if (!order.value || !instructionsDirty.value) return;
isSaving.value = true;
feedback.value = null;
try {
const payload = await requestJson(
`/api/block-demos/delivery-tracker/${encodeURIComponent(selectedOrderId.value)}/instructions`,
{
method: 'PATCH',
body: JSON.stringify(instructionPayload()),
},
);
applyOrder(payload.order);
instructionDialogOpen.value = false;
feedback.value = {
tone: 'success',
title: 'Instructions updated',
description: 'The courier now has your latest drop-off preference and delivery note.',
};
} catch (error) {
feedback.value = {
tone: 'danger',
title: 'Instructions not saved',
description: error instanceof Error ? error.message : 'Check the delivery details and try again.',
};
} finally {
isSaving.value = false;
}
}
/**
* Sends the access-code resolution and updated instructions to the API.
*
* @returns {Promise<void>}
*/
async function resolveException() {
if (!order.value || !openException.value || !accessCodeValid.value) return;
isResolving.value = true;
feedback.value = null;
try {
const payload = await requestJson(
`/api/block-demos/delivery-tracker/${encodeURIComponent(selectedOrderId.value)}/exceptions/${encodeURIComponent(openException.value.id)}/resolve`,
{
method: 'POST',
body: JSON.stringify(instructionPayload()),
},
);
applyOrder(payload.order);
instructionDialogOpen.value = false;
feedback.value = {
tone: 'success',
title: 'Entry code sent',
description: 'The blocker is cleared and the courier can complete the final route.',
};
} catch (error) {
feedback.value = {
tone: 'danger',
title: 'Code not sent',
description: error instanceof Error ? error.message : 'Check the access code and try again.',
};
} finally {
isResolving.value = false;
}
}
/**
* Pulls the next deterministic carrier event from the server-owned tracker.
*
* @returns {Promise<void>}
*/
async function syncDelivery() {
if (!order.value || isDelivered.value) return;
isSyncing.value = true;
feedback.value = null;
try {
const payload = await requestJson(
`/api/block-demos/delivery-tracker/${encodeURIComponent(selectedOrderId.value)}/sync`,
{
method: 'POST',
body: JSON.stringify({ revision: order.value.revision }),
},
);
applyOrder(payload.order);
feedback.value = {
tone: 'success',
title: 'Tracking refreshed',
description: `${payload.checkpoint.label} is now the latest carrier update.`,
};
} catch (error) {
feedback.value = {
tone: 'warning',
title: 'Tracking needs your attention',
description: error instanceof Error ? error.message : 'Resolve the open delivery action and refresh again.',
};
} finally {
isSyncing.value = false;
}
}
/**
* Builds the shared API payload for instruction and exception mutations.
*
* @returns {{ dropoff: string, accessCode: string, note: string, contactless: boolean, revision: number }} Instruction payload.
*/
function instructionPayload() {
return {
dropoff: dropoff.value,
accessCode: accessCode.value.trim(),
note: deliveryNote.value.trim(),
contactless: contactless.value,
revision: order.value.revision,
};
}
/**
* Resolves a status tone for an order or checkpoint state.
*
* @param {string} status Status identifier.
* @returns {string} DOM Studio semantic tone.
*/
function statusTone(status) {
return {
delivered: 'success',
complete: 'success',
current: 'primary',
out_for_delivery: 'primary',
in_transit: 'info',
upcoming: 'neutral',
}[status] || 'neutral';
}
/**
* Returns a compact checkpoint label for the five-column mobile progress row.
*
* @param {string} checkpointKey Checkpoint identifier.
* @param {string} fallback Full checkpoint label.
* @returns {string} Short customer-readable label.
*/
function checkpointCompactLabel(checkpointKey, fallback) {
return {
confirmed: 'Confirmed',
packed: 'Packed',
handoff: 'Courier',
nearby: 'Nearby',
delivered: 'Delivered',
}[checkpointKey] || fallback;
}
/**
* Formats a whole-value price in pounds sterling.
*
* @param {number} value Monetary value.
* @returns {string} Localized currency value.
*/
function formatCurrency(value) {
return new Intl.NumberFormat('en-GB', {
style: 'currency',
currency: 'GBP',
maximumFractionDigits: 0,
}).format(value || 0);
}
</script>
<template>
<section class="min-h-screen bg-canvas text-canvas-fg" data-testid="delivery-tracker-block">
<header class="border-b border-border bg-canvas">
<div class="mx-auto flex max-w-6xl flex-col gap-4 px-4 py-4 sm:px-6 lg:flex-row lg:items-end lg:justify-between lg:px-8">
<div>
<p class="text-xs font-semibold uppercase tracking-wide text-muted-fg">DOM Supply</p>
<h1 class="mt-1 whitespace-nowrap text-xl font-semibold">Track your delivery</h1>
</div>
<DomSelect
v-model="selectedOrderId"
label="Delivery order"
:options="orderOptions"
width="min-w-[22rem]"
>
<template #value="{ option }">
<span class="flex min-w-0 items-center justify-between gap-3">
<span class="truncate font-semibold">{{ option?.label || `Order ${order?.number || ''}` }}</span>
<DomBadge v-if="order?.orderSummary?.actionRequiredCount" tone="warning" size="sm">Action needed</DomBadge>
</span>
</template>
<template #option="{ option }">
<span class="flex min-w-0 items-center justify-between gap-3">
<span class="min-w-0">
<span class="block truncate font-semibold">{{ option.label }}</span>
<span class="block truncate text-xs opacity-75">{{ option.description }}</span>
</span>
<DomBadge v-if="option.actionRequiredCount" tone="warning" size="sm">{{ option.actionRequiredCount }}</DomBadge>
</span>
</template>
</DomSelect>
</div>
</header>
<main class="mx-auto max-w-6xl px-4 py-5 sm:px-6 sm:py-8 lg:px-8">
<DomAlert
v-if="loadError"
tone="danger"
title="Tracking unavailable"
:description="loadError"
>
<template #actions>
<DomButton variant="secondary" size="sm" @click="loadOrders">Try again</DomButton>
</template>
</DomAlert>
<DomEmptyState
v-else-if="isLoading && !order"
title="Loading your delivery"
description="Checking the latest courier status and customer instructions."
size="sm"
/>
<div v-else-if="order" class="grid gap-8 lg:grid-cols-[minmax(0,1fr)_20rem] lg:gap-10">
<div class="min-w-0">
<section aria-labelledby="delivery-status-heading">
<div class="flex flex-wrap items-center gap-2">
<DomStatusPill :tone="statusTone(order.status)" size="sm">{{ order.statusLabel }}</DomStatusPill>
<span class="text-xs text-muted-fg">Updated {{ order.fulfilment.lastUpdatedAt }}</span>
</div>
<p class="mt-5 text-sm font-medium text-muted-fg">{{ isDelivered ? 'Delivery complete' : 'Estimated arrival' }}</p>
<h2 id="delivery-status-heading" class="mt-1 text-3xl font-semibold tracking-tight sm:text-5xl">{{ order.etaLabel }}</h2>
<p class="mt-3 max-w-2xl text-sm leading-6 text-muted-fg sm:text-base">
<template v-if="isDelivered">Your order was left at {{ order.proof.location.toLowerCase() }} and received by {{ order.proof.receivedBy }}.</template>
<template v-else-if="order.fulfilment.stopsAway">{{ order.fulfilment.courierName }} is {{ order.fulfilment.stopsAway }} {{ order.fulfilment.stopsAway === 1 ? 'stop' : 'stops' }} away · {{ order.fulfilment.distanceLabel }}.</template>
<template v-else>{{ order.fulfilment.distanceLabel }} · A local courier will be assigned before the final route.</template>
</p>
<DomProgress
class="mt-6"
:value="order.progress"
label="Delivery progress"
:tone="isDelivered ? 'success' : 'primary'"
:size="isDelivered ? 'md' : 'sm'"
:show-value="false"
/>
<ol class="mt-3 grid grid-cols-5 gap-2" aria-label="Delivery checkpoints">
<li v-for="(checkpoint, index) in order.checkpoints" :key="checkpoint.key" class="min-w-0">
<span
class="block text-[9px] font-semibold tracking-tight sm:text-xs sm:tracking-normal"
:class="index <= activeCheckpointIndex ? 'text-canvas-fg' : 'text-muted-fg'"
:title="checkpoint.label"
>
{{ checkpointCompactLabel(checkpoint.key, checkpoint.label) }}
</span>
</li>
</ol>
</section>
<DomAlert
v-if="openException"
class="mt-6"
tone="warning"
:title="openException.title"
:description="`${openException.description} ${openException.dueLabel}.`"
>
<template #actions>
<DomButton size="sm" @click="openInstructions('exception')">Add entry code</DomButton>
</template>
</DomAlert>
<DomAlert
v-if="feedback"
class="mt-6"
:tone="feedback.tone"
:title="feedback.title"
:description="feedback.description"
dismissible
@dismiss="feedback = null"
/>
<section class="mt-7 border-y border-border py-5" aria-label="Courier and tracking actions">
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div class="flex min-w-0 items-center gap-3">
<DomAvatar :name="order.fulfilment.courierName" :initials="order.fulfilment.courierInitials" size="lg" />
<div class="min-w-0">
<p class="truncate font-semibold">{{ order.fulfilment.courierName }}</p>
<p class="truncate text-sm text-muted-fg">{{ order.fulfilment.carrier }} · {{ order.fulfilment.vehicle }}</p>
</div>
</div>
<div class="flex flex-wrap gap-2">
<DomButton variant="secondary" size="sm" :disabled="isDelivered" @click="openInstructions('instructions')">Edit instructions</DomButton>
<DomButton size="sm" :loading="isSyncing" :disabled="isDelivered" @click="syncDelivery">
{{ isDelivered ? 'Delivery complete' : 'Refresh tracking' }}
</DomButton>
</div>
</div>
</section>
<section class="mt-8" aria-labelledby="timeline-heading">
<div class="flex items-end justify-between gap-4">
<div>
<p class="text-xs font-semibold uppercase tracking-wide text-muted-fg">Shipment history</p>
<h2 id="timeline-heading" class="mt-1 text-xl font-semibold">{{ currentCheckpoint.label }}</h2>
</div>
<DomBadge :tone="openException ? 'warning' : 'success'">{{ openException ? 'Action required' : 'On track' }}</DomBadge>
</div>
<ol class="mt-5 divide-y divide-border border-y border-border">
<li v-for="checkpoint in [...order.checkpoints].reverse()" :key="checkpoint.key" class="grid grid-cols-[auto_minmax(0,1fr)_auto] gap-3 py-4">
<DomStatusPill :tone="statusTone(checkpoint.status)" size="sm">{{ checkpoint.status === 'current' ? 'Now' : checkpoint.status === 'complete' ? 'Done' : 'Next' }}</DomStatusPill>
<div>
<p class="font-semibold">{{ checkpoint.label }}</p>
<p class="mt-1 text-sm leading-6 text-muted-fg">{{ checkpoint.detail }}</p>
</div>
<time class="text-xs font-medium text-muted-fg">{{ checkpoint.occurredAt || 'Pending' }}</time>
</li>
</ol>
</section>
<section class="mt-8 lg:hidden" aria-labelledby="mobile-order-heading">
<p class="text-xs font-semibold uppercase tracking-wide text-muted-fg">Order details</p>
<h2 id="mobile-order-heading" class="mt-1 text-xl font-semibold">{{ order.items.length }} {{ order.items.length === 1 ? 'item' : 'items' }} · {{ formatCurrency(orderTotal) }}</h2>
<div class="mt-4 divide-y divide-border border-y border-border">
<div v-for="item in order.items" :key="item.id" class="flex items-start justify-between gap-4 py-3 text-sm">
<div>
<p class="font-semibold">{{ item.name }}</p>
<p class="mt-1 text-muted-fg">{{ item.detail }}</p>
</div>
<span class="font-medium">{{ formatCurrency(item.price) }}</span>
</div>
</div>
<p class="mt-4 text-sm leading-6 text-muted-fg">{{ order.address }}</p>
</section>
</div>
<aside class="hidden border-l border-border pl-8 lg:block" aria-label="Delivery details">
<section>
<div class="flex items-start justify-between gap-3">
<div>
<p class="text-xs font-semibold uppercase tracking-wide text-muted-fg">Your instructions</p>
<h2 class="mt-1 text-lg font-semibold">{{ dropoffLabel }}</h2>
</div>
<DomStatusPill tone="success" size="sm">Saved</DomStatusPill>
</div>
<p class="mt-3 text-sm leading-6 text-muted-fg">{{ order.instructions.note || 'No additional note.' }}</p>
<dl class="mt-4 space-y-3 text-sm">
<div class="flex justify-between gap-4">
<dt class="text-muted-fg">Entry code</dt>
<dd class="font-medium">{{ order.instructions.accessCode || 'Not provided' }}</dd>
</div>
<div class="flex justify-between gap-4">
<dt class="text-muted-fg">Contactless</dt>
<dd class="font-medium">{{ order.instructions.contactless ? 'Allowed' : 'Handoff required' }}</dd>
</div>
</dl>
<DomButton class="mt-5 w-full" variant="secondary" size="sm" :disabled="isDelivered" @click="openInstructions('instructions')">Edit instructions</DomButton>
</section>
<section class="mt-7 border-t border-border pt-6">
<div class="flex items-end justify-between gap-3">
<div>
<p class="text-xs font-semibold uppercase tracking-wide text-muted-fg">Order details</p>
<h2 class="mt-1 text-lg font-semibold">{{ order.items.length }} {{ order.items.length === 1 ? 'item' : 'items' }}</h2>
</div>
<span class="font-semibold">{{ formatCurrency(orderTotal) }}</span>
</div>
<div class="mt-4 divide-y divide-border border-y border-border">
<div v-for="item in order.items" :key="item.id" class="py-3 text-sm">
<p class="font-semibold">{{ item.name }}</p>
<div class="mt-1 flex justify-between gap-4 text-muted-fg">
<span>{{ item.detail }}</span>
<span>{{ formatCurrency(item.price) }}</span>
</div>
</div>
</div>
<p class="mt-4 text-sm leading-6 text-muted-fg">{{ order.address }}</p>
</section>
<section v-if="order.proof" class="mt-7 border-t border-border pt-6">
<p class="text-xs font-semibold uppercase tracking-wide text-muted-fg">Proof of delivery</p>
<p class="mt-2 font-semibold">Received by {{ order.proof.receivedBy }}</p>
<p class="mt-1 text-sm text-muted-fg">{{ order.proof.location }} · {{ order.proof.recordedAt }}</p>
</section>
</aside>
</div>
</main>
<DomDialog
v-model="instructionDialogOpen"
:title="dialogTitle"
:description="dialogDescription"
size="md"
>
<form class="space-y-4" @submit.prevent="dialogMode === 'exception' ? resolveException() : saveInstructions()">
<DomSelect v-model="dropoff" label="Drop-off preference" :options="dropoffOptions" width="min-w-[22rem]" />
<DomTextInput
v-model="accessCode"
label="Entry or access code"
placeholder="For example 2048"
:description="dialogMode === 'exception' ? 'Required to clear the current courier blocker.' : 'Optional. Shared only with the delivery team.'"
/>
<DomTextareaInput
v-model="deliveryNote"
label="Delivery note"
placeholder="Reception details, safe place, or contact instructions"
:rows="3"
/>
<div class="border-y border-border py-3">
<DomToggle v-model="contactless" label="Allow contactless delivery" description="The courier can complete delivery without a face-to-face handoff." />
</div>
</form>
<template #footer>
<DomButton variant="ghost" @click="instructionDialogOpen = false">Cancel</DomButton>
<DomButton
v-if="dialogMode === 'exception'"
:loading="isResolving"
:disabled="!accessCodeValid"
@click="resolveException"
>
Send code & resolve
</DomButton>
<DomButton v-else :loading="isSaving" :disabled="!instructionsDirty" @click="saveInstructions">Save instructions</DomButton>
</template>
</DomDialog>
</section>
</template>
Integration
How to use this block
Use this block when customers need to understand where an order is, what happens next, and how to fix a delivery problem without contacting support. Its Shop- and Uber-inspired hierarchy puts the ETA and current blocker before secondary order detail, without pretending a decorative map is live tracking.
GET /api/block-demos/delivery-tracker/ordersandGET /api/block-demos/delivery-tracker/:orderIdprovide the order list and normalized tracking detail.PATCH /api/block-demos/delivery-tracker/:orderId/instructionspersists the richDomSelectdrop-off choice, access code, contactless preference, and notes with optimistic revision checks.POST /api/block-demos/delivery-tracker/:orderId/exceptions/:exceptionId/resolvevalidates the missing access code and removes the customer-owned blocker.POST /api/block-demos/delivery-tracker/:orderId/syncis a deterministic demo stand-in for carrier webhooks. The server owns checkpoint transitions and delivered proof.- The repository-local store survives preview reloads but resets when the server restarts. Replace it with your order database, carrier adapter, event ingestion, and authorization checks in production.
Data
Recommended delivery payload
{
order: {
id: 'ord_20482',
number: 'GD-20482',
customerId: 'cus_118',
status: 'out_for_delivery',
etaWindow: { startsAt: '2026-06-11T16:35:00Z', endsAt: '2026-06-11T16:55:00Z' }
},
fulfilment: {
carrier: 'Relay Courier',
courierName: 'Nina Patel',
vehicle: 'Bike 42',
trackingUrl: '/orders/ord_20482/track',
proofRequired: true
},
checkpoints: [
{ key: 'packed', label: 'Packed', status: 'complete', occurredAt: '2026-06-11T12:10:00Z' },
{ key: 'handoff', label: 'Courier handoff', status: 'complete', occurredAt: '2026-06-11T15:18:00Z' },
{ key: 'nearby', label: 'Nearby', status: 'current', occurredAt: null },
{ key: 'delivered', label: 'Delivered', status: 'upcoming', occurredAt: null }
],
instructions: {
dropoff: 'Leave with reception',
accessCode: '2048',
contactless: true,
notes: 'Reception closes at 18:00.'
},
exceptions: [],
proof: null,
revision: 9
}Customization
Implementation notes
Realtime updates
The demo sync route advances a deterministic checkpoint. In production, ingest signed carrier webhooks or a realtime stream, then map noisy events into stable customer states.
Exception rules
Represent each blocker as an action with a due time, owner, resolution payload, and backend validation result. This keeps support tooling and customer UI aligned.
Future updates
Carrier adapters, signed webhook ingestion, durable proof media, pickup-point selection, and reschedule dialogs are the natural production extensions.