Raj Ostawal/Find Care Platform

Product design and frontend · Digital platform

Turning 796 hospital websites into one place to find care

How AdventHealth unified hundreds of separate sites across 1,200 facilities into a single platform, where patients can find a doctor and book a real appointment in minutes.

Role
Product Designer
Partner
AdventHealth × Phase2
Scope
Web and responsive
Timeline
Jan 2025 to Mar 2026

The challenge

Hundreds of sites, none of them speaking the same language

Across 1,200 facilities, AdventHealth had grown into nearly 800 separate websites, each with its own look, navigation and content. For a patient trying to find a doctor or book a visit, the experience changed every time they clicked.

The goal was a single, consumer-first platform that unified all of it, consistent, searchable and bookable, while giving internal teams a system they could extend without rebuilding from scratch. I owned design for the find-care and scheduling experiences at the heart of it, and built the components they run on.

796Separate websites consolidated into one
1,200Facilities served by the platform
1Consistent, consumer-first experience
WeeksTo launch new pages, down from months

The core problem

Patients did not want a website. They wanted an appointment.

The old sites were built around the organisation, by facility, by department, by brand. But a patient does not think in org charts. They arrive with a need: find someone who treats this, nearby, who can see me soon.

My job was to design around that intent: a clear path from "I need care" to a booked appointment, that worked the same way no matter which of the 1,200 facilities a patient landed on.

Design principle: organise around the patient's need, not the hospital's structure.

A spread of platform surfaces including provider profiles, wellness content, video visits and scheduling.
The breadth of the platform: provider profiles, wellness content, video visits and scheduling, unified under one system.

Ideation and information architecture

Designing one path from need to booked visit

Rather than recreate hundreds of site structures, I worked with the team to define a single spine every patient could follow. We mapped the real decision a patient makes and built the architecture around those steps, so the same flow held across every facility and service line.

SearchBy condition, specialty or name
FilterLocation, availability, insurance, gender
ChooseCompare providers and real availability
BookPick a real open slot and confirm
One flow, every facilityThe same path had to work whether a patient searched a hospital, an urgent care, or a single physician.
Real availability, not a request formThe biggest shift: show genuine open appointment times, so booking felt like booking, not sending a message into the void.

Wireframing

Testing the find-and-book flow in low fidelity first

I wireframed the three highest-stakes screens before any visual design: search with filters, the availability grid, and the consumer landing page. The aim was to prove the flow held together, that a patient could move from search to a booked slot without a dead end, before investing in high fidelity.

Three wireframes: find a doctor with filters, a weekly availability grid, and a landing page.
Find a doctor, the availability grid, and the landing entry point, settled in grey boxes first.

The work

Find a doctor, filter with intent, see real availability

The find-care experience was the core of the platform and the part I owned. Search by condition or specialty, then narrow by the things patients actually care about, distance, soonest availability, insurance, gender, language, and see genuine open appointment times rendered right in the results.

Find Doctors search results with a filter rail and a weekly availability grid of bookable time slots.
Find Doctors: search results with filters and a live weekly availability grid.

Building it

The availability grid was the hardest thing on the page

Showing real open appointment times is a design promise with a difficult frontend behind it. A slot is only true for as long as nobody else takes it, and the platform had to render thousands of them across 1,200 facilities in different time zones without ever offering a patient something that was already gone.

Freshness over completeness

Slots were fetched per provider and per week rather than in one giant payload, so the grid could render the visible week fast and refetch quietly on focus. A stale slot is worse than a slow one.

Booking is a race, so treat it like one

Selecting a slot optimistically locked it in the interface while the request went out, with a clear recovery path when the server said it had just been taken. That failure is common enough that it needed a designed state, not an alert.

A component system, not a page

Filters, provider cards, the grid and the booking confirmation were built as reusable adaptive components on the shared platform, which is what let marketing and care teams launch new pages in weeks instead of months.

Filters that survive a refresh

Filter state lived in the URL, so a filtered search could be shared, bookmarked, reopened, and indexed. On a platform replacing 796 sites, search visibility was not optional.

typescriptillustrative
// The grid never rendered a raw API slot. Every slot carried its own
// freshness, so an expired one could gray out in place instead of
// disappearing under the cursor mid-click.
type Slot = {
  startsAt: Date;
  facilityTz: string;             // grid renders in facility time, not the browser's
  state: "open" | "holding" | "taken" | "expired";
};

function useAvailability(providerId: string, week: Date) {
  return useQuery({
    queryKey: ["availability", providerId, weekKey(week)],
    queryFn: () => fetchSlots(providerId, week),
    staleTime: 30_000,          // slots go stale fast
    refetchOnWindowFocus: true,  // coming back to the tab reconciles
  });
}

// Optimistic hold, with the collision case designed rather than thrown.
const book = useMutation({
  mutationFn: bookSlot,
  onMutate: (slot) => setLocal(slot, "holding"),
  onError: (err, slot) =>
    setLocal(slot, err.code === "SLOT_TAKEN" ? "taken" : "open"),
});

Production code from this platform is not mine to publish. This is the pattern reconstructed, to show how the interface kept its promise that an open slot is genuinely open.

A closer look

One consumer experience, from wellness to video visit

Consumer-facing surfaces including a wellness challenge campaign, the AdventHealth app, and scheduling.
The consumer-facing experience: wellness content, video visits and booking in one consistent system.

Beyond find-a-doctor, the platform had to carry everything from wellness campaigns to scheduling a video visit, all in one voice. I extended the same patterns across these surfaces so the experience felt like one product, not a stitched-together set of pages.

Because it was built on a shared component system, marketing and care teams could spin up new pages and microsites in weeks instead of months, without breaking consistency.

Designing on a shared component system meant every new page extended the platform rather than fragmenting it again.

Impact

One platform, one experience, hundreds of sites retired

The unified platform replaced nearly 800 separate websites across 1,200 facilities with a single consumer-first experience, real provider search, real-time booking, and a component system that let teams launch new pages in weeks instead of months.

796 → 1Websites consolidated into one platform
1,200Facilities on one consistent experience
Months → weeksNew page and microsite launch time

What I took away

Unifying a sprawling system is less about visual polish and more about finding the one shape the whole thing can share. The hardest and most valuable work was designing a single find-and-book flow flexible enough to hold across 1,200 facilities, then trusting the component system to carry it everywhere. It taught me to design the pattern, not just the page, which is the same instinct behind the component library I build now.

Next project
Aster UI, an agentic interface component library

Public project metrics and scope are based on the published AdventHealth digital platform case study. Screens shown are from project materials. The code sample is illustrative, written to show the pattern rather than reproduce proprietary source.