← Work

Course Companion

I pitched a course page nobody asked for. It became a funded mission and went live as an A/B test. Sixteen states of what a page may say, flip them here.

Year
2026
Track
built
Category
case-study

Tools

  • Next.js
  • Cursor
  • Claude Design

In February 2026 I pitched a new course page to the management team. Nobody had asked for one, and the last slide said DEMO. A month later it was a funded mission with a small team. In May it went live as an A/B test against the old page, and over the summer we rebuilt it. I designed it, and we did it without Figma handoffs.

Flip the sixteen states

There are no numbers on this page. The figures behind the pitch were the company's, and they described the problem rather than what I did about it.

  1. I pitched a new course page to the management team, unasked, and ended on a demo.
  2. It became a funded mission, and the prototype replaced the PRD.
  3. A running version shipped internally on the date we committed to at kickoff.
  4. It went live as an A/B test against the old page.
  5. We decided to rebuild it.
  6. –I ran the second research wave, putting the loop in front of students before it was built.
  7. –I split confidence into two axes and wrote the sixteen-state contract.
  8. – I built the harness that grades the page, then fixed its own false greens.
  9. –I found the new page hard to find in search, argued to fix it first, and lost.
  10. Where the record stops, mid-sprint.

This is the page as it landed. A question is already open before anything is asked of the student.

  1. The course page for Introduction to Psychology as it landed. The next three term items sit as pills on one line, every date marked as an estimate, over a line saying how ready the student is for Midterm 1. Below the tabs, practice questions are already on screen with the first one open.

The reframe

The company had an AI product that turned course material into practice questions, summaries and mock exams. Not many people used it, and that was being treated as a marketing problem.

I thought it was structural. Students do not go looking for an AI tool. They go to their course page, because that is where their material and their classmates are. The AI lived somewhere else, in a personal workspace, and nothing it made stayed behind.

So the pitch was one change. Put the artifacts on the course page, where anyone taking that course can find them, this semester or next. The paywall moves with them, to the moment a student fails a practice question, because that is the most motivated user in the product. Reading and making stay free. Feedback is the paid part.

A question on screen

The brief I wrote for the rebuild starts with one line: do not build a calendar, build a reason to come back. Students do not want a calendar. They want to know they are not behind, and the one thing to do right now.

So time is in three layers. The header is stakes, the next exam and nothing else. The body is now, and it is the main thing on the page: today's review renders on load with the first question already open. The full calendar is the third layer, behind a chevron.

A topic you put off is not lost. Come back tomorrow moves it, with your result, into Tomorrow. The ring on a topic shows coverage, not progress. I wrote that into the spec with an instruction not to revert it, because progress is the obvious reading and it is wrong.

Today's review

Today's review with a question already on screen: which part of a neuron receives incoming signals from other neurons, with four answers, and Skip and Come back tomorrow beside the topic. Two more topics wait under Tomorrow.
The same question answered wrong. Axon is marked incorrect, Dendrites is marked correct, and one line says why before Next.
The topic finished at four of five correct: the coverage ring fills, the card says Looking good, and offers Sharpen this topic, Try again and Next topic.
Come back tomorrow pressed on the first topic instead. The review moves on to Operant Conditioning, and Biological Psychology joins the two topics under Tomorrow.

The result ends on four cards dealt as a fan, each marked: tired, hyped, no screen, raw material.

Where to next

5 states

Card
Where to next? Pick whatever fits your energy right now. Four cards dealt as a fan, each marked with a mood: an explainer video, infinite practice, an audio recap and reading notes.
the fan

Where to next? Pick whatever fits your energy right now.

tired

Biological Psychology explained. Explainer, 8 min.

hyped

Infinite practice. Adaptive questions that never run out.

no screen

Biological Psychology, 12-min audio recap. Podcast, 12 min.

raw material

Biological Psychology, full reading notes. Lecture notes, PSYC 101.

Sixteen states

The hard problem was not layout. Most of the time we did not know enough about a course to fill the page.

The team had a model for that: one dial, four levels, from we know nothing to we know everything. It was the product manager's, and it held until it had to describe a well-covered course seen by someone on their first visit. One dial has to either invent a readiness score from no history or hide dates we actually hold.

  1. Data confidence as one dial of four levels: L1 generic, L2 reverse-engineered, L3 full data and L4 deferred. L3 is selected, and a note says only L3 is built today.

So I split it. What we know about the course is one axis and what we know about the student is the other. Four by four, sixteen states. Down a row is a content problem, a syllabus or an upload, and nothing a student does at the keyboard moves it. Across a column is an engagement problem, and only the student moves it.

Four things vary per state: the daily card, the plan below it, the topic radar and the one ask we are allowed to make. Everything else stays the same.

Then I built a harness that grades the page against the contract, before the page it grades, so it could not be tuned to flatter the work. It had its own bug: reading the whole document made it match its own copy of the expected text and mark everything green.

This is that harness, redrawn. Every cell is a real capture of my prototype with my note on it, and it opens on the cell that forced the split.

Confidence matrix

16 states

Course
Student
Course none, Student anonymous, L1 · M
The setup
We hold no topics for this course, and this is a student who just arrived and has done nothing yet.
So we show
the Must-know deck. It only needs documents, and that is all we have.
We ask
for the exam date, since we have none.
Course none, Student guest, L1 · M
The setup
We hold no topics for this course, and this is a guest who has answered a few questions.
So we show
the Must-know deck. It only needs documents, and that is all we have.
We ask
them to sign in, so the answers they are giving us survive.
Course none, Student returning, L1 · M
The setup
We hold no topics for this course, and this is someone who has been back a few times.
So we show
the Must-know deck. It only needs documents, and that is all we have.
We ask
for the course schedule, which is what unlocks the plan.
Course none, Student established, L1 · M
The setup
We hold no topics for this course, and this is a regular with real history here.
So we show
the Must-know deck. It only needs documents, and that is all we have.
We ask
them to contribute. They have practised here often enough to know this course better than we do.
Course estimated, Student anonymous, L2 · R
The setup
We extracted some topics, but nobody confirmed them, and this is a student who just arrived and has done nothing yet.
So we show
the readiness check. It is the only card that works with no history, and taking it unlocks the other two.
We ask
whether the topic on screen is really part of their course.
Course estimated, Student guest, L2 · R
The setup
We extracted some topics, but nobody confirmed them, and this is a guest who has answered a few questions.
So we show
the readiness check. It is the only card that works with no history, and taking it unlocks the other two.
We ask
them to sign in, so the answers they are giving us survive.
Course estimated, Student returning, L2 · D
The setup
We extracted some topics, but nobody confirmed them, and this is someone who has been back a few times.
So we show
the daily review, because they have enough history for us to pick what matters today.
We ask
them to confirm the topic list their scores are built on.
Course estimated, Student established, L2 · D
The setup
We extracted some topics, but nobody confirmed them, and this is a regular with real history here.
So we show
the daily review, because they have enough history for us to pick what matters today.
We ask
them to confirm the topic list their scores are built on.
Course confirmed, Student anonymous, L2 · R
The setup
We have the real topic list and the exam dates, and this is a student who just arrived and has done nothing yet.
So we show
the readiness check. It is the only card that works with no history, and taking it unlocks the other two.
We ask
nothing. We have what we need. Get out of the way.
Course confirmed, Student guest, L2 · R
The setup
We have the real topic list and the exam dates, and this is a guest who has answered a few questions.
So we show
the readiness check. It is the only card that works with no history, and taking it unlocks the other two.
We ask
them to sign in, so the answers they are giving us survive.
Course confirmed, Student returning, L3 · D
The setup
We have the real topic list and the exam dates, and this is someone who has been back a few times.
So we show
the daily review, because they have enough history for us to pick what matters today.
We ask
nothing. We have what we need. Get out of the way.
Course confirmed, Student established, L3 · D
The setup
We have the real topic list and the exam dates, and this is a regular with real history here.
So we show
the daily review, because they have enough history for us to pick what matters today.
We ask
nothing. We have what we need. Get out of the way.
The course page for a course we hold everything for, seen by a student who just arrived. It leads with the readiness check and asks for nothing.
Course rich, Student anonymous, L2 · R
The setup
We have everything, including what the instructor added, and this is a student who just arrived and has done nothing yet.
So we show
the readiness check. It is the only card that works with no history, and taking it unlocks the other two.
We ask
nothing. We have what we need. Get out of the way.
Course rich, Student guest, L2 · R
The setup
We have everything, including what the instructor added, and this is a guest who has answered a few questions.
So we show
the readiness check. It is the only card that works with no history, and taking it unlocks the other two.
We ask
them to sign in, so the answers they are giving us survive.
Course rich, Student returning, L3 · D
The setup
We have everything, including what the instructor added, and this is someone who has been back a few times.
So we show
the daily review, because they have enough history for us to pick what matters today.
We ask
nothing. We have what we need. Get out of the way.
Course rich, Student established, L3 · D
The setup
We have everything, including what the instructor added, and this is a regular with real history here.
So we show
the daily review, because they have enough history for us to pick what matters today.
We ask
nothing. We have what we need. Get out of the way.

The matrix holds one axis it does not draw: how far off the exam is. This is the same page at six distances, from a month out to nine days after, with the Timing note the harness prints for each.

Distance from the exam

6 states

When
The course page with Midterm 1 in 34 days. The header shows the two coming exams in plain tiles, and today's review opens on a question.
a month out

The exam is a month out. Nothing is urgent, so nothing is coloured urgent.

four days
cram

The exam is imminent, so the plan is thrown out and everything is ordered by exam yield.

two days after

We ask how it went, and the answer decides whether we move on.

five days after

We stopped asking and moved the plan on. We just say so.

nine days after

Too long to ask. The plan moved on by itself.

What the page may say

Under the states are rules about what we are allowed to say.

A field renders only if we can produce a value and that value can drive something. Both, or it does not show.

An estimated value carries a small mark, and the mark is a call to action rather than a badge. Press it and you get the document the estimate came from and a way to correct it.

When we do not have an exam date, we ask blind. The field is empty, and our guess shows only after you answer, because showing the guess first anchors the answer.

We ask only about something you are looking at, never a cold audit of a list. One gate decides when asking is wrong at all, so two asks cannot compete for the same moment.

Readiness is personal, so a student with no history has no score. The readout says that rather than printing a number, because any number there would be invented.

  1. The header of an introductory statistics course. Midterm 1 and the final exam each show a date with a small est mark beside it.
  2. The est mark pressed. A small sheet says the Midterm 1 date is estimated from one course document, names the course outline it came from, and offers Correct it and Flag it.
  3. A course with no dates. The header says Your first exam with an Add the date button, and below it When's your midterm opens on an empty date field, with a line saying nothing is pre-filled on purpose.

And what the blind ask says once you have answered.

  1. After a date is typed and saved: Saved, the full course on 2026-04-09. For context: other students told us Apr 8. Yours is what we'll use for you. Change it.

When the topics can't be trusted

Most courses did not have the topic structure the daily loop assumed. So I forked the build to answer one question: what does this page do when we cannot trust the topics?

The review becomes one set of questions across the whole course, and the topics tab goes. The other lanes fill with documents, ranked three ways on purpose, because the most opened material is not the best rated and flattening that loses the only signal we have.

The exam strip took the most work. It says what is at stake, and for most courses we had no date to put in it. The card we shipped said dates are not in yet, which is true and gives a student nothing to do. So it became seven treatments, and this is the panel we walked them with, redrawn. It opens on the one we shipped.

The exam strip, with no dates

7 states

Treatment
The course header with no dates in it: one dashed card saying exam dates aren't in yet, and that countdowns will show here for everyone once they are added.
current · shipped

What we ship today: one honest “dates aren’t in yet” card. True, and nothing to walk toward.

light estimate

The exam strip one confidence step down: same cards, the status-warning ramp carrying the confidence. Set it or leave it.

rail

One 62px track: confirmed coursework as a chip, the roughly-known exams as pressable pills sitting on the rail.

slots

Today’s strip shape with three states: pinned, roughly known (Set day), set by you. Nothing new to learn.

term calendar

Collapsed by default. One row: the next thing up with its countdown, the rest of the term as a quiet line, and “Term calendar” unfolds the real month grids, where a week we only know roughly is a band across that week.

zen months

The same months, no day grids, monochrome: each item carries its kind’s glyph, “≈” marks a week we are guessing, and every box hugs its own content. One item is ~58px, a second grows it. The + on a month adds one; a month holding nothing is a thin +.

intelligence

The brainstorm’s converged band, fully chronological: the next three term items by time (exam, quiz, essay, whatever comes first) as tab pills on one centered line, with a ≈ countdown chip on the nearest, the only blue. A readiness readout while collapsed, and everything further out behind +N more, where each row expands in place: covers, format, notes, when. Scraped from past terms’ syllabi, so every date reads ≈ and carries a Set-the-day ask.

The ladder under the exam slot became the rule. Whatever is the best thing we hold about a course is what the slot says, and the ask under it is the same sentence at every level.

The second turn of three on the exam-date canvas. Four rungs, the top one wins, and the ask is the same sentence at every level. Lifted out of the canvas rather than screenshotted, so the text is still text. Open it full size

When the slot holds nothing, the ask is a schedule. The rule I wrote for that upload was ask, check, confirm, rebuild, and every failed check has a real way out, never a dead end.

The schedule upload

4 states

File
A dialog titled Two exam dates found: Midterm 1 on Apr 8 and the final on May 14, each quoted from the line of the schedule it came from, a link to review six topics found, and Looks right or Something's wrong.
the schedule

Two exam dates found. Check these before we rebuild your plan around them.

lecture slides

This looks like lecture slides, not a schedule. We couldn't find exam dates or a week-by-week outline in it.

another course

This schedule is for PSY 150. The course code inside doesn't match this course, so its dates would be wrong here.

last term

This schedule is from Fall 2025. Dates from a past term would put your whole plan in the wrong place.

In front of the Documents tab there were six orders. The old library stays reachable from every one of them, as the last line under the results and never the first thing.

In front of the Documents tab

6 states

Order
The Documents tab as it was: a grid of documents in no particular order, each with its type and rating.
current

The legacy library grid, untouched: everything we hold, in no particular order. The control.

search first

A find-in-this-course box over type facets, the one thing the flat grid cannot do. Best when the student already knows what they want.

by type

One ranked rail per kind, best-rated first. “I want a practice exam” becomes a glance instead of a scan.

by topic

Documents mapped onto the course’s topics, so “which doc covers X” is answerable. And it says out loud that the mapping is our guess, filing the rest under the whole course.

shortlist

Six documents, each with the reason it earned a place: opens, ratings, this week. The library is a scroll; this is an answer. Browse-all is one click behind it.

better order

The same grid with an honest default sort and facets. Nothing new to learn, and the cheapest of the five to ship.

After the last question

When the questions run out, the page has one thing worth sending: the set a student just did, and their score on it. So the ask to share the course comes once, under the score, and never beside another ask. A classmate who opens the link lands signed out on the same ten questions, and when they finish, the save ask takes the share's place. One ask at a time.

The share loop

The practice questions finished at seven of ten, That's all 10. Under the score, a tinted panel says Share PSYC 101 with your class: one link gives them these questions and every document in the course, with a Share this course button. What to read next follows below it.
Share this course pressed. A small sheet over the page says anyone with the link can open this course, shows the course link beside a Copy link button, and says 156 students are enrolled.
The same sheet with the link copied, its button now reading Copied.
The classmate's view, signed out, with Log in and Sign up at the top. A banner says Alex R. shared this course with you, over the course header, and the same ten practice questions start at question one.
The classmate answers the first question correctly. One line explains why, and beside Next there is a small Not about my course link.
The classmate finishes the ten, still signed out. Where the share panel was, a Save your progress row asks them to log in so the next set starts where they left off, with Log in to save and Not now.

I built fifteen treatments of that ask, from a plain row to a sticker sheet, and the prototype records one of them as selected to be built. The other fourteen stayed in the harness as the comparison, and it opens on the one.

The share ask

15 states

Ask
plain row

Most conservative: one sentence and an outline button, no tint. Tests whether any theatre matters at all.

the link

Conservative: the URL is shown, so the ask is exactly as big as it looks. Transparency as the pitch.

A tinted panel saying Share PSYC 101 with your class. One link gives them these questions and every document in the course, and the more of the class studies here, the more material the course has. One Share this course button.
quiet panel · selected to be built

The default push: a tinted ask under the score, one pill, no theatre. The other fourteen stay here as comparison.

your score

The result becomes the thing worth sending: a scorecard preview travels with the link. People share what they did, not URLs.

group chat

People-first: five course mates up front, the chat is the destination. A concrete recipient beats an abstract link.

exam push

The shared deadline does the pushing: real exam date, real classmate count, exam amber.

beat my score

Creative: your scorecard next to your class’s blank one. Same set, fair fight.

invite ticket

Creative: the share as a gift, an admit-one ticket that seats a course mate, not a broadcast.

crew wristband

Creative: a 3D wristband for the whole crew, idling in a slow turn. The link as group access, not a one-to-one favour.

lettered band

Creative: the same crew band with the course code printed around the ring itself, the message written on the band, turning with it.

all-access pass

Creative: a lanyard study pass with a blank “issued to” line, a gift that begs a name. Grab the pass and it swings, stretches and flips, then snaps back.

holo sticker

Creative: a holographic crew sticker. The foil tilts and shifts under your cursor. The link underneath gets the whole chat in.

course stamp

Creative: a dark story-size card, the set stamped like a passport: course, score, date, the URL. A receipt you are handed, not a badge you earn. Press the card to stamp it again.

sticker sheet

Creative: a cute die-cut sticker sheet of course facts: score, exam day, the crew. The recipient does the distribution work.

sticker bomb

Creative: the sheet gone maximalist, patterned die-cut circles (graph grid, crosshatch, halftone dots) packed and overlapping like the back of a phone case. Same facts, louder object.

Seven of them move. Press one to see how.

  1. Crew wristband. It floats and turns, a sheen crossing it.
  2. Lettered band. The course code and the score spin around the ring.
  3. All-access pass. Grabbed, pulled and flung, it swings back to rest.
  4. Holo sticker. The foil tilts and shifts under the cursor.
  5. Course stamp. Pressed, it stamps again.
  6. Sticker sheet. A sticker straightens and grows under the pointer.
  7. Sticker bomb. One sticker lifts to the top of the pile.

The prototype was the handoff

We agreed at kickoff not to write requirement documents. The prototype was the alignment artifact instead. So the handoff and the prototype are one file, with two tracks always visible: product context, with the bets, the decisions and the open questions, and developer handoff, with component pages, measurements, props, a token reference and the tracking spec. Forty-two pages.

The way I worked was to build the options instead of arguing about them. The header is the clearest case. There were nine ways to combine the next exam with how ready you are, so I built all nine behind one flag, and they shipped that way, with no single pick. That is a five minute decision in a room and an unresolvable one in a document. The note under each is what the board and the handoff said about it.

The course header

9 states

Treatment
The course header as it was: Midterm 1 on Apr 8, four days away, beside Midterm 2 in a plain tile.
default

The current header.

meter

One bar, an 80% “exam-ready” flag, the date beside it. Lowest cognitive load.

clock, two bars

Two stacked bars: time-to-exam vs your readiness. Closest to my sketch.

clock, one bar

Blue fill (you) on a gray time-elapsed ghost, one bar. Its line comes closest to a pace judgment, where the others state a gap and the days left.

racing flag

Bounded height, checkered finish, one accent.

chart

A mini timeline, the climb from 62% to 80% by Apr 8. Most expressive. In this build the label under the chart lost its number.

activity

Readiness over the last 8 weeks, trending toward exam-ready. Backward-looking momentum where the other timeline styles are a forward climb.

streak

A calm take on a study-consistency streak, in the design system's own parts (not a Strava clone).

exam tiles

The shipped exam-strip tile with readiness merged in, and the cheapest variant to build and test.

  1. The handoff's home page: Course Companion, two tracks in one place, a button to open the prototype, a status of Ready for build, and the two tracks side by side, product context and developer handoff.
  2. Page 24 of the handoff, the topic review card: its collapsed states with their coverage rings, the answer options in every state, and a table mapping coverage to the encouragement copy.
  3. The same card's measurements as a table: radius, border, shadow, padding, ring sizes and type, in pixels.
  4. Page 37, Today's Review ranking: a session time budget, a priority score written as a formula over mastery gap, exam proximity and dueness, and the fill algorithm in numbered steps.
  5. Page 33, empty and edge states: six cards, each giving the copy, when it shows and how it is treated, from all caught up to a document being generated.

Everything else the prototypes hold, and what was on the boards before any of it was wired.

Built into the prototype

  • 16 statesConfidence matrixShown in Sixteen states
  • 6 statesDistance from the examShown in Sixteen states
  • 4 cardsWhere to nextShown in A question on screen
  • 7 treatmentsThe exam strip with no datesShown in When the topics can't be trusted
  • 8 statesThe schedule uploadShown in When the topics can't be trusted, four of them
  • 6 ordersThe Documents tabShown in When the topics can't be trusted
  • 15 asksThe share askShown in After the last question
  • 7 objectsAsks that moveShown in After the last question
  • 3 statesWhat an ask may print
  • 6 framesThe share loopShown in After the last question
  • 10 treatmentsThe course headerShown in The prototype was the handoff, nine of them
  • 4 stylesThe save ask, with its honest copy
  • 3 statesThe topic list
  • 3 statesThe estimate mark, finishedShown in What the page may say, two of them
  • on or offTriage under an answered question
  • 4 statesWhat leads a course with no questions
  • 3 statesWhat the course holds
  • 4 treatmentsMaking an estimated date pressable
  • 8 probesInterview probesShown in Tested with students, two of them

On the boards before anything was wired

Generated by the design tool on my brief, before anything was wired. The brief was mine, and so were the picks and what got built from them.

  • 23 optionsExam date bannersShown in When the topics can't be trusted, as the date ladder
  • 5 buildsExam date banners, my five comments built
  • 23 statesExplanation sources
  • 16 optionsHeader, eight rounds of review
  • 18 optionsHappy moments
  • 11 optionsPractice shape
  • 8 optionsAfter the exam
  • 6 optionsConfidence asks
  • 17 optionsProximity decisions

Tested with students

The second research wave, in July, put the loop in front of students before it was built. I designed the study, wrote the guide and built the tooling. A session is set up in the prototype's own panel and becomes a link that opens the clean user view with those exact settings. The interview companion beside it runs the session: a script, a consent line to wait for, and a list of things not to say.

The wave killed one of my own mechanics. Come back tomorrow was meant to read as spacing, and students read it as scheduling and gating. Endless adaptive practice read as stress rather than help, which is where cram mode came from.

  1. The prototype's session settings for an interview: switches for session length, keep-going tiles, a readiness gauge and streaks, all off, the data confidence level at L3, and a shareable link that opens the user view with these settings.
  2. The interview companion before a session: a thirty-minute timer, seven stages from setup to wrap, fields for the participant and their course, and a pre-flight checklist for the build and the recording.
  3. The companion's second stage, Frame: a script to read aloud that sets expectations and asks for consent to record, a reminder to wait for a clear yes, and a notes field.

The two probes that found it.

  1. The interview companion at probe 4 of 8, Come back tomorrow. Ask: what do you think this does, when would you click it? Follow: does that feel like help, or like being put off? A notes field below.
  2. Probe 5, the Tomorrow lane, marked as a priority signal. Ask: it says these are saved for tomorrow, spaced so it sticks, so why hold them instead of showing you now? Follow: do you trust it to decide that for you?

Shipping it

Most of the code was pushed by the frontend engineer on the team, who was very good. What changed is that we stopped doing Figma handoffs. I built the initial states in the real codebase, he rebuilt and hardened them on a shared branch, and I kept pushing code myself from time to time. One of those weeks was five cards: the first daily card built from popular material, the router that picks the confidence state, an edge case for courses with no exam date, a way to flag a topic that looks wrong, and a rewrite nobody had picked up.

Getting the environment running cost me a day, and while doing it I found why nobody could push, and wrote the fix down for the team.

The part worth telling is the mistake. I was asked to bring four sections of the old page onto the new one, and the person asking named three. I searched for what they named, found it, and wrote a three section spec. It was consistent and it was wrong. Someone else found the fourth section two days later, and the evidence had been in my own notes: the name of the test variant was a list of the sections it contained, and I had read it as a label.

The rule I wrote afterwards: enumerate the parent, do not hunt for the children. A screenshot proves something is there. It never proves something is missing.

Findable, or not

In August I measured our own page in both arms of the live test, on the same course. The new one served a fraction of the old page's text and none of its document links. We had built something students could not find.

It was not a tag to flip. The crawler exclusion sat on a URL a crawler never reaches, so removing it would change nothing. You cannot serve one version of a page to a search engine and another to people, which makes a single crawlable URL a launch requirement rather than a cleanup task.

Then I argued my own case down. The uplift estimate was experienced judgement rather than a model, and it would land months after the launch it was being weighed against. In the meeting I had called to push it, I asked whether making the page findable would bring in new users at all, and nobody could say yes. What kept it alive was that the URL structure would block any future migration, so it had to happen either way.

It was scoped and deferred. I think that was the wrong call and I understand it. Four people, one engineer, and a launch in front of us.

Where it ended

When I left it was live and running as a test, the rebuild was shipping behind its flags, and the findability work was scoped and waiting.

The part I would defend is the sixteen states. Almost every decision on that page came down to what we are allowed to say when we do not know, and the honest answer was always more work than the dishonest one: ask instead of guessing, show a grey arc instead of a number, build a page that degrades in pieces instead of one that assumes the data arrived.

What I would change is the order. I spent four months on the problem in front of me, and the one that mattered, whether anyone could find the thing, was one measurement away the whole time.

More case studies

See all 27