← Back to all work
Case study

Dog Schedule

A native Swift/UIKit + Firebase iOS app for a community of dog owners: list your dogs, offer to walk other people's, book someone nearby to walk yours, track the walk live on a map, and chat with whoever you're working with. There's no fixed "owner" vs. "walker" role — every account can do both, and money is entirely opt-in.

Platform
iOS · UIKit (programmatic)
Backend
Firebase (Auth, Firestore, Storage, Functions)
Auth
Email · Google · Apple · Phone · Guest
Design system
"Organic" — cream / terracotta / sage, custom, from scratch
The problem

Overview

Dog Schedule turns "can you walk my dog" between neighbors into a real product: a community list of nearby people, a booking flow with confirmation and reschedule/rate negotiation, live GPS tracking with poo/pee/pin logging during the walk, a walk report sent to the owner afterward, ratings, and running earnings for anyone who charges. Every account can list dogs and offer to walk — there's no fixed role split, which shaped almost every screen to be direction-agnostic rather than role-gated.

How it works

Two neighbors, one dog, no fixed roles. Either person can be the one asking or the one walking — the same account does both, so there's no separate "owner" app and "walker" app to design, build, or explain.

This is the actual walker-and-dog illustration from the app's own "Organic" design source file — reused here rather than redrawn, to keep the case study honest about what the real design system looks like.

Flat illustration of a person walking a dog on a leash, in the app's Organic design system style
Getting in

Five ways in, one account model

Email/password, Google, Apple, and phone number all create an account transparently on first use — no separate sign-up step. A fifth path, guest browsing, skips auth entirely and upgrades into a real account later without losing anything.

Email + password Google Sign in with Apple Phone number (SMS OTP) Continue without login ACCOUNT Created transparently no separate sign-up step guest → linked in place, nothing lost
All four real providers land on the same account model. Guest sessions upgrade via Firebase Auth account linking — dogs and history added as a guest carry over.
Core flow

Booking a walk, either direction

There's no fixed "who can ask whom" — either side can be the requester. A request becomes one order-summary screen that adapts its buttons to whatever's actually actionable, and either party can renegotiate time or rate at any point before it's done.

01 Browse Community 02 Request a walk 03 Order summary Confirm / Decline or Accept a rate 04 Start walk live map · poo/pee/pin 05 Walk report sent to the owner 06 Rating 1–5 ★ EITHER SIDE, ANYTIME Propose a new time or rate — Accept / Decline / Withdraw
Requesting, tracking, reporting, and rating a walk — with reschedule and rate negotiation as an independent side-loop rather than a blocking step.
Features

What's built

🐕

Manage Dogs

Photo-forward grid of your dogs; a dog can be shared with someone from your conversations so they can walk it solo without becoming a co-owner.

🗺️

Live walk tracking

MapKit + Core Location distance/duration tracking, with Poo, Pee, and Drop Pin logging that all surface on the walk's history map afterward.

💬

Chat

Real-time Firestore-backed conversations, photo and document attachments, and tappable system messages that jump straight to the related walk/request.

💰

Availability & earnings

Opt-in hourly rate, a recurring or calendar-range weekly schedule, and an earnings chart computed from each walk's actual agreed rate — never a flat estimate.

🔔

Push notifications

Cloud Functions send one notification per event — new message, new request, confirmed/declined, walk started, report sent, rating submitted.

🌐

Full localization

English and Hebrew via a String Catalog, ~540 strings, including right-to-left layout — follows the device setting or an in-app override.

🔒

Face ID app lock

Opt-in, device-local lock shown on cold launch and on returning from background — the one place biometrics adds real protection since Firebase Auth otherwise re-signs in silently.

📤

Download my data / delete account

A full JSON export of everything tied to your account via the system share sheet, entirely on-device — the non-destructive counterpart to account deletion.

🌙

Night Mode

A live in-app dark theme independent of system Dark Mode — every design-system color resolves to a light/dark pair, flipped with no restart needed.

Screens

Key views

ScreenWhat it's for
Home ("Community")Quick actions, nearby people preview, upcoming/recent walks in both directions
Community listEveryone nearby with an availability badge and filter pills
Person profileStats, bio, weekly availability, "Ask them to walk" / "Message"
Request a walkPick dog(s), date/time, note, "I'll come too", propose a rate
Order summaryOne screen for every request status, either direction
Active walk (map)Live tracking + poo/pee/pin logging
Walk reportStats, route sketch, photos, note — reviewed before sending
Manage Dogs / Dog ProfileAdd, edit, delete, and share a dog
Availability & rateOpt-in walking, hourly rate, recurring or calendar schedule
EarningsMonthly total + Sun–Sat bar chart
Chat list / threadLive conversations, photo/document attachments
Profile hub (Settings)Edit profile, Face ID lock, Night Mode, data export, delete account
Engineering notes

A few of the harder problems

Two independent proposal types on one booking

A reschedule proposal (proposedDate/proposedByUid) and a rate proposal (proposedRate/rateProposedByUid) are tracked as separate field pairs, so one outstanding time proposal and one outstanding rate proposal — even from two different people — never clobber each other's attribution.

Guest sessions that don't lose data

Browsing without an account starts a real anonymous Firebase Auth session. Signing up later upgrades that same session in place via Firebase's account-linking, rather than starting over — dogs added and walks taken as a guest carry through untouched.

Hebrew / RTL as a first-class layout, not an afterthought

Full right-to-left support via a String Catalog (~540 strings), with a real gotcha around how String(localized:) keys strings that contain interpolation — documented as a standing gotcha for anyone adding new user-facing copy.

Push notifications depend on a chain outside the code

Without an APNs Authentication Key configured in the Firebase console, every send fails with a third-party-auth error even though client-side registration looks completely fine — a failure mode that's invisible from the client alone.

Design system

"Organic"

A warm, hand-drawn-feeling visual language across the entire app — pill-shaped components, a full color ramp, and a complete Night Mode counterpart for every token.

Cream Terracotta Sage Ink

Bundled fonts: Outfit for headings, Figtree for body copy.

Next: Parking Share

A tight, permissioned system for a physical space — rules enforced end to end.

View case study →