Carrier portal: the user who doesn’t work here
Every other TMS user is paid to learn it. The carrier isn’t — so the portal had to earn a login from someone who’d rather send an email.
Web
B2B
Logistics
Role
Sole Product Designer
Primary user
Carriers — small transport firms, 3 to 15 trucks
Timeline
2024–2026
Status
Live
Methods
Client Workshops · Stakeholder Interviews · Constraint Mapping · Information Architecture · Interaction Design

One carrier’s orders, sorted by what they still owe us — not by date.
Overview
The carrier is the only TMS user who doesn’t work for the client. Everyone else is on a payroll that includes learning the system. The carrier is a stranger with three trucks and no reason to log in.
The TMS has six user groups. Four of them, forwarders, dispatchers, back office and drivers, work for the client or drive for the people who do. Design for them is a negotiation inside one company.
Carriers are different. They are separate businesses, usually small: an owner with three trucks who runs sales, routing, payroll and paperwork himself, and who works with several forwarders at once, each with their own portal. The TMS is one of maybe four systems he is obliged to use, and it is not the one that pays his mortgage. It is the one he has to get through so that the one that pays his mortgage releases the money.
That changes what “good” means. For a dispatcher, a dense screen with fourteen columns is a good screen; it is their whole working day and density beats clicking. For a carrier, the same screen is a tax. He logs in when a driver hands him a stack of scans, and he wants to be gone in four minutes.
I designed the portal as the external face of the TMS: what the carrier sees, what he can act on, and where the record stays the client's. The design question was never “what else can we show him”. It was: what is the smallest surface that still gets us complete documents, on time, without a phone call.
Problem
Carriers were sending documents the system already had, and the back office was rejecting them by text message because writing out the reason took longer than resending.
Two things move between a carrier and the client: paperwork and money. Both were leaking.
The driver finishes a run and uploads the delivery documents from the driver app. Those files land in the TMS. The carrier — the driver’s own employer — can’t see them. So he asks the driver to send the same scans to him by email or messenger, and uploads them a second time into the portal. Two people, one set of documents, twice the work, and no one in the chain knows whose copy the back office is actually looking at.
On the other side, the back office reviews those documents and rejects some of them. There was no place in the flow to say why, so rejections went out as text messages, or as nothing at all — the admin team’s own words on this were that they reject by SMS specifically so they don’t have to write an email explaining it. The carrier learns his paperwork was wrong at the point where he notices he hasn’t been paid.
Underneath both is a visibility problem the carrier can’t solve on his own. In the 2024 session on the portal, the sentence that stuck was that it isn’t obvious to him what he still has to do. Documents are stored, not organised — some carriers keep order, most don’t, and originals reach the office up to a month after the run. He has no way to tell, on one screen, which of his forty closed orders are complete, which are missing one page, and which are already on their way to being paid.
The cost of getting this wrong doesn’t land on the carrier. It lands on the client’s back office, who absorb it as email, phone calls and manual matching — because a carrier who finds the portal annoying doesn’t stop being a carrier. He just goes back to email.
The document the carrier uploads a second time because he can’t see the first one.
Constraints
The carrier is a reader of our data, not an author of it — and that isn’t a UI decision, it’s who owns the record.
Five constraints shaped everything below, and only one of them is technical.
The carrier cannot edit the fleet. Trucks are added by the client's coordinator, along with which countries each one has a road toll vignette for. The carrier can see his vehicles and flag one as ready to work, but that is a request, and operations answers it. Rates and dispatch stay on the client's side. Whatever we designed had to be read-mostly without feeling like a form dropped into a void.
One person, several companies. Carriers commonly run three to five legal entities and one person administers all of them. A login tied to a single company would have meant that person keeping three sets of credentials for the same job.
Two very different carriers. The one-owner shop with three trucks and the fifteen-truck operation where two employees split the work by vehicle group are the same user role and not the same user. The second needs grouping by truck; the first would find it noise.
The invoice flow has a legal shape. Collective invoicing had to be initiated by the carrier inside his own panel, not generated by the TMS on his behalf. The client's forwarding company issuing invoices to itself through the carrier's account is not something you can design around. Every invoice also has to clear KSeF, Poland's national e-invoicing platform, which makes a sent invoice immutable.
No direct access to carriers. The persona behind this portal is built from the back office's view of carriers, the 2024 session with the client, and what forwarders report. A carrier interview stayed on the open list.
Key decisions
Four decisions, all of them about how little to put in front of someone who doesn’t want to be here.
Decision 01 · Hierarchy
Split the orders into what needs him and what doesn’t
The portal’s main screen is not a list of orders sorted by date. It’s two groups: orders that need something from the carrier, and orders that don’t. The second group is collapsed, green, and carries an approximate payment date. The first group is the screen.
Each order in the top group shows what’s missing as a count rather than a description — three of four documents in, one to go. The reference the client used for it in the 2024 session was a fitness tracker: four of five workouts done. It’s the right reference for a reason that isn’t cosmetic. The carrier is not reading a document register, he’s clearing a queue, and a queue needs a visible bottom.
Settled orders are filtered out by default. Everything about this user’s motivation says the completed work is the part he wants gone from the screen.
Why
Two grounded signals pointed the same way: the raw role note asks for exactly this split — action-required on top, complete and green below with an approximate payment date — and the 2024 session named the failure it fixes, that the carrier can’t tell what’s still on him. Progressive disclosure is the textbook version, but the reason it’s right here is motivational, not cognitive: this user is clearing a queue, not browsing a register.
Trade-off
Hiding settled orders works against the second thing this user does: his other visit to the portal is at month-end, looking up a closed order for his accountant, and poor search on closed orders is already a named frustration. So the design buys a fast primary path at the cost of the secondary one, and it only pays off if search and filters on the settled group are good. A second cost: a completion counter turns a settlement relationship into a score, and a carrier at three of four documents through no fault of his own reads it as a grade.
Decision 02 · Visibility
Show the carrier what his own driver already uploaded
The duplicate upload isn’t a usability problem, it’s a data-model problem wearing a usability costume. The documents for an order are one set. The driver adds to it from the mobile app, the carrier adds to it from the portal, the back office reviews it. Three interfaces, one object. The old arrangement gave the carrier a write-only box and no window.
So the order’s documents became a single visible list for everyone who touches it, with the driver’s uploads already in place when the carrier opens it, each file carrying its own state: received, accepted, or rejected.
Rejected files carry a reason, and that reason is written to the carrier. This is the part that costs. Today the back office rejects by text message precisely to avoid composing an explanation; putting a required reason field in their flow adds work to an internal user in order to remove work from an external one. I think that’s the correct direction — the internal user is paid to be in this system and the external one isn’t — but it’s a transfer of effort, not an elimination of it, and it will only hold if the reasons are pickable rather than typed.
Why
The duplicate-upload loop is written down in the July 2026 portal notes as a specific observed problem: the driver uploads into the TMS, the carrier doesn’t see it, so he sends it again. Making system state visible to the person acting on it is Nielsen’s first heuristic, and here it removes a whole round of work rather than merely informing.
Trade-off
Every rejection now needs a reason someone has to produce, and the team that writes them is the one that invented the SMS workaround to avoid writing them. If the reasons end up as free text they will degrade into “wrong” within a month, so they have to be pickable, not typed.
Decision 03 · Settlement
The carrier builds the invoice, and the system stops him before he gets it wrong
Carriers invoice in batches. A collective invoice covering several orders is only usable to the client if three things hold: one currency, one calendar month, and every transport document on every order already accepted. The first two are fiscal. The third is the client protecting itself from paying for incomplete paperwork.
Two ways to enforce that. Let the carrier invoice however he likes and reject what doesn’t fit, or make the invalid combination unbuildable. The design does the second: the carrier selects orders in his panel, and the moment his selection breaks one of the three rules, the button that creates the batch is disabled with the reason shown. When it’s valid, the system issues a batch number and the total, and he quotes that number on his invoice. That number is what the automatic matching runs on when the invoice comes back through KSeF.
The batch has to be assembled by him rather than proposed by us for a legal reason rather than a design one — the client’s forwarding company can’t be seen to be issuing the carrier’s invoices. The design constraint and the corporate-structure constraint happen to agree here.
Why
Error prevention over error messages is standard, but the specific weight here is the delay: an invoice rejected after issue costs the carrier a correction to zero and a reissue, and costs the back office a manual exception. A disabled button costs a second. The batch number doubles as the key that lets the incoming invoice match automatically instead of landing on someone’s desk.
Trade-off
A blocked button is a dead end for a carrier with a legitimate reason to cross a month boundary, and he has no way to ask for an exception from inside the panel. The harder trade is the policy behind it: collective invoices issued outside the panel are refused outright and the carrier is asked to correct to zero and reissue. That is a real cost pushed onto a small business to protect our matching. The team did discuss the gentler alternative — a scheduled message telling the carrier which orders are ready to invoice and for how much — and it stayed a proposal.
Decision 04 · Authority
The carrier reports a truck as ready; he doesn’t add it
The obvious feature request is to let the carrier manage his own fleet. He knows his trucks better than the client’s coordinator does, and he’s the one who notices when a plate changes.
The design refuses it, on purpose. Vehicles are created by the client’s coordinator together with the vignette countries, because that record feeds dispatch and settlement, and a carrier editing it can break a route that’s already been sold. What the carrier gets instead is one verb: mark a truck as ready to work. That produces a request. Operations accepts or rejects it, and rates and assignment stay where they were.
The design work is in making a request not feel like a black hole. A submitted request needs a visible state and an answer, or the feature is worse than the phone call it replaces — the carrier used to get a yes or no from a person, and we’d be handing him a form and silence.
Why
The July 2026 notes are explicit that the carrier is a recipient of the client’s data and cannot add vehicles, and that “ready to work” is the one thing he can flag. Ownership of a record should sit with whoever bears the consequences of it being wrong, and here that’s the client’s operations team.
Trade-off
Every correction the carrier could have made in five seconds now costs a coordinator’s attention, and the carrier’s frustration with depending on other people’s timing — already the thing this persona complains about most — gets one more instance. Editing rights were parked as a someday, which in practice means never. If I were arguing this again I’d push for a narrow exception: let him correct his own data errors, keep him out of the commercial fields.
Outcome
In production since 2024. No launch metrics were collected, so what I can show is the structure, and the questions worth measuring.
The web portal has been in production since 2024. It was never instrumented, so I have no numbers on logins, duplicate uploads or invoices arriving without a batch number.
What I do have is two years of the portal in use. When the team designed user management for the client portal in 2026, the carrier portal's version was the reference point: its problems were named in the planning session, and the new design was built to avoid them. That is the kind of feedback you only get from something real and in use.
Four things I would measure before calling the portal a success: how many carriers log in rather than emailing the back office, whether duplicate document uploads stopped, how many invoices still arrive without a batch number, and how long a “ready to work” request waits for an answer.
The half of the portal a carrier wants to look at, and never has to act on.
Reflection
The change I would make is at the start: an afternoon with two carriers before any of the four decisions.
I designed for carriers without meeting one. Everything here comes from the client's side of the table: the back office describing what carriers get wrong, forwarders describing what carriers ask for, a session with the client about what the panel should show. That is a coherent picture, and it is also a picture of carriers as a problem to be managed. One afternoon with a three-truck owner and a fifteen-truck operation would have come before the four decisions above, and I would expect at least one of them to change.
One role was really two. The single-owner shop and the fifteen-truck operation with two people splitting work by vehicle group have different jobs, and we treated them as one user. Grouping by truck is written down as something the larger carriers need. It did not get designed. That is a scope decision I would defend under time pressure and not on the merits.
The chat question is still open. The client arrived with a solved answer, a group chat, and the useful work was refusing to start from it: asking who the actual user is when a carrier broadcasts to 500 drivers, whether a one-way announcement board would be cleaner than a conversation, and how a driver tells a company announcement apart from the operational thread that tells him where to be tomorrow. Those are the right questions and they did not get resolved. Announcements are rare, two or three a month, which is exactly the frequency at which a dedicated channel gets ignored.






