Case study
Quorum
Find events near you, fill the open spots, and make the plan happen.
- Role
- UI/UX lead · Full-stack build
- Context
- CS capstone, Ohio University
- Timeline
- Aug 2025 – May 2026
- Stack
- Flutter · Dart · Firebase


01 · Overview
What Quorum is
Quorum is a mobile app for finding events near you and helping people follow through: pickup games, club meetups, study sessions, anything with a time, a place, and room for more. Open it and you see a feed of what's happening nearby, with the still-open spots and the details right on each card. Tap Join, and you land in a shared chat with everyone else going. It started as “Player Needed” for pickup sports and grew into a general events app with groups, profiles, and messaging.
It was my senior capstone in Computer Science at Ohio University, built in Flutter and Firebase by a five-person team. I led the UI/UX end to end, from Figma flows to a Material 3 design system. I also took on a large share of the engineering, building much of the Flutter front end and the Firebase back end behind it.
02 · Problem
The plan only works if people show
Events have a supply problem, whether it's a pickup game or a club's first meetup: people who would come can't find the event, and hosts who need people can't find them. The coordination that does happen scatters across group chats, stories, and word of mouth, where a half-formed plan quietly dies because nobody could tell if it was still happening.
That gave the product its one-sentence brief: put nearby events in one place, make the open spots obvious, and keep the people who join talking in the same app. When a host needs a few more people, that message should reach someone who can fill the spot.
03 · Role & process
From Figma flows to a shipped design system
I owned the design from the first sketches. The core flows were registration, discovery, event creation, and chat, and I mapped them as clickable prototypes in Figma before any of it hit code. Testing those flows cheaply meant we settled the hard navigation questions on the whiteboard instead of mid-build.
Those prototypes became the design system in Flutter: a Material 3 theme with custom light and dark color schemes, an Outfit type scale, and shared components so every screen felt like one app. A ThemeController swaps light and dark at runtime. The whole UI was built against tokens from day one instead of hard-coded colors.

04 · Product decisions
The calls that shaped the app
Discovery is location-first
The home screen isn't a calendar. It's a feed of what's near you now, sorted by distance and time, with category chips to filter by what you're into. Events carry a GeoPoint, so distance is computed from your location, and a map view plots them. Picking a place when you create an event uses Google Places autocomplete, which keeps locations consistent.

Open spots are the whole point
Every event tracks how many people it needs and who's already in, so a card can say “needs 2 more” at a glance. Open one and you get the full picture: who's hosting, who's coming, and the exact spot on the map. A single Join button drops you straight into the group. Pickup games include skill level and who-can-join fields. Other event types keep the form shorter.

Coordination lives in the app
Joining an event drops you straight into its group chat, so plans don't scatter back out to a dozen separate threads. The chat is a full real-time system: direct and group conversations, read receipts, emoji reactions, photo sharing, and the ability to share an event as a rich card right in the conversation.

Light and dark, by design
Light and dark mode share the same structure. Custom Material color schemes, a consistent type scale, and tabular figures for distances and counts keep the app legible in either mode. The two Discover screens at the top are the same screen, same code, different theme.
More of the app




05 · Engineering
Flutter + Firebase, and the hard parts
The back end uses Firebase Auth, Firestore, Storage, and Cloud Messaging, with a feature-first Flutter architecture that splits each feature into its data layer and its UI. I designed the Firestore data model: collections for users, events, groups, chat rooms and their messages, plus per-user notifications, all driven by realtime listeners so the UI updates the instant data changes.
The harder problems sit behind the screens:
- Joining can't oversell an event. Limited-spot events use Firestore transactions to add or remove a person, so two people tapping Join at once can't both claim the last slot.
- Derived state stays in sync. An event's group chat is kept in lockstep with the attendee list. Membership changes sync to the chat room automatically, and participant names are denormalized in so the list renders without extra reads.
- Unread, done cheaply. Read state comes from per-user timestamp maps. Marking a thread read batches its updates and caps the work to recent messages, so opening a busy chat doesn't fan out into hundreds of writes.
- The feed stays fresh. Events that are past get archived to a separate collection, so Discover only ever queries what's still worth showing.
06 · Outcome
What shipped, and what I took from it
5
Person capstone team I shared the build with
Android
Shipped from a single Flutter codebase
2 semesters
From first Figma flow to a working app
Quorum is the project where I learned how much faster the work moves when design and engineering stay close together. The Figma decisions and the Firestore decisions had to support the same product. Because the flows, prototypes, and design system were settled early, the build moved faster once we started writing code. That's how I want to keep working: understand the problem, design the solution, then build the whole thing, front end and back, to match.