← All work

/  Case study 01

City Hive  ·  B2B e-commerce  ·  Shipped 2025

CSV order upload for beverage wholesale buyers

Upload a spreadsheet, create an order. The design problem was everything that goes wrong in between.

Company

City Hive, beverage e-commerce

Role

Product designer: reframe, UX, UI, spec, handoff

Surfaces

Merchant dashboard + storefront

Timeline

2025 · 1 week, primary sprint task

Team

Me, a dev team, 1 CS rep

At a glance

The ask

“There should be an API end point that allows authenticated users to send an excel listing of products and to have cart created and ready for them. Apparently a common use case for bars and restaurants.”

— The original request, and so a journey began

Time to build a 100-item order

Before: one product at a time

58 min

After: upload, map, confirm

2–10 min

How I measured it: timed a 100-item order built by hand on the dashboard, then timed real files through the upload flow, from the cleanest (2 min) to the messiest (10 min).

Outcome

200+

distributors got the upload flow on the merchant dashboard. Storefront designed and specced, not yet released.

01

Context

The order already exists. It just lives in a spreadsheet.

Exported files are messy. An endpoint answers a messy file with an error array, which leaves someone holding a 167-line order and no idea which lines failed or what to do about them.

Key insight

I treated the upload as the easy half. The design problem was what happens to the rows that don't match, and whether someone can finish their order anyway.

02

Flow

Four steps, on purpose

The established pattern: file, map, validate, submit. Reusing it was deliberate. An import flow is the wrong place to be original.

Two entry points, one resolution path

Everything after the file is parsed is shared.

Merchant

From inside an order

Customer

Upload cart page

→

Cart has items?

Keep or remove

→

Map columns

Barcode, quantity, unit

→

Match catalog

By barcode

→

All matched

Nothing to resolve

Some issues

Missing, multiple, OOS

1

→

Review and fix

Choose or drop items

None matched

Dead end

→

Fix and retry

Export failed barcodes

2

→

Cart

Ready to check out

1

Valid isn’t resolved

A barcode can match and still be ambiguous (Tito’s comes in seven sizes) or out of stock today. Neither is a data error, so a format check can’t catch it.

2

Recovery is a loop, not a repair

You can’t edit a spreadsheet into stock. Export the failed rows, fix them, upload again and choose Keep, so the rows already in the cart stay.

Merchant entry

Customer entry

Recovery

Result

03

Interface

The same flow, twice

City Hive runs a strict design system that differs between buyers (Storefront) and merchants (Universal Dashboard). This design needed the same UX implemented on both platforms.

1

File: upload cart

Cart conflict is resolved before parsing. A merge you can't see is worse than a question you have to answer.

Dashboard

Storefront

2

Map: sort the file

Export headers are arbitrary (Item UPC, Order Qty, Pack), so mapping has to be manual. Knowing when you're finished doesn't. Submit stays disabled until the required Barcode field has a home.

Dashboard

Storefront

3

Validate: solve issues and approve

Three things can go wrong, and they're not the same thing.

Matches nothing

A file problem. Export those rows and fix them.

Matches several sizes

A choice. The buyer picks the right product.

Out of stock

Not wrong at all. It's just unavailable today.

Dashboard

Storefront

Dashboard · nothing matched

Storefront · nothing matched

4

Submit: view updated cart

Back to where you started, with the cart filled. The merchant lands in the order they were already building; the customer lands in a cart ready to check out.

Dashboard

Storefront

04

Walkthroughs

Watch it run

Screen recordings of both flows, end to end: file, map, validate, submit.

Merchant dashboard

Shipped

Storefront

Designed, not yet released

05

What shipped

Merchant dashboard first

Storefront was specced and designed, not yet released. On the merchant dashboard, usage shows buyers adopted it, and two numbers show whether the recovery design held up.

What the numbers showed

First-try match rate

41%

of uploads matched every row on the first try. The other 59% hit at least one problem row, so the review step carries most uploads.

Recovery loop

74%

of rows that failed on an earlier upload now go through successfully. Failed rows aren't a dead end; recovery works.

Monthly usage

220

orders placed through the CSV flow in the first month measured, counted with a production database query.

06

Reflection

What I'd take from this

Do differently

Time the typical file, not just the extremes

I timed the best and worst files, 2 and 10 minutes against a 58-minute manual baseline, but never a typical one. A median across real uploads would have turned the saving into one number instead of a range.

Learned

Design the failure path first

Only 41% of uploads matched on the first try. A flow built for the happy path would have failed most buyers. The review-and-retry loop is what made the feature work, and 74% of failed rows now go through.