Giftly · 2025

The cart was the easy part

Took the password out of the buyer path, moved checkout state off the client, then shipped a multi-item cart — the cart last, because the cart was the easy part.

PublicNamed and linkable, with figures as reported.

The situation

Buying two gifts meant going through checkout twice, because checkout state lived in the browser tab — there was nothing on the backend a second gift could be added to.

And every purchase ran through a password prompt aimed at a buyer who shows up once a year.

The constraints

  • This is the revenue path, mid-flight. Checkout could not close for renovation, so the state move had to happen underneath a flow that kept selling.
  • Every step ships behind an experiment, so each stage had to be attributable and reversible on its own.

The call

Take the password out of the buyer path rather than making the login form easier. The work started as an experiment on inline login at checkout — measure the friction before removing it — and once that won and became the default, the password went too: a magic link or a typed code for people who had bought before, and account creation at checkout for people who had not, with no password set at any point. The obvious alternative was to keep optimising the form, which would have kept asking a once-a-year buyer to remember something they had no reason to remember.

Move checkout state onto the backend before building anything on it. A cart is not really buildable while the source of truth lives in a browser tab — so the unglamorous move went first, staged: payment onto its own page, then the checkout refactor, then the cart on top.

What happened

A cart where each gift keeps its own delivery method, greeting card and schedule under a single payment, shipped in staged rollouts rather than one cutover.

No password anywhere in the buyer path — returning buyers get a magic link or a typed code, and new buyers get an account without ever setting one.

Built with

Ruby on Rails · TypeScript · Vue 3 · Inertia · PostgreSQL · Stripe API · Claude Code