Skip to main content
JoshuaBriley.
IVFCRYO logo

Case study

Getting five people ready before a shipment moves.

IVFCRYO ships frozen embryos and other fertility material between clinics. I designed the app that patients and clinic staff use, and worked with engineers on the system behind it that tracks each shipment and sends alerts. Moving the box only takes a day. Getting five people, the patient, two clinics, a courier, and IVFCRYO, all confirmed and ready is the harder part, and that's what the app is built around.

TL;DR

Situation
IVFCRYO ships frozen embryos and other fertility material between clinics. I designed the app patients and staff use, and worked with engineers on the tracking system behind it.
Problem
Interviews with the owner, the COO, and the office manager showed the hard part wasn't the drive. It was getting five people, the patient, two clinics, a courier, and IVFCRYO, all confirmed and ready before a shipment could start.
Alternatives
  • Two separate apps

    One app for patients, one for staff. Simpler to build, but each would keep its own copy of a shipment's status, and the two could disagree.

  • One shared record, two views

    Patients and staff look at the same shipment record, plus a plain tracking page for anyone else involved.

Decision
I chose one shared record instead of two separate apps, so a shipment could never show one status to the patient and a different one to staff.
Implementation
The shipment moves through clear stages, from draft to delivered, and can't be scheduled until everyone involved has confirmed they're ready. Alerts are sorted by how serious they are, so a small temperature change doesn't trigger the same alarm as a real problem.
Evidence
Support calls dropped 75%, and shipping errors dropped 55%, once patients could see for themselves that both clinics had signed off.
Reflection
A blind customer testing with a screen reader found two issues I'd fix first: status updates read aloud too fast, and when a shipment uses two couriers, the screen reader can't tell them apart.

Receipts

Design · owned
  • Stakeholder research & synthesis
  • Five-party workflow modeling
  • Information architecture
  • Two-sided + public flows
  • Readiness as a formal state
Front end · owned
  • Accessible component system
  • Progressive enhancement
  • Forms as a recovery system
  • Text/icon/shape, never color alone
  • Reusable accessible base
Backend · partnered
  • Shaped the Rails domain model
  • Specced lifecycle + readiness states
  • Defined integration boundaries
  • Set telemetry + alert requirements
Outcomes
  • Patients stopped chasing two clinics
  • 75% fewer support calls
  • 55% fewer shipping errors
  • Fewer transfer dates lost to delay

Step 01

Five people, one shipment

Before drawing a single screen, I mapped how a shipment actually moves: a fragile, temperature-controlled package changing hands across two clinics and a courier, on a tight medical deadline. A wrong label or a missed temperature drop isn't just an inconvenience here. It can mean losing someone's only remaining embryo.

Don, the owner, put it simply: a shipment "looks like one transaction to the patient, but it is actually a chain of separate responsibilities", the patient, two clinics, a courier, and IVFCRYO, each with its own paperwork and approvals. So the first thing I built wasn't a screen. It was a map of who owed what to whom.

Five independent parties, one shipment

  1. Patient

    Authorizes the transfer, provides identity and records, completes forms and payment. Should never have to project-manage two labs.

  2. Sending clinic

    Identifies, prepares, and releases the specimens, and names a responsible lab contact, not the front desk.

  3. Receiving clinic

    Confirms intake requirements, staffs qualified people, inspects, and accepts the specimens into storage.

  4. Dedicated courier

    Carries the sealed unit directly between facilities, no unrelated stops, with acknowledged chain-of-custody handoffs.

  5. IVFCRYO

    Provides the shipping unit and IVFCRYO-Sense monitoring, coordinates the logistics, and holds the case together.

The physical chain of custody, with acknowledgment

  1. Prepare & release

    IVFCRYO ships the unit with an IVFCRYO-Sense tracker inside; the sending lab loads the specimens and a named contact releases them.

  2. Courier pickup

    A dedicated medical courier accepts custody from the named lab contact and hand-carries the sealed unit. The handoff is acknowledged, not assumed.

  3. Delivery & inspection

    The receiving lab inspects the unit and records a calibrated temperature at specimen-storage level before taking custody.

  4. Accept & close

    Qualified staff accept the specimens into storage and the record closes on acknowledgment. "Delivered" is not "accepted."

Handoffs break down when the next person does not know they are now responsible. "Sent" is not the same thing as "received and approved."
Don Fish · Owner, IVFCRYO

How a screen got built

Shipment detail, rough hand-drawn concept sketch.

Sketch

Arguing about the shape.

Shipment detail, clean wireframe without annotations.

Wireframe

Fixing it.

Annotated wireframe of the shipment detail page: a live position map above sensor readings for temperature, humidity, and battery, then two parallel tracking timelines, with callouts explaining why telemetry outranks logistics and why the two legs stay unmerged.

Annotated

The reasoning written on top.

A crude sketch to settle what the page is for, a clean wireframe to settle where things go, then the same wireframe with the decisions written onto it. That third pass did the work: writing down why status lives in the URL, or why a half-filled form is never abandoned, is what turned a picture of a screen into a decision anyone on the project could check.
Annotated wireframe of the shipment detail page: a live position map above sensor readings for temperature, humidity, and battery, then two parallel tracking timelines, with callouts explaining why telemetry outranks logistics and why the two legs stay unmerged.
05Shipment detail

One page that answers the only two questions anyone has: where is it, and is it still cold.

Step 02

Checking everyone is ready

I asked all three people I interviewed what they'd fix first, and all three named the same thing: a shared readiness check that both clinics confirm before a courier is scheduled.

The worst pattern, Daryl told me, is "scheduling first and hoping the remaining requirements are completed before pickup." It happens because someone is trying to protect a patient's transfer date, and it sometimes ends in a last-minute cancellation instead. So I built readiness as something the system checks, not just an impression someone has: a requested date, a provisional plan, and a confirmed shipment stay three separate things, instead of all looking the same the way they did on paper.

Every party clears its checkpoint before the case can be scheduled

  • Patient Authorizations, identity, and payment complete
  • Sending clinic Release approved, specimens prepared, contact named
  • Receiving clinic Acceptance approved, intake requirements confirmed, staff scheduled
  • Courier Route and timing confirmed as feasible
  • Equipment Shipping unit available and suitable for the duration

Only once every checkpoint is confirmed does a shipment move from awaiting_readiness to ready, and only then can it be scheduled. This was the first thing I asked engineering to build, so a courier could never be sent before a clinic was actually ready.

It would not be enough for our team to mark a clinic as ready. The responsible person at each facility would confirm that the documents, staff, equipment, and timing are in place.
Sasha Jenkins · Office Manager, IVFCRYO

Step 03

One app, two views

A customer needs a short, reassuring path from request to tracking. The IVFCRYO staff member lives in the tool all day and needs to see every shipment and every client at once. Building two separate apps would have been simpler, but each would keep its own record of a shipment, and the two could drift apart and disagree, exactly the problem the app exists to fix.

Instead, both sides read from one shared shipment record. A readiness view now sits on the customer side too, since Sasha's hardest daily work was chasing "what are we still waiting for?" across email, fax, and clinic portals.

Two roles, one shared home

Customer

  • Shipping list

    Home. Active + past shipments, readiness + overdue alerts.

  • New shipment

    Sender, receiver, specimen, live carrier pricing, CRYO Shield tier.

  • Readiness view

    What each party still owes before it can be scheduled.

  • Active shipment

    Read-only tracking and sensor telemetry.

  • Receiving customers

    Saved delivery contacts.

  • Profile

    Billing, address, cancel account.

Admin · IVFCRYO staff

  • Shipping list

    Every active + past shipment across clients, by readiness state.

  • Active shipment

    Edit, cancel, change status, notify, open an incident.

  • Customer list

    Filter, sort, open a client.

  • Customer detail

    All orders for one client.

  • Equipment inventory

    Units, monitoring, maintenance and replacement flags.

  • Add customer

    Creates the account, emails credentials.

Annotated wireframe of the shipments index: a filter bar, status tabs, and a list of shipment cards, with six numbered callouts explaining why status lives in the URL and why cards replaced table rows.
03Shipments index

The primary workspace. Readiness state is the top-level filter, not a column.

Flow diagram of authentication and account recovery. A visitor branches on whether they have an account, through sign-in, admin activation, a user-chosen email or SMS verification channel, and six-digit code entry. A failed code offers resend, backup code, or password reset, and a final admin check routes to either the admin or client view. Five numbered design notes sit alongside, and password recovery runs as a separate track underneath.
11Authentication and account recovery

A security gate that must not become a support ticket. Every dead end has a way out.

A third group never signs in at all. The receiving clinic or family gets a link by email or text, and just needs one question answered: is it still on its way. So the public page leaves out the temperature graph, which would only alarm someone who isn't trained to read it, and puts a staffed phone number in the footer instead.

Annotated wireframe of the public tracking page: a plain-language status line, a four-step progress track, a live position map, and a staffed phone number in the footer, with callouts explaining why there is no login and why raw telemetry is withheld.
06Public tracking

The unauthenticated view sent to recipients in notification email and SMS. No account, no sidebar, no raw telemetry.

Step 04

Designing for mistakes

A mistyped address or a name that doesn't match a clinic's records isn't a small form problem here, it's a risk to someone's only embryo. So every form helps people avoid mistakes, explains them clearly when they happen, and lets someone fix them without calling support. Addresses get checked against real map data, and specimen details are captured as structured fields instead of free text.

IVFCRYO's shipping guarantee, CRYO Shield, only pays out on a claim that's fully documented, so the order form also captures the declared value and protection tier, and receiving captures a temperature reading and photos right away. As Daryl put it, "the claims process begins long before a claim exists."

A legally blind customer tested the app with a screen reader from early on, and kept testing after launch, which is how the labeling issue in the edges below got found. Status and errors always show as text and icons, never color alone, and important updates get read aloud automatically instead of only appearing silently on screen.

Built-in, not bolted-on

  • Structured records over free text
  • Geocoded address validation
  • Inline validation, recoverable errors
  • Text, icon, and shape, never color alone
  • Focus managed on visibility change
  • Live-region status announcements
  • Explicit acknowledgment at every handoff
  • Immediate, structured incident capture
Annotated wireframe of the new-shipment form, broken into seven numbered sections from service selection to insurance, with a live price quote pinned beside it and six callouts covering quote recalculation, contact reuse, and notification defaults.
04New shipment

A forty-control form made survivable: numbered sections, live cost, declared value, and no dead ends.

Flow diagram of the shipment creation path. Service selection resolves a live price quote or a contact-for-quote branch, then runs through date, package, pickup and delivery contacts, notification preferences, insurance, and agreement. Failed validation returns to the offending field with form state preserved, and a successful submit forks into a confirmation email and the admin fulfillment queue. Six numbered design notes sit alongside.
12Creating a shipment

The highest-consequence path in the product. Nine sections, one submit, no way to make an impossible booking.

Step 05

Working with engineering

An app can only promise what the system behind it can actually deliver, so I didn't just design the screens and hand them off. I worked alongside the engineering team on the parts that had to carry those promises.

I turned the interview findings into the shipment stages and the readiness check the system had to enforce, mapped out where each carrier and outside service should plug in, and set the requirements for monitoring and alerts. Engineering built the backend. I built the front-end components and the specification they had to meet.

The integration boundaries we drew together

  • IVFCRYO-Sense

    GPS, internal + ambient temp, humidity, pressure

  • ShipEngine

    Multi-carrier rates and labels

  • Dedicated courier

    Direct medical hand-carry, no sorting hubs

  • SendGrid

    Tiered email notifications

  • Twilio

    SMS alerts, off-screen

  • Devise + 2FA

    Auth for medical logistics

A design requirement I handed engineering: tiered alerts

  • Normal Within expected range. Logged, surfaced quietly, no one paged.
  • Early warning A trend moving toward a threshold. Closer monitoring, a call to the courier.
  • Required action A defined threshold crossed. The owner is notified and must respond.
  • Emergency A critical excursion. The pre-assigned escalation path fires.

Daryl's warning drove this: "if one device frequently generates false or unhelpful notifications, employees will eventually stop trusting it." One alert level for everything trains people to ignore it. Four levels, each with someone assigned to respond, don't.

shipment.rb ruby
# app/models/shipment.rb  —  states + requirements I specced with engineering
# A shipment can't be scheduled until every party acknowledges readiness.
# That gate was the single change all three interviewees said they'd make first.
class Shipment < ApplicationRecord
  # "Requested" and "provisional" are NOT "confirmed." Conflating them is what
  # put couriers on the road before a clinic had released.
  enum status: { draft: 0, awaiting_readiness: 1, ready: 2,
                 scheduled: 3, in_transit: 4, delivered: 5,
                 accepted: 6, closed: 7, canceled: 8 }

  has_many :readiness_checks     # one per responsible party
  has_one  :cryo_shield_coverage # declared value + protection tier
  has_one  :shipment_tracker     # IVFCRYO-Sense: temp, GPS, humidity
  has_many :sensor_readings
  has_many :custody_events       # named contact + acknowledgment
  has_many :incidents
  has_many :notifications

  # Scheduling is gated, not assumed. "Sent" is not "approved."
  def schedulable?
    readiness_checks.all?(&:acknowledged?)
  end

  # Alerts are tiered so a normal fluctuation never pages like a critical
  # excursion — the office team stops trusting a channel that cries wolf.
  def record(reading)
    sensor_readings << reading
    case reading.severity          # :normal, :warning, :critical
    when :warning  then CryoAlertJob.perform_async(id, :warning)
    when :critical then CryoAlertJob.perform_async(id, :critical)
    end
  end
end
The lifecycle model as a shared spec: scheduling gated on readiness, alerts tiered by severity. I defined the states and requirements; engineering owned the Rails implementation.

Step 06

What changed after launch

A patient could now see that both clinics had signed off instead of calling to ask. The office team could open one case instead of piecing it together from email, fax, and phone notes. And because scheduling waited on readiness, fewer couriers were sent before a clinic had actually released the specimens.

75%

fewer support calls

patients and clinics got answers without phoning in

55%

fewer shipping errors

caught before they reached a patient's specimens

The measurement frame the research described

Safety

  • Temperature excursions
  • Monitoring gaps
  • Chain-of-custody exceptions
  • Incomplete receiving records

Reliability

  • On-time pickups + deliveries
  • Rescheduled shipments
  • Shipments started without full readiness

Efficiency

  • Order-to-readiness time
  • Manual follow-ups per case
  • Exception resolution time

Experience

  • Status inquiries
  • Complaints
  • Stage-appropriate updates delivered

Patients stopped calling in the dark

The app answers the questions people used to call in with real fear behind them. Support calls fell by three quarters.

Fewer preventable mistakes

The readiness check and better forms catch errors before they reach the specimens. Shipping errors fell by more than half.

Fewer last-minute cancellations

Fewer couriers get sent before a clinic has truly released the specimens, so fewer patients lose a transfer date.

The rest of the system

Six more screens went through the same three passes. These are the annotated pass, whole.

  • Annotated wireframe of the landing screen.
    Landing
  • Annotated wireframe of the auth + two-factor screen.
    Auth + two-factor
  • Annotated wireframe of the address book screen.
    Address book
  • Annotated wireframe of the users admin screen.
    Users admin
  • Annotated wireframe of the equipment inventory screen.
    Equipment inventory
  • Annotated wireframe of the admin settings screen.
    Admin settings

What Don said

Don Fish

Don Fish

Owner · IVFCRYO

Josh didn't just design screens. He sat with me, our COO, and our office manager, and came back with the insight the whole rebuild turned on — the hard part is getting everyone ready, not tracking the truck. He designed the product and owned the front end, and worked shoulder-to-shoulder with our engineers on the data model and the integrations underneath. Our team runs on it, and our patients feel the difference: they finally know someone has the whole case.

The edges

Both of these come from the same root cause: live data streaming in from more than one source, with no shared rule for timing or wording set early enough to prevent it.

  • One update speed, whether you wanted it or not

    The tracker checks in every sixty seconds with temperature, location, humidity, and more. That is fine to look at quietly on screen. For someone using a screen reader, each update gets read aloud, and the next one starts before the last one finishes. There is a setting to slow it down, but a person has to find it first, and the fast pace is still the default. If I revisit this, I would change the default instead of just adding a setting.

  • Same label, different carrier

    Once a shipment used more than one carrier, both got announced with identical wording. A sighted user can tell them apart by where they sit on screen. Someone using a screen reader cannot tell which carrier currently has the shipment. That only surfaced because a screen reader user tested the multi-carrier path. First thing I would fix: name each carrier explicitly in that wording.

Product design engineering

Design the interface, and understand what powers it.

I like to do the research, design the product, build the front end, and then work with engineers on the system that has to keep every promise the design makes. IVFCRYO needed someone who could carry a project from a conversation with the owner to a finished, accessible app, and who understood the backend well enough to hold it to what the design needed. If that's what you're looking for, let's talk.