Control Park is a mobile parking marketplace built with React Native and Expo. The app lets users browse parking listings, save favorites, reserve spots, manage vehicles and payment methods, message hosts, and track reservation activity from a phone-first interface.
The project also supports host-side workflows. In addition to browsing and booking, users can create and manage listings, review incoming booking requests, approve or reject reservations, and monitor their hosted parking activity from the same app.
- Overview
- What the App Does
- Core User Flows
- Tech Stack
- Architecture
- Project Structure
- API Integration
- Environment Variables
- Getting Started
- Scripts
- Testing and UI Documentation
- Key Design Decisions
- Known Gaps
Control Park approaches parking as a marketplace workflow rather than a static directory of available spaces.
The app is designed around two main personas:
- guests looking for parking
- hosts listing and managing parking inventory
That leads to a product with both consumer-facing and operational features:
- listing discovery
- reservation management
- host listing creation and editing
- payment method setup
- in-app messaging
- push notifications
- profile and account management
At a high level, Control Park provides:
- account creation, sign-in, email verification, and password reset flows
- searchable parking listings with pricing, availability, images, ratings, and saved state
- listing details with amenities, perks, incentives, and host information
- reservation creation and reservation history
- host-side approval, rejection, and management of booking requests
- guest/host messaging through conversations and message threads
- notification inbox and notification preference management
- payment-method setup for reservations
- host listing creation, draft saving, editing, and deletion
- vehicle management and profile management
- A user signs up or logs in with Supabase-backed authentication.
- The user browses listings from the mobile home screen.
- The user filters by price, availability, and sort order.
- The user views a listing in detail and saves it or starts a reservation.
- The user selects a vehicle and payment method, then creates a booking.
- The user tracks reservation status and can message the host when needed.
- A host creates or edits a listing with title, description, address, lot/structure details, access notes, price, perks, incentives, and images.
- The listing can be saved as a draft or published through the backend API.
- The host reviews incoming reservations and can approve or reject booking requests.
- The host monitors hosted reservations and profile-related listing state from host-oriented screens.
- The app registers an Expo push token for signed-in users.
- The client polls notification endpoints and also listens over WebSocket for near-real-time updates.
- New messages, booking requests, and reservation decisions trigger in-app notifications and route refreshes.
| Layer | Technology | Purpose |
|---|---|---|
| Mobile app | React Native 0.81, React 19, Expo 54 | Cross-platform mobile client |
| Language | TypeScript | Safer app and API integration logic |
| Navigation | React Navigation native stack | Screen routing across guest and host flows |
| Styling | NativeWind + Tailwind CSS | Utility-first styling for React Native |
| Data fetching | Axios, TanStack React Query | API requests, caching, and invalidation |
| Auth and session | Supabase JS | Authentication and session management |
| Local state | Zustand, Context | Favorites, reservations, payment methods, and auth session state |
| Notifications | Expo Notifications + WebSocket | Push registration and live updates |
| Media | Expo Image Picker, Expo File System | Listing/profile image capture and persistence |
| UI documentation | Storybook | Component exploration and UI testing scaffolding |
| Test scaffolding | Vitest + Playwright + Storybook addon | Browser-driven story tests |
This repository is the mobile client for the Control Park platform. It expects a backend API to be running separately, typically on port 9001 during development. The companion backend lives in E:/server/README.md.
+---------------------------+
| React Native / Expo app |
| guest + host workflows |
+-------------+-------------+
|
| HTTP / WebSocket
v
+---------------------------+
| Control Park backend API |
| listings, auth, bookings, |
| payments, messages, etc. |
+-------------+-------------+
|
v
+---------------------------+
| Supabase auth/session |
| + server-side data layer |
+---------------------------+
The source tree is organized around a few clear concerns:
src/screenscontains screen-level product flows such as home, reserve, notifications, host reservations, payment, and profile screenssrc/apicontains typed client wrappers around backend endpointssrc/contextcontains shared client state using React Context and Zustandsrc/componentscontains reusable UI building blockssrc/utilscontains Supabase configuration, auth helpers, image helpers, validation, and utility logicsrc/navigationdefines the app stack and navigation helpers
control-park/
assets/ # App icons, parking imagery, fonts, card logos
src/
api/ # API client modules for listings, reservations, payments, etc.
components/ # Reusable UI components
context/ # Auth, favorites, vehicles, reservations, payment-method state
data/ # Mock data used for development/UI work
Forms/ # Form components
hooks/ # Push notification and profile-related hooks
navigation/ # Stack navigator and navigation helpers
screens/ # Product screens for guest and host workflows
stories/ # Storybook stories and assets
types/ # Shared TypeScript types
utils/ # Supabase, validation, image persistence, auth helpers
.storybook/ # Storybook configuration
.rnstorybook/ # React Native Storybook support files
App.tsx # App root
app.json # Expo app configuration
package.json # Scripts and dependencies
The mobile app talks to a backend API through the modules in src/api.
Current endpoint groups used by the client include:
/auth/*for signup, signin, password reset, profile updates, email changes, and push token registration/listingsfor listing fetch, create, update, draft save, report, save/unsave, and host-owned listing queries/reservationsfor guest bookings, host booking review, booked ranges, and host stats/conversationsfor message threads and chat messages/paymentsfor setup intents and saved payment methods/notificationsfor in-app notifications and notification settings
The shared API client in src/api/client.ts automatically attaches the current Supabase access token to outbound requests when a session exists.
During development, the client attempts to infer the Expo dev host and target port 9001 automatically. If EXPO_PUBLIC_SERVER_URL points to a non-local environment, that value is used directly instead.
Backend setup details live in E:/server/README.md.
The checked-in .env.example currently includes:
EXPO_PUBLIC_SUPABASE_ANON_KEY=
EXPO_PUBLIC_SUPABASE_URL=
EXPO_PUBLIC_SERVER_URL=The current source code also references additional public variables:
EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEYEXPO_PUBLIC_PROJECT_ID
That means the example env file is currently incomplete and should be updated before treating it as canonical project setup.
Recommended local .env shape:
EXPO_PUBLIC_SUPABASE_URL=
EXPO_PUBLIC_SUPABASE_ANON_KEY=
EXPO_PUBLIC_SERVER_URL=http://localhost:9001
EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY=
EXPO_PUBLIC_PROJECT_ID=- Node.js 20+
- npm
- Expo-compatible iOS simulator, Android emulator, or physical device
- A running Control Park backend API
- A Supabase project configured for this app
# 1. Clone the repo
git clone https://github.com/Control-Park/control-park
cd control-park
# 2. Install dependencies
npm install
# 3. Create local environment config
cp .env.example .env
# 4. Fill in the required public environment variables
# 5. Start the Expo development server
npm startnpm run ios
npm run android
npm run webThe app assumes a backend server is reachable at:
- the value of
EXPO_PUBLIC_SERVER_URL, or - the current Expo host on port
9001during local development
Without the backend, the UI can still be explored, but data-backed flows such as authentication, listings, reservations, payments, and messaging will not function fully.
From package.json:
| Script | Command | Purpose |
|---|---|---|
npm start |
expo start |
Start Expo dev server |
npm run android |
expo start --android |
Open Android target |
npm run ios |
expo start --ios |
Open iOS target |
npm run web |
expo start --web |
Run web target |
npm run storybook-generate |
sb-rn-get-stories |
Generate React Native Storybook story index |
npm run storybook |
storybook dev -p 6006 |
Start Storybook |
npm run build-storybook |
storybook build |
Build static Storybook output |
This repository includes Storybook and Vitest configuration, but it does not currently expose a dedicated test script in package.json.
What is present today:
- Storybook configuration in
.storybook/and.rnstorybook/ - Story files under
src/stories/ - Vitest configuration in vitest.config.ts
- Playwright browser integration for Storybook-driven test runs
This suggests the project is set up for component-level UI documentation and story-based browser verification, even if the command surface is still lightweight.
Control Park is built around the reality that parking decisions often happen on the move. The app centers the phone experience rather than treating mobile as a secondary interface.
Instead of splitting guest and host workflows into separate apps, the repository supports both roles in one navigation model. That reduces duplication while keeping the product coherent.
Supabase manages session state on the client, and the shared Axios client injects bearer tokens automatically. This keeps downstream API modules smaller and more focused.
The app combines push token registration, in-app notification polling, and WebSocket updates. That is important for booking requests, reservation decisions, and conversation activity.
Listing image overrides are persisted locally to improve the mobile experience even when backend image behavior is still evolving. This helps preserve UX continuity during local development and demos.
These are worth documenting explicitly:
- This repository does not include the backend implementation, only the mobile client and API integration surface.
.env.exampleis missing some variables referenced by the codebase.- There is test scaffolding, but no first-class
npm testscript yet. - The repo currently has uncommitted changes in: src/navigation/AppNavigator.tsx src/screens/EditListingScreen.tsx src/screens/HostProfileScreen.tsx
Those gaps do not reduce the value of the project, but calling them out makes the documentation more trustworthy and more useful for collaborators.