Skip to content

Get in touch

Send me a message, or book a time to talk.

tengariya@gmail.com

Warp TMS

Freight software for booking shipments, following them and handling the invoice

The top of the TMS dashboard. The headline reads 4 need your attention, with a line saying to start with Los Angeles to Dallas and a switch for the order. Four shipments sit on one timeline with a line for now, and below that is a larger card for the first shipment with its time left.
The dashboard when you open it.
The dashboard on a phone: the headline 4 need your attention, the order switch, and the timeline of four shipments with its legend underneath.
On a phone.

People mostly open a TMS when something has gone wrong. I designed the TMS Warp gives the companies that ship with it, from the first screen they see to the AI features that now take some of the work off them.

Role
Product designer. I was the only designer on it.
Company
Warp, a freight company in Los Angeles.
Team
Daniel Sokolovsky, co-founder and CEO, and Troy Lester, co-founder and CRO, who set the direction with me. Richard Marks, Head of Transportation at DoorDash, and his operations team used the first version. Dennis Mullahy, formerly of Macy's supply chain, advises Warp's board.
Status
In use.
Outcome
Released in beta to more than 1,100 companies. After two months, about 80 percent of shipment orders came in through it.

What a TMS is

TMS stands for transportation management system. Say a company needs to move a pallet from one city to another and books it with Warp. After that they get a login to the TMS, and that's where they see their shipments, their lanes, their invoices and their carriers, and where they book the next one. Warp gives it to them for free.

TMS software has been around for decades, mostly as places where you fill in a form and get an answer back. The people who open ours work at the companies that ship with Warp: someone in scheduling, someone in finance, sometimes a director of transportation. They're at a desk most of the day and they're not technical.

Someone shipping with us is handing over something that could be worth multi-million dollars, so they want to see where it is the whole way. If a shipment is on time, though, there's nothing to look at. People open a TMS when a shipment is late, or stuck, or something about it seems off. I learned that from working with the operations team at DoorDash, including their Head of Transportation, Richard Marks, and from Dennis Mullahy, formerly of Macy's supply chain and an advisor to Warp's board. I also spent time at Warp's warehouse in Los Angeles, watching the operations team do their work.

The first version

At Warp we didn't start with user interviews. We started with what the founders and I thought the problem was, shipped a first version fast, then went to a customer and asked. So the first version of the TMS went to DoorDash. Richard Marks and his operations team used it for a while, and then we got on a call where they walked us through how they were using it and where it got in the way.

Three things came out of that call.

The first version, recreated with sample shipments.
  1. The tableOverdue, but by how much?

    The first version's shipments table, three rows: P-77310, Chicago to Atlanta, delivery Jun 8, 2026, marked Overdue; P-77201, Detroit to Cleveland, delivery Jun 7, marked Exception; S-48142, Miami to Orlando, delivery Jun 9, marked Overdue. Nothing says how late any of them is.
    The first version's shipments table, three rows: P-77310 Overdue, P-77201 Exception, S-48142 Overdue. Nothing says how late any of them is.

    The first was the table of shipments. It said a shipment was overdue but not by how much. Two hours late might need nothing, and two days late might need someone on the phone right away. To find out which it was, you had to click three times.

  2. The coloursWhich one first?

    All nine rows of the first version's table with their status badges: Booked, Exception, Pending, At risk, Overdue, Exception and Overdue in reds and pinks of similar shades, and two In transit in yellow.
    All nine shipments of the first version with their status badges: Booked, Exception, Pending, At risk, Overdue, Exception and Overdue in reds and pinks of similar shades, and two In transit in yellow.

    The second was colour, and that one was my call. I'd used a lot of reds in similar shades, and when everything is a shade of red you can't tell which shipment to deal with first. I got that wrong.

  3. The dashboardWhich three?

    The first version's row of counts: Total shipments 34, In transit 4, Delivered 23 and Exceptions 3, each with a change against last week.
    Two of the first version's counts: Delivered 23 and Exceptions 3, each with a change against last week.

    The third was the row of numbers on top: total shipments, in transit, delivered, exceptions. A count of three exceptions doesn't tell you which three, so you clicked through again to find them. I hadn't expected people to want the problems right at the top, but that's what they wanted, and the other counts they'd look at now and then.

What the first screen should show

So what should it show first? I came up with three options.

  1. The first was what I'd already built, the counts.

  2. The second was to ask each customer what they'd like to see first, which is one more question during setup. When we went through that one with the team, they pointed out that it would make onboarding longer, and that was fair. One more step before anyone sees anything, and a longer signup could lose new customers. I dropped it.

  3. The third was to show the shipments that have a problem, with the reason and how late each one is.

I went with the third. How late a shipment is tells you what to do. An hour late is probably traffic or weather. Two days late is worth a call. So the screen opens on the shipments that need someone, and it names the one to start with.

A screen full of trouble can make people panic, so red is only for the shipments that are really exceptions, and how late goes next to it in words. Everything else stays plain. It also means there's no personal view: everyone sees the same order. If groups ever need a different first screen, I'd do it as a saved view and not as a question on the first run.

There's a switch for the order. The list starts with the ones you can still save, and if you flip it the latest ones come first. When nothing is wrong, the headline says so and the card gets shorter.

The top of the dashboard: the headline 4 need your attention, a line saying to start with Los Angeles to Dallas, and the order switch set to Can still save.
The top of the dashboard on a phone: the headline 4 need your attention, a line saying to start with Los Angeles to Dallas, and the order switch set to Can still save.
The same headline with the switch set to Hours late. The line now says to start with Detroit to Cleveland.
The same headline on a phone with the switch set to Hours late. The line now says to start with Detroit to Cleveland.
The same headline, ordered two ways.
The dashboard when nothing is wrong: the headline You're all clear, and under it a bar with a green tick saying there are no exceptions, overdue deliveries or overdue pickups right now.
The dashboard on a phone when nothing is wrong: the headline You're all clear, and under it a bar with a green tick saying there are no exceptions, overdue deliveries or overdue pickups right now.
When nothing is wrong.

One timeline for all of them

Once the first screen was going to list the shipments with problems, I had to decide how to draw them. I designed four versions.

One had a tab for each shipment. It looks fine on a desktop, but on a tablet or a phone you'd need a separate layout. In another, each shipment had its own timeline, but a timeline is the same for every shipment, so repeating it only made the page taller. The third had no timeline, and then you have to read every row to find the one that's furthest behind.

Tabs

The version with a tab for each shipment: Los Angeles to Dallas, Detroit to Cleveland, Chicago to Atlanta and Miami to Orlando, each with how late it is and a short bar. Under the tabs, the open shipment, Dallas appointment requested, not confirmed, 31h left, with its own timeline from Jun 9 to Jun 12.
The tab version on a phone: the headline 4 loads need you, two of the four tabs, and under them the open shipment with 31h left and its own timeline.

A timeline each

The version where each shipment has its own timeline: the headline 4 need you now over a scale of days, then a card for Los Angeles to Dallas with its own bar, 31h left, and under it the heading of the next group, no movement since the pickup window opened.
The version with a timeline for each shipment, on a phone: the headline 4 need you now, a scale of days, and the first card with its own bar, 31h left.

No timeline

The version with no timeline: the headline 4 loads need your attention over a numbered list. 01 Los Angeles to Dallas, 31h left; 02 Detroit to Cleveland, pickup not on record; 03 Chicago to Atlanta, 2d 7h late. To find the furthest behind you read each row.
The version with no timeline, on a phone: a numbered list, 01 Los Angeles to Dallas, 31h left, and 02 Detroit to Cleveland, pickup not on record.

One timelineChosen

The version with one timeline for all four: S-48231 31h left, P-77201 1d 22h late, P-77310 2d 7h late and S-48142 4h late share one scale with a line for now at 3:00 PM, so the longest late line stands out. Under it, the first shipment's card.
The version with one timeline for all four, on a phone: the four shipments on one scale with a line for now, and the first shipment's card under it.
The four versions, on the same four shipments.

The last one puts all of them on one timeline. It shows how late each shipment is next to the others, so the worst one is easy to spot without reading anything. You scan it. A line marks now. A solid line is how late a shipment is, a dashed one is the time left, and a hatched one means it hasn't been picked up yet.

Four shipments on one timeline with a line for now. One has a hatched stretch for no pickup yet, one has a solid line running left for how late it is, one has a short line late, and one has a dashed line running right for time left. The legend names the lines: Late, Time left, No pickup yet.
The same timeline on a phone: four shipments with a line for now, a hatched stretch for no pickup yet, solid lines running left for how late they are, one dashed line running right for time left, and the legend Late, Time left and No pickup yet.
The timeline.

How many fit? Warp's data analyst went through about a million customer shipments, and the most with an exception at the same time was six. So the timeline holds up to six. This screen shows four.

Under the timeline each shipment gets a card, and the first one is bigger than the rest because the question on the page is which one first. The count in the headline is the largest thing on the screen, so the eye knows where to start.

Five fields for a price

The TMS we tested against asked for 19 fields before it showed a price. The price is when someone decides whether to ship with us or with another carrier, so that's a lot of typing before the decision.

We cut it down. Besides where and when, ours asks for five things: how many items, the total weight, and the length, width and height, because those five are what Warp's pricing uses. The prices come back as a list with the cheapest one marked.

Two rows of boxes. The first row has 19 boxes, labelled 19, for the TMS we tested against. The second row has 5 boxes, labelled 5, named items, total weight, length, width and height, for ours.

Fields before you see a price: 19 in the TMS we tested against, 5 in ours.
The New shipment panel: pickup and delivery ZIP codes, a pickup date, and one item with quantity, total weight, length, width and height, and a green Get rates button.
The New shipment panel on a phone: pickup and delivery ZIP codes, a pickup date, one item with quantity, total weight, length, width and height, and a green Get rates button.
Our quote form.
Then the rates, cheapest marked.
Then the rates, cheapest marked.
The quote panel's rates list: four rates, the cheapest marked Lowest, with the filter set to 3rd-party.
Then the rates, cheapest marked.
The quote panel's rates list: four rates, the cheapest marked Lowest, with the filter set to 3rd-party.
Then the rates, cheapest marked.

When we do not have the data

In freight, a wrong number is more dangerous than a missing one, so a few rules follow from that.

If we don't have something, the screen shows a dash, not a guess and not a zero. A dash in the carrier column means no carrier has been assigned yet, and a dash in the delivery date means there isn't one. People can call someone to find out.

If the TMS can't reach Warp's system, it says so and offers to try again. It doesn't fall back to an older copy, because someone might act on a status that has already changed.

Forms start empty. Nothing is filled in for you, because a shipment booked for the wrong place or the wrong day is expensive to fix.

Charts do the same. A month with no data is a gap, and hovering over a month shows its value and how many shipments it's based on.

A table of shipments. In the last row, which needs a carrier, the carrier, delivery date and cost cells each show a dash.
The delivery date and cost columns of the shipments table. In the last row, which needs a carrier, the delivery date and cost cells each show a dash.
A dash where there is no data.
A dashboard that could not load: the message Couldn't load your dashboard, the line We couldn't reach Warp, and a Try again button.
A dashboard on a phone that could not load: the message Couldn't load your dashboard, the line We couldn't reach Warp, and a Try again button.
When it cannot reach Warp.
A line chart of average cost per shipment by month, with a card open on March 2026 showing its value and the 28 shipments it is based on.
Part of a line chart of average cost per shipment by month, with a card open on March 2026 showing its value and the 28 shipments it is based on.
Hovering over a month shows what it is based on.

How it moves

Most software like this doesn't move much. I wanted this to feel a little alive, without slowing anyone down. Typing, search and moving between pages are instant, because people do those all day. What moves is the dashboard settling in once when you open it, a status changing, a booking being confirmed, and charts drawing in.

When you open a shipment, its number moves from the row up into the page heading, so you can see where you went.

Opening a shipment.
Opening a shipment.
Three frames of a shipment opening. Frame one: the list of shipments with the row for S-48205.
Frame two: the shipment page arriving.
Frame three: the shipment page, S-48205, Austin to Houston.
A shipment opening on a phone, frame one of two: the Austin to Houston shipment's card in the list.
Frame two: the shipment page, S-48205, picked up, Austin, TX to Houston, TX.
Opening a shipment.
Confirming a booking.
Confirming a booking.
The booking confirmed: the What you booked summary.
Confirming a booking.
The booking confirmed on a phone: the shipment's tracking number, its order number and what was booked.
Confirming a booking.

Where I used AI

I didn't plan to put AI in this at first. A lot of the people who use a freight TMS aren't very tech savvy, they're used to filling in long forms, and I didn't want to overwhelm them.

I also read what people in logistics say about AI in public forums. Mostly it wasn't hostile. It was people asking how they're supposed to trust the data, or trust it when they're auditing something. And whenever an AI gives you an answer, the first question is whether it's even real and where you can see the actual data.

So the question became what AI could do that solves a real problem for the person at the desk, without forcing anyone to use it. The next chapters are my answers. They're live at Warp now, and each one either shows where its answer came from or says what it can't do.

Why a load is here, and what to do about it

Back to the card at the top of the dashboard. Every shipment on that list says why it's there, straight from the record, and what to do next. This one reads: Dallas appointment requested, not confirmed. High winds closed a highway near Needles. No revised arrival on record. The next move is to confirm with the receiver before the deadline. The first priority was always to show what needs an operator's attention and what's going wrong with it, so the reason is on the card. Whoever opens the product can see it right away, see how late the shipment is, and make the call on whether to do anything.

The two links at the foot of a shipment's card: Why is it here? and Draft the update.
The two ways in.
The Ask panel open beside the dashboard, after the question Why is S-48231 here? It is titled Why S-48231 is on the list, shows Los Angeles to Dallas with its progress, and under Deadline still ahead lists three checks with a tick each: an open exception on its record, a deadline on it that is still ahead, and the Dallas appointment requested, not confirmed, the first two with the value from the record under them.
Why is it here?

I'd noticed the AI was there but you couldn't get to it in one click, so each card carries two ways in. Why is it here? opens Ask beside the page and shows the checks that put this shipment on the list, each with what the record says. Draft the update is the other one; that's next.

Shipments due tomorrow that haven't had an event since pickup get their own group, Tomorrow. It lists them as facts, like no event since pickup, one day ago, or both appointments requested, not confirmed. It doesn't try to predict which ones will be late.

A group titled Tomorrow with three shipments on a small day scale from 6 AM to 6 PM. The first, a pickup from Phoenix to Los Angeles at 8 AM, reads Both appointments requested, not confirmed. The other two are deliveries, Denver to Kansas City at 2 PM and Seattle to Denver at 4 PM, each reading No event since pickup, with how many days ago.
The Tomorrow group on a phone: a pickup from Phoenix to Los Angeles at 8 AM reading Both appointments requested, not confirmed, and deliveries from Denver to Kansas City at 2 PM and Seattle to Denver at 4 PM, each reading No event since pickup, with how many days ago.
Tomorrow, listed as facts.

What to tell people

The panel What to tell people. Under Not known: Revised arrival, not on record, and the Dallas appointment, requested, not confirmed, with the requested window on a small time line and the arrival as a dash. Under Known: four facts on the page, each linked.
The update starts with what isn't known.

A shipment page can tell you what's going on, but then somebody has to tell the customer, the receiver and the carrier. This is a small quality-of-life thing. If a shipment is two hours late or ten, the TMS checks the details in the record and drafts the message with the exact details.

The first version wrote a summary. A summary can blur what's known with what isn't, like promising Thursday when Thursday was only the window we'd asked for. The feedback we got was that it wasn't much use, so I changed it.

Now the update starts with what's not known yet, like revised arrival, not on record. Then what is known, each item linked to its record. Then a draft for each person: an email for the customer, a call script for the receiver because there's no email on file, and a message through the carrier's dispatch. Anything Ask wrote carries a small grey Written by Ask, so you can tell it from what came straight from the record.

A card for a shipment from Miami to Orlando under a heading Picked up, now past due. It reads Status says Arrived, 4h late, no arrival event, with a next move, Get the arrival time from Estes before you tell the receiver. Under the card, in small grey text, a line reads Next moves written by Ask.
A card on a phone for a shipment from Miami to Orlando under the heading Picked up, now past due: Status says Arrived, 4h late, no arrival event, and the next move, Get the arrival time from Estes before you tell the receiver. Under it, in small grey text, Next moves written by Ask.
The mark, under the next moves.

It never sends anything. You copy the draft and send it yourself, because people only send AI text after they've checked it.

Paying invoices

The pay review is on the invoices page. Invoices in freight have a lot of small things in them, like terms that say one thing and a hidden charge that says another, so the idea was that AI would scan them and tell you if something's wrong. A verdict like "AI reviewed 42 invoices, no errors found, 98 percent confidence" doesn't add up. Forty-two checked, nothing wrong, and only 98 percent sure? That's more of a design problem than a model problem.

So the page doesn't tell you how many it scanned. It shows what it checked and what it didn't. It checked delivery status, proof of delivery, extra-charge evidence and line totals. It didn't check payment terms or the booked rate, because every open invoice just reads Due with no value and there's no rate confirmation to compare against. Behind that, open invoices are grouped by what the records show, and the first group is orders that haven't been delivered yet. Why would you clear an invoice for an order you never got? That was an easy call.

The open invoices list. Two lines say what was checked, delivery status, proof of delivery, extra-charge evidence and line totals, and what was not, payment terms and booked rate. The first group, Not delivered yet, holds eight invoices, and the first of them has a flag reading Liftgate at delivery, proof of liftgate use not on record.
The open invoices list. Two lines say what was checked, delivery status, proof of delivery, extra-charge evidence and line totals, and what was not, payment terms and booked rate. The first group, Not delivered yet, holds eight invoices, and the first of them has a flag reading Liftgate at delivery, proof of liftgate use not on record.
The open invoices list on a phone. Checked: delivery status, proof of delivery, extra-charge evidence, line totals. Not checked: payment terms, booked rate. The first group, Not delivered yet, holds eight invoices, and the first of them has a flag reading Liftgate at delivery, proof of liftgate use not on record.
What it checked, and what it didn't.

A flagged charge says what's missing, like proof the liftgate was used, and opening it shows what was billed, what was agreed and the evidence. It never says ready to pay. The screen shows the facts and the person decides. That's what you want in front of you when you're paying for something.

What changed in spend

On the spend page there's a button next to the month-over-month figure that says Explain. It opens Ask beside the page with the question already asked. It's the same Ask, not a second assistant. You ask what changed in spend from one month to another and the data comes back straight away, not a paragraph about it.

Explain, beside the figure.
The spend page with Ask open beside it: the change from April to May carrier by carrier, and April and May outlined on the chart.
Explain, beside the figure.
The spend figures: Spend, Month over month, Avg per order and Outstanding. Month over month reads minus 9.9 percent with a link beside it that says Explain, and under it the two months being compared.
Two of the spend figures: Spend, and Month over month, which reads minus 9.9 percent with a link beside it that says Explain, and under it the two months being compared.
Explain, beside the figure.
A bar chart of monthly spend. The bars for April and May are outlined, and a line under it reads April and May are outlined: the months Ask's last answer compared.
The last months of a bar chart of monthly spend, December 2025 to June 2026, with the bars for April and May outlined.
The two months it compared.

The answer is worked out from the records, carrier by carrier, from one month's total to the next. It names the two months it compared, so you know what the figure is measured against. Arrows show whether each carrier went up or down. There's no red or green, because spend going down isn't good or bad by itself. It can just mean fewer shipments. On the chart, the two months it compared are outlined.

It also doesn't say why spend changed. It shows what moved. My first rule for the biggest change named the wrong carrier, because carriers moved in opposite directions, so now it names the biggest drop and the biggest rise.

The Ask panel after the question Why did spend change from April to May. It shows minus 9.9 percent, May against April, the two monthly totals, and a list by carrier with an arrow and the change for each: XPO and R plus L Carriers down, Estes, ABF and Old Dominion up, Saia down.
The change, carrier by carrier.

Ask

Ask is the chat. You open it from the top bar, or from the card, shipment or carrier you're looking at, and it opens beside the page, so the answer and the record are on screen together.

Ask, answering from the records.
The dashboard with Ask open beside it. The question is What's late right now. The answer says 4 shipments need your attention, 2 exceptions, 1 overdue delivery and 1 overdue pickup, lists the four shipments with how late each is, and has a link to the full list. Under it a line says From your records as of a date and time, and a follow-up reads Why is S-48231 here?
Ask, answering from the records.
The Ask panel after the question What's late right now. The answer says 4 shipments need your attention, 2 exceptions, 1 overdue delivery and 1 overdue pickup, lists the four shipments with how late each is, and has a link to the full list. Under it a line says From your records as of a date and time, and a follow-up reads Why is S-48231 here?
Ask on a phone after the question What's late right now. The answer says 4 shipments need your attention, 2 exceptions, 1 overdue delivery and 1 overdue pickup, and lists the four shipments with how late each is, a link to the full list, the line From your records as of a date and time, and the follow-up Why is S-48231 here?
Ask, answering from the records.

It doesn't answer in sentences. Ask what's late right now and you get the shipments themselves, each one a link to its page. That's on purpose. Writing the answer is where a language model goes wrong the most. It tends to give cheerful, exciting answers, and with a real shipment on the road, that can cost someone a lot of money. A chat is always limited, too. I eventually want to go where the data is, like brainstorming a design in chat and then going back to Figma. Rows let you act right where you're looking.

The Ask box with a chip above it reading About S-48231, Los Angeles to Dallas, and the prompt Ask about S-48231.
It knows which shipment you came from.

Every answer says when it was true. If it can't answer, it says so and lists what it can. Ask it to pay or send something and it says no. The only thing it will write for you is a shipment's update.

  1. The Ask panel after the question whats late rn, answered with the same four shipments.
    Typed the short way.
  2. The Ask panel after the question How much did we spend with XPO last quarter. It asks Did you mean spend with XPO, says it doesn't total spend by quarter, and offers three questions it can answer.
    A near miss, asked back.
  3. The Ask panel after the request pay all the open invoices. It says Ask can't answer that from your records yet, that it can't pay, send, book or change anything but can draft a shipment's update, and lists questions it can answer.
    Asked to pay, it says no.

To test it, another AI that had never seen the code wrote 50 questions an operator might ask. The first version answered in sentences, and only 24 came back right. That's why it stopped answering in sentences. After that, 40 of 50 did.

I see it as a help and not something people have to rely on, a quality-of-life thing.

How it went

I counted orders and not logins. Logins show how many people signed up, not how many are using it. Counted that way, about 80 percent of shipment orders were coming in through the new TMS after two months. We released it in beta to about half of our existing customers, more than 1,100 companies, and it's in use.

All work