Community-powered parking discovery for Aguascalientes (pilot).
ParkPulse is a map-first mobile app for finding and validating parking with community input. Users can sign in, explore parking places, report real-time availability, save favorite places, rate and review parking lots, and maintain their own profile with theme and avatar customization.
Finding parking is usually fragmented, stale, and frustrating. ParkPulse turns that into a lightweight community feedback loop: drivers can discover parking spots, check recent status signals, and contribute live updates that help the next user make a faster decision.
- React Native + Expo mobile app with Supabase backend
- Community reporting flow for
available,full, andclosed - Map-first UX with search, saved places, reviews, and profile customization
- Pilot-ready data model with seeded places, TTL-based status updates, and authenticated user activity
- The current demo assumes Supabase is configured and seeded.
- The project already includes seeded pilot places in Supabase for Aguascalientes.
- Place status updates currently rely on manual refresh plus periodic in-app refresh.
- Realtime subscriptions are not part of the current demo build.
- Email/password authentication with Supabase Auth
- Map-first parking exploration for Aguascalientes
- Rich place detail sheet with:
- live status
- last update
- report activity summary
- rating summary
- hours, pricing, capacity, and access details
- Search overlay with local filtering
- Parking place creation flow backed by Supabase RPCs
- Report submission flow with proximity information and TTL-based status expiry
- Review composer with star rating and optional comment
- Review list modal per parking place
- Saved places list per signed-in user
- Personal report history screen
- Editable profile/settings screen with:
- preferred name
- full name
- phone
- avatar URL
- profile photo upload from device to Supabase Storage
- local theme preference
Implemented:
- Authenticated app shell
- Persistent
places,place_reports,place_ratings, anduser_profiles - Storage bucket for user avatars
- Frontend flows for create place, report, save, review, and profile editing
- Data-layer test coverage across
src/lib - UI tests for key app flows
Still pending or intentionally incomplete:
- OTP / phone auth
- Admin moderation tools
- Stricter server-side reputation and anti-abuse controls
- Bot resistance and contributor reliability scoring
- Realtime subscriptions
- Reservations / payments
For the current demo build:
- authentication is email/password with Supabase Auth
- map data is expected to come from Supabase seed data and user-generated reports
- manual refresh is part of the intended live-data story during the pilot
The current Supabase bootstrap creates and uses:
user_profiles- profile data tied to
auth.users - fields include
email,phone,full_name,preferred_name,avatar_url
- profile data tied to
places- persistent parking lot catalog
- coordinates, description, pricing, hours, capacity, access type, and status
place_reports- availability reports from users or session actors
- TTL-based expiration per status
place_ratings- one rating/comment identity per place
place_live_status- frontend-friendly live place read model
place_report_feed- frontend-friendly report history read model
place_review_feed- frontend-friendly review feed
avatarsstorage bucket- profile images uploaded from the app
RPCs:
create_place(...)create_place_report(...)upsert_place_rating(...)- optional helper:
get_place_report_history(...)
- Pilot city: Aguascalientes
- Parking status options:
availablefullclosed
- TTL defaults:
available: 15 minutesfull: 30 minutesclosed: 12 hours
- Report proximity target:
- 200 meters in the current frontend flow
- Expo
- React Native
- TypeScript
react-native-maps@gorhom/bottom-sheetreact-native-gesture-handlerreact-native-reanimated- Supabase
- Auth
- Postgres
- Storage
- Jest
- React Native Testing Library
src/
components/
i18n/
lib/
navigation/
screens/
docs/
supabase/
assets/
Important areas:
- App.tsx: app root
- src/navigation/AppNavigator.tsx: auth-aware navigation
- src/screens/MapScreen.tsx: main product flow
- src/screens/ProfileSettingsScreen.tsx: profile/theme/avatar settings
- src/lib/places.ts: places API and normalization
- src/lib/reports.ts: reports API and normalization
- src/lib/reviews.ts: review feed reads
- src/lib/ratings.ts: rating writes
- src/lib/profiles.ts: profile reads/writes
- src/lib/avatarUploads.ts: device image picker + avatar upload
- supabase/bootstrap.sql: database and storage bootstrap
- Node.js 22 recommended
- npm
- Expo CLI through
npx - Optional:
- Android Studio
- Xcode
If you use nvm:
nvm usenpm installCreate a .env file from .env.example and set:
EXPO_PUBLIC_SUPABASE_URL=
EXPO_PUBLIC_SUPABASE_ANON_KEY=Do not commit .env.
npm run startIf native packages changed, use a clean Expo cache:
npx expo start -cIf Expo fails on startup with TypeError: fetch failed, the CLI is usually trying
to reach Expo's package metadata service before Metro starts. In that case, use:
npm run start:offlineThis keeps local development working when your network, proxy, firewall, or DNS blocks Expo's dependency check.
Run the SQL in supabase/bootstrap.sql inside Supabase SQL Editor.
Full setup guide:
The bootstrap sets up:
- profile sync from
auth.users - places schema and seed data
- report and rating tables
- frontend-oriented views
- avatar storage bucket
- RLS policies for profile data and avatar uploads
The current seeded demo data includes three pilot parking places in Aguascalientes.
The app now supports picking a profile picture from the device and uploading it to Supabase Storage.
Requirements in Supabase:
- bucket name must be exactly
avatars - bucket can be public for simple profile images
- storage policies must allow authenticated uploads
Current app upload path format:
<auth.uid()>/avatar.<ext>
The uploaded public URL is saved into:
public.user_profiles.avatar_url
If you migrated or rebuilt your Supabase project, rerun the latest supabase/bootstrap.sql so Storage policies and the bucket match the current app code.
npm run start: start Expo / Metronpm run start:offline: start Expo / Metro without Expo network checksnpm run android: open Android targetnpm run ios: open iOS targetnpm run web: open web targetnpm run lint: run ESLintnpm run typecheck: run TypeScript checksnpm test: run Jest
Current automated testing covers:
- normalized data and API behavior in
src/lib - navigation behavior
- key screen flows such as:
- map loading
- search
- save place
- create place
- submit report
- open reviews
- profile settings
- avatar upload helper
Important test files include:
src/lib/*.test.tssrc/navigation/AppNavigator.test.tsxsrc/screens/MapScreen.test.tsxsrc/screens/ProfileSettingsScreen.test.tsx
These are the main areas still needing work:
- stronger server-side rate limiting
- anti-troll review/report moderation
- reliability scoring for contributors
- bot detection / abuse prevention
- admin review tools
- better conflict resolution for place edits
- true realtime updates without manual refresh
If profile picture upload fails with:
new row violates row-level security policy
then the problem is usually in Supabase Storage setup, not the app UI.
Check:
- the
avatarsbucket exists - old conflicting storage policies are removed
- the latest bootstrap SQL has been applied
If npm or node fails before install, repair your Node environment or use
the version declared by .nvmrc.
- Create one branch per ticket
- Use conventional commits
Example:
feat(profile): add avatar upload flow
Proprietary for now.