Forwarder: the Schedule and Market View

The two screens the dispatch floor lives in — the fleet Schedule and the offer-matching Market View — plus load-to-load, a route model I took from problem framing to implementation.
Web
B2B
Logistics
Role

Product Designer (2022) → Design Lead (2026)

Users

Forwarders, planners, dispatchers

Timeline

2022–2026

Status

Live

Methods

Shadowing Users · Information Architecture · Design System · User Testing · Desk Research · Benchmarking

The Schedule: every truck on the road, one row each, with Today / Tomorrow / Later tabs

The Schedule — every truck on the road, one row each.

Overview

Two screens carry almost all the operational weight: the Schedule, a live fleet timeline, and Market View, where offers get matched to trucks.

The forwarder app is the centerpiece of the TMS. Almost every other module in the system feeds into or branches off these two screens.

I joined six months after launch. The first version of Market View and the Schedule's tab structure were already in place. Everything since is mine: four years of density and information-architecture work, re-packing both screens each time the business added a field, a role or a regulation. Market View has been through enough of those rounds that what remains of the original is the look and feel; the information architecture is mine. In 2026 I took load-to-load from problem statement through research to implementation.

Problem

Build us the Excel sheet — except it doesn’t lose state when someone closes the tab, and it survives the ~500 trucks we actually run.

That was the brief I inherited — less ”build us a TMS” than a demand to beat a spreadsheet the team trusted. The hard part is temporal: the same schedule gets read across three different slices of time.

  • Planning — one to three days ahead, choreographing which truck will be empty in Hannover on Thursday morning.

  • Matching — the next few hours, watching for trucks coming free in time to pick up an offer that drops in the next 90 minutes.

  • Live dispatch — driver just called, truck broke down, the planned 14:00 loading is now 16:30.

Worth being precise about who did what, because it changed the design argument. When I joined, those weren’t three jobs. There were no planners, forwarders or dispatchers as separate roles — the same people did all three, switching horizon several times an afternoon. The split into named roles came later, over the years, as the client scaled and the processes hardened around specialisation.

So the question in 2022 wasn’t “three roles, three views?” It was: three time horizons living in one person’s head — segment the screen, or split it?

Problem image
Anatomy

The Schedule is one row per truck; the mechanisms around the rows are what make it survive contact with the actual work.

  • Scope filterMy trucks / My group / All. Personal scope without breaking shared awareness; All is one click away.

  • Inline incident notes — free text on each truck row, visible to everyone. Examples straight from the screen: “Driver forgot to clear the cargo through customs”, “Warehouse fire”. Social translucence: whoever writes “warehouse fire” on row 47 doesn’t have to call the person working that lane — they see it on their next pass.

  • Row expansion — full timeline, map, driver contact, cargo manifest, countdown to the next critical event, all one click deep, so the row itself stays scannable.

  • “Mark as a mess” — a one-tap flag meaning “this one is on fire, watch it”. The label is the crew’s own slang, not a neutral “Report issue”, and that’s why it gets used: it matches how they actually talk about a truck going wrong.

  • Color-coded badges by group, contract type, and state — pre-attentive processing, so someone scanning dozens of rows finds their subset before reading a single word. Colour is never the only carrier: every badge holds a text label and most carry an icon as well, so a row still reads for anyone who can’t separate the hues (WCAG 1.4.1).

In 2026 the EU tachograph law forced new fields onto every row — continuous driving time, accumulated rest, break countdown — because committing a truck to a 600-km job tomorrow means seeing at a glance whether the driver has the hours. The screen keeps getting denser as the business adds metrics; a large share of the iteration on this screen is that work.

Section image

Today / Tomorrow / Later tabs, scope filter, incident notes, one row expanded.

Key decisions

Four decisions — one I inherited, one I inherited and rebuilt, two I owned.

Decision 01 · The Schedule

One schedule with Today / Tomorrow / Later tabs — not three separate views

The team built one screen, segmented by when a truck’s activity lives, and let people pick the horizon their current task needed. The decision came from the client-side ops manager and triangulated against three sources:

  1. Business: shared awareness was the original promise. Whoever commits tomorrow’s truck needs to know someone is currently rerouting it.

  2. Research: the work moved between horizons faster than any view boundary could keep up with — the same person planned, matched and firefought within the same hour. Splitting the screen by task would have fought the way the work was actually done. When the named roles did appear years later, cross-coverage between them kept that argument true.

  3. Behavioral baseline: the spreadsheet they were leaving was a single tab everyone wrote into. Pave the cowpath — not because the cowpath is optimal, but because the cost of breaking it has to be weighed against the gain.

Decision 1 image
Why

One person covering all three horizons (research) + the single-tab habit that was actively working (behavioral baseline).

Trade-off

Tabs reduce cognitive load at the cost of cross-horizon visibility: “is this truck free at any point in the next 48 hours?” costs a tab-flip per horizon. The tabs were the client's call, made before I joined the decision. Today I would not reverse it, but I would add a cross-horizon panel for the power-user moments: an addition that respects the original decision instead of replacing it.

Decision 02 · Market View

Dozens of fields per row, readable at scale — and three matching modes, because there are three mental models

Market View pairs offers with trucks. Everything on this screen comes from outside: offers from clients, plus offers pulled from freight exchanges like TimoCom. There is no internal freight in this system.

Three modes ship today, in one segmented control:

  • Trucks ↔ offers: algorithmic pairing with margin, distance and compatibility. The default for matching work.

  • Offers only: no pairing at all. Some users hold their own model of which truck takes what, and the algorithm's suggestions are noise to them.

  • Loads ↔ loads: the 2026 addition (Decision 03), pairing loads with each other instead of pairing a truck with an offer. An offer is a load too; it just arrived from a client rather than sitting free in the pool.

Three modes because there are three mental models, and forcing one on everyone would have cost the users who think differently.

The look and feel of this screen predates me. The information architecture is mine: which fields matter, what reads first, how a row is ordered and grouped. That is mostly a density problem. Faced with dozens of fields per row, the common moves are hiding fields, which kills scanning, or expanding row height, which kills comparison. Neither works in ops software. The third option is micro-typography: weight, colour, spacing, monospace against proportional, pre-attentive cues that let the eye find the signal in a wall of numbers.

The iteration loop across 2023–2025: the business adds a column, a margin breakdown or a new contract type, and the view stops working at a glance. I propose two or three layouts, we look at them on real screens with real operators, the winner becomes the new baseline. Repeat.

Decision 2 image
Why

Users compare rows in seconds at full density. The client’s own benchmark: ~25 trucks visible without scrolling, eye-strain past 40 — so progressive disclosure is off the table and row height is fixed at 56 px.

Trade-off

This density has no room for casual users; the screen assumes training. It also assumes the users we watched are typical. The client, a former forwarder, opened the door to real users and we shadowed them, but he stayed the first voice on most calls about this screen.

Decision 03 · Load-to-load

A five-state route taxonomy before any screens — and a mode, not a tab

The 2026 capstone: mine from problem statement through research to implementation. The trigger: EU tachograph regulation — from July 2026, tachograph obligations (and with them driving-time rules: 4.5 hours maximum continuous driving, a mandatory 45-minute break, daily and weekly rest caps) extend to vans of 2.5–3.5 tonnes in international transport. Ad-hoc routing — stringing loads together in your head over an afternoon — stops being viable.

The idea wasn’t mine, and it wasn’t the client’s. It came from the planners, who had been pairing loads into routes in Excel, holding them mentally, committing at the last minute — and describing empty approach runs of 400–500 km where 100 km was possible (user-reported, not instrumented). The client formalized the request; I ran the research and designed the system. Five documented sessions over six weeks: problem framing → object taxonomy → IA → design review.

The hard work wasn’t the screen — it was the conceptual model. A route can exist in multiple states between “two loads I’ve mentally paired” and “truck is leaving the yard”. I designed five: free load (no truck commitment) → draft route (multi-load, editable, shared pool; a load can sit in multiple drafts) → finalized free route (non-editable, ready for truck assignment or external sale) → soft pin (Reserved — on the schedule, margin computed, protected from other users’ edits, the planner can still bail) → hard finalize (Assigned — leaves the module forever). Each state has different edit permissions, deletion behavior, and cascade effects when a load is cancelled.

IA: load-to-load lives inside Market View as a third mode in the segmented control — not a separate tab. People flip between matching trucks-to-offers and loads-to-loads within the same minute; it’s the same kind of work — pairing — and only what they’re pairing changes.

Two principles from the meeting notes: “No margin shown without a truck — hypothetical margin = misinformation” (don’t show data that misrepresents state), and “you can only match inside a draft if you own one of the loads” — error prevention enforced at the permission layer, not the UI layer.

Decision 3 image
Why

In operational software, the data model is the design. Get the entity lifecycle wrong and no amount of UI polish will save you. And Reserved exists because the tachograph rules push final acceptance later — from the notes: “we accept a route as final later than we do today.”

Trade-off

Segments are less discoverable than tabs — a new user might miss the third segment for a week (mitigated with onboarding and a text label, Routes, not an icon). And the model has two layers I kept trying to flatten: five object states underneath, three statuses on the schedule view (free / reserved / assigned). Three revisions in, the client-side PM and a developer defended the three view statuses each time — the right number of states is the number the work actually has.

Decision 04 · Load-to-load

The feature users asked for — and the sentence that killed it

The research sessions killed one of my proposals, and it’s the best thing that happened to the design.

Planners raised a real fear: route-swapping under pressure. One of them described it in review — he suddenly has to swap a truck (an emergency pull-off), doesn’t remember the truck’s number; where does he quickly find the route he already approved? He was afraid the route was simply lost. My answer was a fourth tab, “routes in progress” — a dedicated place for in-flight routes.

Two developers pushed back with an argument I couldn’t beat: the schedule data behind it is the most heavily-trafficked resource in the system, and a fourth tab would have been a fourth live-refreshing copy of it. So the design rerouted toward filter-based lookup — the fear gets answered by a fast, specific search path, not a new surface. The tab itself stayed specced “in reserve”, without live refresh, buildable if lookup proves insufficient in production.

Sometimes the right answer to a user request isn’t the feature they asked for — it’s the need underneath it, served by a cheaper mechanism.

Decision 4 image
Why

The user’s fear was real; the requested feature was one of several ways to answer it — and the only one with a standing infrastructure cost.

Trade-off

Filter-based lookup is a workflow to learn, not a place to see. If route-swapping turns out to be a many-times-a-day event, the reserved tab gets built — the design keeps that door open instead of pretending the question is settled.

Outcome

Four years in production as the primary screen of the dispatch floor; load-to-load ships later in 2026.

~500

trucks the schedule carries

180k+

orders a year matched on these screens

30s → 5s

to judge an incoming offer, client's figure

The Schedule and Market View have remained the centerpiece through driver-app integration, carrier portals, back-office workflows, and a tachograph-driven regulatory shift. The client puts the time a forwarder needs to judge an incoming offer at 30 seconds before this screen and 5 seconds after — their measure, not mine, and the one number they volunteered about this view.

Load-to-load is pre-launch, and its layout is in testing as I write this: two variants — compact, keeping the existing Market View visual language and Excel-like density the users asked for, and a new, more spacious view with a clearer draft-vs-finalized hierarchy. My hypothesis, written down before testing: users will prefer compact, because they’re attached to the density they know. And a kill criterion, documented up front: if users say “we can’t work with this, give us back the old one”, compact wins by default — no designer-ego defense, no iterating on the new view three more times.

Beyond the layout test: a documented research process, an object model that survived the developers’ stress-testing, and a feature moving toward release. I’ll know a few months after launch whether the kill criterion saved us or the new view earned its place.

Outcome image
Reflection

Three things I'd do differently — one per era of this app.

The Schedule tabs. I’d add the cross-horizon view: four years of watching this work has shown me the minority of moments where a power user needs one truck across all time — and right now they’re flipping tabs to assemble the picture.

Market View research. The shadowing did happen — the client, a former forwarder, put us in front of real users and we watched them work. I’d do it earlier and more often. Regular half-days next to someone working this screen in my first year would have shortened my domain-learning curve and given me a read on the domain that didn’t arrive through the client’s opinions first.

The taxonomy lesson. I came in with a designer’s instinct to simplify the load-to-load states. The team taught me that some complexity is irreducible.