All work

E-Commerce Platform Redesign

September 22, 2026
E-Commerce Platform Redesign

Quantitative

We instrumented every field in the checkout with interaction tracking, then analyzed ~40,000 sessions:

StepEntryCompletionDrop-off
Cart review100%84%16%
Shipping info84%61%23%
Payment61%38%~38%
Confirmation38%36%2%

The payment step was the clear bleed point. Session recordings showed users repeatedly scrolling up to re-check the order total — which wasn't visible on that screen.

Qualitative

Twelve moderated sessions with existing customers, plus five with first-time buyers. The single most common phrase, heard in nine of seventeen sessions, was some variation of "wait, how much is this going to be?"

Approach

We consolidated four pages into a single-page accordion flow with a persistent order summary.

Design Principles

  • Never hide the total. The order summary is sticky on desktop, collapsible-but-pinned on mobile
  • Guest checkout first. Account creation is offered after purchase, pre-filled with the data already entered
  • One decision per section. Each accordion panel asks for one category of information
  • Fail gracefully. Inline validation on blur, never on submit

Component Library

The redesign shipped with a 34-component library built on design tokens. A representative token definition:

{
  "color": {
    "surface": {
      "base": "#FFFBF5",
      "raised": "#FFFFFF",
      "sunken": "#F4F0E8"
    },
    "action": {
      "primary": "#F04B3E",
      "primaryHover": "#D83D31"
    }
  },
  "space": {
    "xs": "4px",
    "sm": "8px",
    "md": "16px",
    "lg": "24px",
    "xl": "40px"
  }
}

Components consumed tokens exclusively — no hardcoded hex values passed code review. The validation hook that powers inline field errors:

function useFieldValidation<T>(
  value: T,
  validators: Array<(v: T) => string | null>
) {
  const [error, setError] = useState<string | null>(null);
  const [touched, setTouched] = useState(false);

  const validate = useCallback(() => {
    for (const validator of validators) {
      const result = validator(value);
      if (result) {
        setError(result);
        return false;
      }
    }
    setError(null);
    return true;
  }, [value, validators]);

  return {
    error: touched ? error : null,
    onBlur: () => {
      setTouched(true);
      validate();
    },
  };
}

Results

Measured over the first full quarter post-launch, against the same quarter the prior year:

MetricBeforeAfterChange
Cart abandonment68%45%−23 pts
Avg. checkout time4m 12s1m 48s−57%
Mobile conversion1.8%3.1%+72%
Support tickets (checkout)340/mo89/mo−74%

The projected realized revenue impact exceeded the original forecast by roughly 15%.

What We'd Do Differently

Two things, honestly:

  • We spent too long on the desktop layout before testing mobile. Mobile was ~70% of traffic, and we should have designed there first rather than adapting down
  • The component library was built during the redesign rather than before it, which caused some rework when patterns diverged late

Stack

Built with Next.js (App Router), TypeScript, and Tailwind CSS. State managed via Zustand for cart persistence. Payments through Stripe Elements. Analytics instrumentation via a thin wrapper around PostHog.

Gallery

ecommerce-platform-redesign
ecommerce-platform-redesign

Tell us what
you're building.

We'll map the shortest route from "we should probably…" to something your customers can actually use.

Start with one sentence

No pitch deck required. A rough idea is enough.