← Back to all work
Case study

Parking Share

A native SwiftUI + Firebase iOS app that lets residents of an apartment building share their parking spot when they're not using it. Two roles — an admin who manages the building, and residents who manage their own spot — enforced all the way down to the Firestore security rules, not just the UI.

Platform
iOS · SwiftUI
Backend
Firebase (Auth, Firestore)
Auth
Phone (OTP) + Email
Design system
"Deck / Industrial Signage" — custom, from scratch
The problem

Overview

Apartment buildings often have more assigned parking spots than residents actively using them at any given time. Parking Share gives a building's admin a way to model the garage — floors and stalls — and gives each resident control over their own spot: mark it shareable, set a recurring weekly schedule or one-off date windows, and flag details like double-parking or an EV charger. Every permission boundary is enforced twice — once in the UI, and independently in Firestore security rules, so the rules hold even against a client that doesn't play by them.

How it works

One physical stall, one owner of record, shared out on a schedule — not handed over. The resident keeps the spot; sharing it just means someone else can use it during the windows they've opened up.

Drawn in the app's own "Deck / Industrial Signage" palette — concrete surface, ink, and the original accent orange — rather than a generic stock graphic.

STALL 010
Core flow

From invite to shared spot

There's no open self-signup. An admin adds a resident by phone number; that phone number is the only thing that can ever sign in as that resident. First sign-in routes through a one-time setup screen before reaching the normal app.

01 · ADMIN Invite resident name · phone · unit · spot 02 · RESIDENT Signs in phone OTP or email 03 · FIRST SIGN-IN One-time setup confirm name + spot details 04 My Spot home screen 05 Share + schedule weekly + one-off UNRECOGNIZED NUMBER Rejected at OTP no admin has added this phone — “ask your admin to add it” ENFORCED IN PARALLEL Firestore security rules a resident can only ever write their own doc + spot
Resident invite → first sign-in → self-service spot sharing, with the two guard rails that keep it honest.
Permission model

What each role can actually touch

Admin — building manager

  1. Defines the garage: levels and stalls (floor/spot setup)
  2. Creates and edits the resident roster (name, phone/email, unit, spot)
  3. Can edit any spot's config — owner, unit, double-park, EV charger
  4. Signs in by phone or email

Resident

  1. Sees only their own spot and profile — never the roster or another spot
  2. Full self-service on their own spot: sharing toggle, weekly schedule, one-off windows, EV/double-park flags
  3. Own name is editable once, during first-time setup only
  4. Signs in by phone only (email sign-in is admin-only, by design)
  5. Read-only "Browse" tab to see the rest of the garage
Features

What's built

🅿️

Garage map

Admin-defined floors and stalls, rendered as top-down tiles with a car glyph colored by taken/free state, double-park stalls, EV and lock badges.

🪪

Resident directory

Full CRUD roster with a segmented phone/email switch and a role picker that's gated by role — users get phone-only, admins get either.

🗓️

Sharing schedule

Recurring weekly day/time chips via native DatePicker, plus one-off date-range windows for exceptions.

🔐

Rules-enforced ownership

Every write is checked against Firestore security rules — a resident's own doc, their own spot, nothing else — independent of what the UI allows.

🎨

Custom design system

"Deck / Industrial Signage" — stenciled display type, concrete-textured backgrounds, a rocker toggle instead of the system Toggle, die-cut role tags.

🚗

Stall detail

Owner, unit code, double-parking flag, EV charger, shareable toggle — all editable by an admin, or by the resident on their own spot.

Screens

Key views

ScreenWhat it's for
Login / OTPPhone OTP or admin email sign-in
Garage onboardingFirst-run wizard: level count → name floors → review → build
Garage mapAdmin's live view of every level and stall
Resident directory + formRoster CRUD, add/edit a resident
Resident setupOne-time onboarding after first invite sign-in
My SpotResident home — spot hero tile, share toggle, schedule summary
Spot configShared editor for owner/unit/double-park/EV/shareable — used by both roles
Schedule editorDay chips + time range + one-off date windows
Engineering notes

A few of the harder problems

A security rule that silently failed only in combination

Combining !callerIsAdmin() && callerOwnsSpot(spotId) in one allow update clause failed even though each half passed when tested alone. The fix was removing the redundant admin check entirely — admins already had a separate write rule, so the combined check was actively breaking resident writes. Found by testing against the live Firestore REST API with a real end-user ID token rather than trusting flaky simulator taps.

Admin create vs. self-signup are different rules

The original allow create rule only let a signed-in user create their own doc — fine for admin self-signup, but it meant an admin could never actually create someone else's resident doc under real rules. Fixed by adding a separate admin-only create clause.

Hand-edited Xcode project file

The project is built without the Xcode GUI touching project.pbxproj — every new Swift file needs four manual edits (build file, file reference, group, sources build phase) to actually compile and link.

Design system

"Deck / Industrial Signage"

Grounded in the literal subject — concrete surfaces, stenciled signage type, painted lines — built from the app's original accent orange.

Accent — deckAccentDim Ink Surface Line

Custom bundled fonts: Big Shoulders Display ExtraBold for stenciled headlines, IBM Plex Mono for labels and codes, IBM Plex Sans for body copy.

Next: Dog Schedule

An open, two-sided marketplace with live tracking, chat, and payments.

View case study →