ParkPin
A personal parking app that logs your spot by floor and zone and shows it on a home widget (iOS and Android) without opening the app - offline-first, local storage.
- React Native / Expo
- TypeScript
- Home Widget (iOS/Android)
- Offline-first
Onboarding - "never wander for your spot again." It leads with three things: tap-to-log, widget check, and per-vehicle saving
Home - the current spot shown large as "B3-A, next to the pillar," with the vehicle, lot, time, and map/share/leave buttons
Map - see the saved lot on a map and hand off to a maps app for directions
Tips - a set on parking etiquette, regulations, and plate privacy; the footer states these are general guidance and to defer to current rules
Lot setup - register floors and zones for a regular lot; outdoor parking saves straight as "outdoor" with no setup
History - entries, exits, and durations on a per-vehicle timeline (e.g. "parked 3h," "E-Mart P2-Strawberry")
My vehicles - register cars by license plate; with two or more, each car's spot is tracked separately
Share - turn the parking spot into an image card to send
Home widgets - check "B3-A, next to the pillar" right on the home screen without opening the app (multiple widget sizes)
Setup
- Problem
You forget where you parked and lose time finding the car. Regular lots (with a floor/zone structure) and unfamiliar places (department stores) need different ways to record, so a single method doesn't capture both well.
- Context
Started as a personal tool. Regular lots are logged structurally by floor and zone, unfamiliar places by a single free-text note, and each vehicle (license plate) is saved separately.
Build
- What I did
- Two ways to record - floor/zone taps for saved lots, a quick note for unfamiliar places
- Per-vehicle (license plate) location saving + Korean plate-format validation
- Home widget on both iOS and Android to check without opening the app - WidgetKit + App Group on iOS, react-native-android-widget on Android
- Offline-first local storage (AsyncStorage) - works without a network and survives app restarts
- Optional Supabase backend - accounts, social login, and cloud backup/sync; runs local-only when not configured
- Product decisions
- After parking, the screen keeps only the "I left" button and hides floor/zone/save - what you need when returning is a check, not a record
- The widget as the main entry point - checking your spot shouldn't even require opening the app, so it ends in two lines on the home screen
- Local-first - a personal parking spot must save and show instantly, even without a network or account; accounts and cloud sync sit on top as an optional Supabase backend, and it degrades to local-only when not configured
- QA considerations
- Where the widget and app split the same location data (iOS App Group) is the most regression-prone spot - the top priority is "does the location saved in the app always show correctly in the widget?"
- Offline-first - saves and shows instantly without a network or account, and survives an app restart
- Korean license-plate format validation is pinned by unit tests (the trust basis for per-vehicle saving)
- When optional Supabase sync isn't configured, it degrades cleanly to local-only
- Unit tests (jest) go first on storage, plate validation, display logic, and hooks to create a place to catch regressions
Outcome
- Metrics
- In closed testing on Android and iOS
- Pre public store release (store-listing materials in preparation)
- Landing/support page public at parkpin-app.pages.dev
Process (planning → build)
The same template from problem and hypothesis through scope, spec (SSOT), build, the QA gate, and release - how this was planned and driven.
Process (planning → build)
Problem & hypothesis
Started to remove the time lost re-finding where I parked. The hypothesis: regular lots (with a floor/zone structure) and unfamiliar places need different ways to record, so one screen forks into two input modes (structured log / quick note).
Skills · Problem framing · hypothesis
Scope & priority
Pinned the scope by numbering features FR-001 to FR-013. Kept widget, offline, and per-vehicle saving as the core and pushed map, share, and tips to a later tier to keep the initial scope narrow.
Skills · Scoping · prioritization
Spec-first (SSOT)
Wrote screens, behavior, and acceptance criteria into docs/ParkPin_SSOT.md first and let the implementation follow it. docs/ParkPin_Dev_Workflow.md fixed the dev routine so a solo build wouldn't drift.
Skills · Spec · documentation
Build & iteration
Stood up the core in React Native/Expo, added the home widget on both iOS (WidgetKit) and Android (react-native-android-widget), then layered an optional Supabase sync on top for users who want accounts and backup.
Skills · Execution · delivery
Verification (QA gate)
Unit tests (jest) went first on storage, plate validation, display logic, and hooks. Since the widget and app hold the same location data across processes - the spot most prone to regressions - that state sync was the top verification priority.
Skills · Quality · risk
Release
Configured store submission via EAS; currently in closed testing on iOS and Android. A landing/support page is public at parkpin-app.pages.dev.
Skills · Release
- Tech stack
- React Native (Expo SDK 56)
- TypeScript
- iOS WidgetKit
- react-native-android-widget
- AsyncStorage
- Supabase