Overview
Ostrich is a private London property marketplace where homeowners explore selling on their own terms, without agents or public listings. The viewing request flow is the core product interaction: a buyer submits an indicative offer, the seller responds, and if there's mutual interest a viewing is arranged. I was the sole designer on a project to rebuild the entire experience, working with two engineers, the CEO as product lead, and Harriet, the ops lead, whose daily experience managing buyer-seller interactions shaped every major design decision.
Note: Personal data in the visuals is illustrative. No real users, properties, or prices are shown.
The challenge
Buyers had no clear picture of where their requests stood. Sellers managed multiple incoming requests with no priority ordering. And ops were manually handling cancellations, rescheduling, and post-viewing feedback through a mix of emails and admin actions, doing work that should have been self-serve. Viewing requests and viewings lived in two separate lists with no shared component system. Mapping the existing system end to end took longer than I expected.
The architecture told the same story. The flow had been built incrementally across four phases, growing from a simple offer form into a multi-step process whose status logic no longer matched the product it described. The data model still used “Offer” and “OfferMessage” internally while the product surfaced “Viewing Request.” Statuses didn’t clearly map to available actions.
The brief wasn’t just to fix the interface. It was to design explicit paths for every scenario currently being handled by hand, while the engineering team refactored the backend in parallel.
How I approached it
The project broke into four threads that ran in sequence but kept looping back into each other: mapping what already existed, building a component system to draw it in, working through the harder interaction problems, and closing the loop on what happened after a viewing. None of this was clean or linear in practice, but the four threads are how the project actually felt as I worked through it.
Mapping the system
Harriet had joined Ostrich around the time the project started, and was learning the existing system alongside us as we mapped it. She’d been handling buyer-seller interactions day to day, so the edge cases came up faster than they would have for someone reading documentation: what happens when a buyer requests alternative slots while the seller has already given availability to someone else, what happens if all the slots expire before the buyer responds, what the seller sees if a confirmed viewing gets cancelled within 24 hours of the slot. These were all being handled by hand, and we needed to design explicit paths for every one of them.
The mapping turned up over 25 distinct states. Each one needed tailored copy for buyer and seller across email, website, and in-product notifications. Harriet wrote all of it. The voice shifts between buyer and seller, between confirmation and rejection, between in-product and email, and the consistency across those surfaces is most of what makes the system feel coherent. Getting copy wrong at any of those touchpoints would have created confusion no amount of visual design could fix.
Building the interface
The biggest structural decision was how the two sides would navigate. The previous seller view had a dashboard as the landing page, but it wasn’t doing the job sellers actually needed it to do: showing the status of every viewing request in one place. So we got rid of it. In its place, sellers landed on a page built around side navigation, with the Buyers link opened by default showing the list of buyers and the current status of each one. Viewings, Listing, and Insights sat below it. Clicking a buyer’s name opened the viewing request for that buyer.
Buyers worked from the other direction. A Viewing Requests link in their navigation took them to a list of the properties they were interested in, and clicking a property opened the same request from their side. Sellers saw buyers, buyers saw properties, and they met on the same conversation. A small architectural symmetry that did a lot of work, because it meant both sides could reason about the system in their own terms.
The lists themselves drew from email. Each row carried a reading state. Read, not-read, and sent rows were visually differentiated, and the list was sorted by date. People know how to triage an inbox, and treating the lists as something familiar meant we didn’t have to teach the priority logic.
The viewing request page was where everything met, and it had its own organising decision. The page split into two sections: the current activity at the top, with light cards showing the active state and the response options available now; and Past activity below, with dark cards showing what had already happened, collapsible so the timeline didn’t dominate. A user could glance at the page and immediately separate “what do I need to do?” from “what’s already happened?” That distinction held up across every state in the system.
Around the request page itself, I extended the existing component library with the patterns the project needed: list items that shifted information density at each breakpoint, an aside panel for the buyer’s profile and property details, a property switcher for sellers managing multiple listings.
Building the design token system
Designing for the awkward moments
Cancel and reschedule were the same options on both sides, but the reasons people cancel weren’t. Sellers cancel for property-readiness reasons: they’re not ready to host viewings, they’ve accepted an offer elsewhere, they’re going on the open market. Buyers cancel for buyer-journey reasons: their criteria has changed, they’ve progressed with another property, they’re no longer moving. We surfaced the right reasons to each side rather than pretending they were the same conversation. Harriet wrote both sets of options, and the language difference is most of what tells the system apart for the person using it.
Neither cancellation was a dead end. A seller who cancelled could re-invite the buyer for a viewing later. A buyer whose viewing was cancelled could message the seller, and the seller could change their mind. The framing the design needed to support was “this isn’t working right now” rather than “this is over.”
A smaller decision in the same family was the running late notification: a one-tap status update with predefined options, sent in-app and by SMS, designed to reach the seller wherever they’re paying attention.
Closing the loop on feedback
Before this project, getting feedback from buyers after a viewing was entirely manual. Ops would email, chase responses, and relay what they heard back to sellers. The information was inconsistent, the chasing was constant, and the seller often heard nothing at all.
We designed a structured feedback flow that asked the buyer to commit to a next step. Four options, ordered by how engaged the buyer still was: submit a formal offer, arrange another viewing, no longer interested (with reasons the seller would actually find useful), or snooze if they needed more time.
The harder problem was what to do when the buyer never responded at all. We didn’t want to block them outright, that would have meant introducing friction to fix a behaviour problem, which usually pushes people further away rather than closer. Instead, when a buyer who hadn’t given feedback returned to a property listing, we surfaced a contextual prompt naming the missing feedback and the homeowner who’d hosted them. The reasoning was that the moment of re-engagement is also the moment to acknowledge the unfinished conversation. If the prompt didn’t work, ops would still pick up the phone and ask the buyer about the viewing directly. Harriet’s input on the copy was the difference between this feeling like a guilt-trip and a reasonable ask.
Reaching the formal offer
The post-viewing feedback flow had four options, and one of them was the path the system was actually built for: making a formal offer. The buyer fills out a structured form: offer amount, buyer names, funding details, timeline, with the indicative offer shown as a reference anchor. The form is asking for a complete proposal, not a guess. That commitment is what tips the conversation into something the seller can act on.
Once submitted, the offer goes to the Ostrich team, not directly to the seller. The buyer sees a “Formal offer made” status; the seller sees a “Formal offer received” status; both reference the Ostrich team handling next steps. When the seller accepts, both sides see the same closing card: “The Ostrich team will be on hand to help to support you through the sale process.” From here, solicitors take over and the app’s job is largely done.
The deliberate scoping was a design decision. The product mediates the digital coordination period, the offer, the negotiation, the back-and-forth, and then steps back when the legal process takes over. We talked about extending the app further, into a transparent timeline that would show both sides where they were in the sale process, what was blocked, what was waiting. It was the right idea for a future version. For this one, the system did its job by knowing where its job ended.
Outcome & reflection
Viewings 2.0 shipped in March 2025. The most visible change was for ops: cancellations, reschedules, and post-viewing feedback that used to be handled through email by hand now ran through the product itself. Buyers were less likely to disappear without a word. When they did, ops still picked up the phone, but the volume was lower than it had been. Sellers stopped depending on someone else to relay what a buyer had said. The chasing didn’t go away entirely, but the volume of it dropped meaningfully, and what was left was the kind of edge case that genuinely needed a human.
The interface held up under a complete visual rebrand later that year, with no structural rework. What you’re seeing throughout this case study is the system after the rebrand dropped onto it. The cards, navigation, information architecture, and interaction flows are all unchanged from the original design. That was the clearest signal we’d built something properly extensible, rather than something that worked once and then needed redoing.
The collaboration was what made this project work. Harriet had joined Ostrich around the same time the project started, so we were learning the existing system together as we mapped it, alongside Matt, the lead engineer, who was working through the same questions from the backend side. Discovery wasn’t extracting one person’s knowledge. It was a group of people thinking through every state out loud, which is the only reason the design handled them properly.