parkingspotswap

Parking Spot Swap

Give a Spot, Get a Spot - A community-powered parking spot exchange app.

Overview

Parking Spot Swap is a free mobile app that helps drivers find parking by connecting those leaving spots with those looking for them. Users earn credits by offering their parking spots and spend credits to locate available parking nearby.

Core Features

Authentication & Onboarding

Email Workflows

The app includes a comprehensive email notification system:

Email Categories:

Automatic Email Triggers:

Deep Links: All email links use web fallback URLs (https://parkingspotswap.com/app/...) that:

Web Fallback Pages: Static HTML pages are provided in /public/app/ for desktop users who click email links:

Each page displays a branded confirmation message with App Store download link. Important: These pages must be deployed to https://parkingspotswap.com/app/ for email links to work on desktop.

Monthly Report Emails: The app automatically tracks user activity and can send monthly summary emails:

Report Contents:

Transaction Receipt Emails: The app automatically sends Stripe-branded receipt emails for all monetary transactions:

Features:

Screens:

Email Provider (Mailrelay): To enable real email sending, configure Mailrelay in the ENV tab:

  1. EXPO_PUBLIC_MAILRELAY_API_KEY - Your Mailrelay API key (from Settings > API Keys in Mailrelay dashboard)
  2. EXPO_PUBLIC_MAILRELAY_ACCOUNT - Your Mailrelay account subdomain (e.g., “mycompany” from mycompany.ipzmarketing.com)
  3. EXPO_PUBLIC_MAILRELAY_FROM_EMAIL - Default sender email address (e.g., “noreply@parkingspotswap.com”)
  4. EXPO_PUBLIC_MAILRELAY_FROM_NAME - Default sender name (e.g., “Parking Spot Swap”)

Without these credentials, emails are logged locally but not sent.

Credit Economy

Spot Notes

When offering a spot or dropping a pin, users can add optional notes to help others find the exact location:

Notes are displayed on the spot card and navigation screen to help drivers find the exact spot.

Key Screens

Pricing & Fees Structure

When a user requests a hold, the following fees apply:

Charged to Hold Requester: | Fee Type | Rate | Example (5 min hold in NYC) | |———-|——|———————| | Base Hold Fee | $2.00/minute | $10.00 | | Service Fee | 5% of base | $0.50 | | Taxes | Varies by location (destination-based) | $0.93* | | Total Charged | | $11.43* |

*Tax rate varies by state, county, and municipality. Example uses NYC rate of 8.875%.

Spot Holder Earnings: | Item | Rate | Example (5 min hold) | |——|——|———————| | Base Amount | $2.00/minute | $10.00 | | Platform Fee | -5% of base | -$0.50 | | Net Earnings | | $9.50 |

Platform Revenue:

Payment Validation for Holds

Both parties must have payment methods set up to use the paid hold feature:

For Hold Requesters (Drivers):

For Spot Holders:

Hold Extension System

When a hold is about to expire, the requesting user can request an extension:

Hold Monitoring & Dispute Resolution

The app monitors spot holders during active holds and handles disputes:

Spot Holder Movement Monitoring:

Proximity Alerts:

Dispute Resolution (Spot Reported Unavailable During Hold):

Payment Split Logic (50% for Wait Time):

Vehicle Information Sharing

When claiming an offered spot or requesting a hold:

Payment Settings

Stripe Connect Integration

The app uses Stripe Connect for marketplace payments between users:

Payment Flow:

  1. Authorization: When a hold is confirmed, payment is authorized (not captured)
  2. Capture: Payment is only captured when the driver successfully parks
  3. Prorated Billing: Early arrival means lower charges - only pay for actual time used
  4. Cancellation: No charge if hold is cancelled or spot is unavailable

For Drivers (Requesters):

For Spot Holders:

Environment Variables Required:

EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_... (or pk_live_... for production)
EXPO_PUBLIC_STRIPE_SECRET_KEY=sk_test_...     (backend only, never expose client-side)
EXPO_PUBLIC_API_URL=https://your-backend.com  (for production API calls)

Test Mode:

Admin Panel (Role-Based Access)

Trust & Safety

Technical Stack

Frontend (Mobile App)

Backend (Server)

Backend Architecture

The server is located in the /server directory and provides the following:

API Endpoints

Authentication (/api/auth)

Users (/api/users) - Requires authentication

Admin (/api/admin) - Requires admin/owner role

Stripe Payments (/api/stripe)

Platform Fees Analytics (GET /api/admin/platform-fees)

Query params: ?range=7d|30d|90d|all (default: 30d)

Returns comprehensive platform fee data:

User Roles

Database Schema

users - User accounts with roles and stats

transactions - Credit and monetary transactions

fraud_reports - User fraud reports

audit_logs - Admin action logs

stripe_customers - Stripe customer records (for hold requesters)

stripe_connect_accounts - Stripe Connect accounts (for spot holders)

hold_payments - Payment tracking for holds

Running the Backend

cd server
bun install           # Install dependencies
bun run db:init      # Initialize database tables
bun run db:seed-admin # Seed initial admin users
bun run dev          # Start development server

Default Admin Credentials

After seeding, the following admin account is created:

Production Deployment Steps

  1. Change Admin Password: Edit server/src/db/seed-admin.ts and update the password:
    {
      email: 'info@parkingspotswap.com',
      password: 'YourSecurePasswordHere!', // Use a strong password
      displayName: 'System Owner',
      role: 'owner',
    }
    
  2. Set JWT Secret: Create a .env file in the server folder or set the environment variable:
    JWT_SECRET=your-very-long-random-secret-key-here
    

    Generate a secure secret with: openssl rand -base64 64

  3. Initialize Production Database:
    cd server
    bun run db:init
    bun run db:seed-admin
    
  4. Connect Mobile App: Update the mobile app to point to your production backend URL by setting the API base URL in your app configuration.

  5. Configure Stripe (required for payments):
    # Add to server/.env
    STRIPE_SECRET_KEY=sk_live_...              # Your Stripe secret key
    STRIPE_WEBHOOK_SECRET=whsec_...            # Webhook signing secret
    APP_URL=https://your-app-scheme://         # Deep link URL scheme
    

    Stripe Dashboard Setup:

    1. Create a Stripe account at stripe.com
    2. Enable Stripe Connect in your dashboard
    3. Set up a webhook endpoint at https://your-api.com/api/stripe/webhooks
    4. Subscribe to events: account.updated, payment_intent.succeeded, payment_intent.payment_failed
    5. Get your webhook signing secret

    Mobile App Configuration:

    # Add to mobile app .env
    EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...
    EXPO_PUBLIC_API_URL=https://your-api.com
    
  6. Secure the Database: In production, consider:
    • Using PostgreSQL instead of SQLite for better concurrency
    • Setting up database backups
    • Using HTTPS for all API endpoints

Haptic Feedback

The app uses haptic feedback throughout for a premium feel:

Haptic Type Usage
Light Impact Close buttons, navigation links, tab switching, toggle switches, sort filters
Medium Impact Share actions, spot selection on map, image picker
Heavy Impact Primary action buttons (Find Spot, Navigate, Start Offering)
Selection Filter/sort option changes
Success Parking confirmed, spot offer completed, pin drop submitted
Warning Spot reported as taken
Error Not enough credits, movement detected during offer

Project Structure

src/
├── app/                    # Expo Router screens
│   ├── (tabs)/            # Tab navigation
│   │   ├── index.tsx      # Find screen
│   │   ├── offer.tsx      # Offer spot screen (default landing)
│   │   ├── activity.tsx   # Activity/credits screen
│   │   └── profile.tsx    # Profile screen
│   ├── auth.tsx           # Sign in/sign up screen
│   ├── onboarding.tsx     # New user onboarding guide
│   ├── find-spot.tsx      # Find parking flow
│   ├── navigate-spot.tsx  # Navigate to spot
│   ├── drop-pin.tsx       # Drop pin for open spot (with validation)
│   ├── payment-settings.tsx # Payment methods and bank account setup
│   ├── vehicle-management.tsx # Manage saved vehicles
│   ├── admin-dashboard.tsx # Admin panel for user/system management
│   ├── dev-role-assign.tsx # Development tool to assign admin roles
│   ├── terms.tsx          # Terms of Service
│   ├── privacy.tsx        # Privacy Policy
│   └── help.tsx           # Help & FAQ
├── components/            # Reusable UI components
└── lib/
    ├── state/             # Zustand stores
    │   ├── types.ts       # TypeScript interfaces
    │   ├── user-store.ts  # User & credits state
    │   └── spot-store.ts  # Parking spots state
    └── cn.ts              # className merge utility

Credit Transactions

Action Credits
Offer parking spot +1
Navigate to found spot -1
Report spot unavailable (legitimate) +2 (refund + bonus)
Pin drop reward +1
Referral signup +3
Power user bonus +2

Future Enhancements

App Store Readiness

Compliance Checklist

App Store Submission Checklist

Before Submission:

  1. ☐ Host external legal documents (see /legal folder):
    • legal/terms-of-service.html → Your website URL
    • legal/privacy-policy.html → Your website URL
  2. ☐ Add URLs to App Store Connect:
    • Privacy Policy URL
    • Terms of Service URL
  3. ☐ Update app.json (via Vibecode settings):
    • App name: “Parking Spot Swap”
    • Add NSLocationWhenInUseUsageDescription: “Your location is used to show nearby parking availability and verify parking spot contributions.”
  4. ☐ Prepare App Store metadata:
    • App description (see below)
    • Screenshots (real app UI)
    • Keywords

Recommended App Store Description:

Parking Spot Swap - Give a Spot, Get a Spot

Find parking faster with community help. When you're leaving a spot, let others know. When you need parking, see what's available nearby.

HOW IT WORKS:
• Offer Your Spot - Leaving? Share your spot and earn credits
• Find a Spot - Browse nearby available parking on the map
• Drop a Pin - See an empty spot? Mark it for others

EARN & SPEND CREDITS:
• Earn credits by helping others find parking
• Spend credits to navigate to available spots
• No subscriptions, no paywalls - just community sharing

OPTIONAL PAID HOLDS:
• Need extra time? Pay to hold a spot while you drive there
• $2/minute with transparent pricing
• Only pay for actual time used

TRUST & SAFETY:
• Reliability scores show trustworthy contributors
• GPS verification prevents false reports
• Community-powered fraud prevention

Start earning credits today by sharing your parking spot!

Apple Review Notes (copy this):

Parking Spot Swap is a community-powered parking availability app. Users earn credits by contributing parking information (offering their spot when leaving or dropping pins for open spots they see). Users may optionally spend credits to navigate to available spots. For offered spots during verification countdown, users may optionally pay other users to hold the spot at $2/min with a 5% platform fee. No subscriptions or paywalls are used. Credits cannot be purchased and have no cash value.

User Feedback System

Running the App

The app runs automatically on port 8081 via Expo. View it through the Vibecode platform.

QC/QA - Production Readiness

Recent Quality Improvements (v1.0.0)

Architecture Strengths

Known Limitations (Future Improvements)

  1. Backend Required: Email/password updates simulate API calls - connect to real backend for production
  2. Mock Data: Some screens use hardcoded San Francisco coordinates for demo
  3. Email Tokens: Client-side token generation should be server-side for production security
  4. Network Detection: No offline mode or network state management yet

Production Readiness Guide

This section outlines everything needed to take the app from development to production.

What’s Implemented (Frontend Ready)

Feature Status Notes
All UI/UX screens ✅ Complete Fully polished mobile interface
API Client Layer ✅ Complete src/lib/api/ with JWT auth, error handling
Authentication Flow ✅ Complete Login, signup, 2FA verification via API
2FA Setup & QR Code ✅ Complete Real TOTP QR codes for authenticator apps
Push Notifications ✅ Complete Registration, handling, deep linking
Email Integration ✅ Complete SendGrid configured and sending
Stripe Client ✅ Complete Payment method management, Connect flows
Local Data Persistence ✅ Complete Zustand + AsyncStorage
Vehicle Management ✅ Complete Add/edit/delete vehicles
Spam Detection ✅ Complete Activity tracking and scoring
Admin Dashboard UI ✅ Complete Full interface built

What Needs Backend Implementation

The frontend API layer is complete with mock responses for development. To go live, you need to implement the actual backend endpoints.


YOUR TASKS (Owner’s Action Items)

1. Set Environment Variables (Required)

Go to the ENV tab in Vibecode and add these variables:

# Required for production
EXPO_PUBLIC_API_URL=https://your-backend-api.com

# Stripe (already set for test mode, update for production)
EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_your_key_here

# Push Notifications (Expo)
# These are set up automatically when you build for production via EAS

2. Build Your Backend API

You need a backend server that implements these endpoints. Here’s what each endpoint should do:

Authentication Endpoints (/api/auth/)

Endpoint Method Description Request Body Response
/register POST Create new user {name, email, password, referralCode?} {user, accessToken, refreshToken}
/login POST Sign in user {email, password} {user, accessToken, refreshToken, requires2FA?, tempToken?}
/verify-2fa POST Verify 2FA code {tempToken, code, isBackupCode?} {user, accessToken, refreshToken}
/2fa/setup POST Generate 2FA secret - {secret, qrCodeUri, backupCodes}
/2fa/confirm POST Confirm 2FA setup {code} {success, backupCodes}
/2fa/disable POST Disable 2FA {password, code} {success}
/refresh POST Refresh tokens {refreshToken} {accessToken, refreshToken}
/password-reset/request POST Request reset email {email} {success, message}
/password-reset/confirm POST Reset password {token, newPassword} {success}
/change-password POST Change password {currentPassword, newPassword} {success}
/logout POST Invalidate tokens - {success}

User Endpoints (/api/users/)

Endpoint Method Description
/me GET Get current user profile
/me PATCH Update profile (displayName, profileImage)
/me/email POST Update email (requires password)
/me/delete POST Delete account (requires password)

Spots Endpoints (/api/spots/)

Endpoint Method Description
/ GET Search nearby spots (query: lat, lng, radius, limit)
/ POST Create/offer a new spot
/:id GET Get spot by ID
/:id/verify POST Verify spot availability
/:id/claim POST Claim a spot
/:id/report-unavailable POST Report spot unavailable
/:id/confirm-parking POST Confirm successful parking
/:id/cancel POST Cancel spot offer
/mine GET Get user’s offered spots
/claimed GET Get user’s claimed spots

Hold Requests (/api/hold-requests/)

Endpoint Method Description
/:id/accept POST Accept hold request
/:id/decline POST Decline hold request
/:id/complete POST Complete hold (user parked)
/:id/cancel POST Cancel hold request
/:id/extend POST Request extension
/mine GET Get my hold requests
/incoming GET Get incoming hold requests

Referrals (/api/referrals/)

Endpoint Method Description
/validate POST Validate referral code
/claim POST Claim referral bonus
/my-code GET Get user’s referral code
/stats GET Get referral statistics

Notifications (/api/notifications/)

Endpoint Method Description
/register POST Register push token
/unregister POST Unregister push token
/preferences GET/PATCH Get/update notification preferences
/history GET Get notification history
/:id/read POST Mark notification read
/read-all POST Mark all as read

Admin (/api/admin/)

Endpoint Method Description
/stats GET Get platform statistics
/flagged-users GET Get flagged users list
/users/:id GET Get user details
/users/:id/clear-restriction POST Clear user restriction
/users/:id/suspend POST Suspend user
/users/:id/unsuspend POST Unsuspend user
/users/:id/role POST Update user role
/users/:id/credits POST Adjust user credits
/issues GET Get issue reports
/issues/:id PATCH Update issue status
/audit-log GET Get audit log
/users/search GET Search users

3. Set Up External Services

Stripe (Payments)

  1. Create a Stripe account at stripe.com
  2. Enable Stripe Connect for marketplace payments
  3. Get your API keys from the Stripe Dashboard
  4. Set up webhooks at https://your-api.com/api/stripe/webhooks
  5. Subscribe to events:
    • account.updated
    • payment_intent.succeeded
    • payment_intent.payment_failed

Backend environment variables needed:

STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...

Push Notifications (Expo)

  1. Your Expo project is already configured
  2. When you build for production via EAS, push notifications work automatically
  3. For custom server-side sending, use the Expo Push API:

SendGrid (Emails)

Already configured! Make sure these are set in ENV tab:

EXPO_PUBLIC_SENDGRID_API_KEY=SG.xxx
EXPO_PUBLIC_SENDGRID_FROM_EMAIL=noreply@parkingspotswap.com
EXPO_PUBLIC_SENDGRID_FROM_NAME=Parking Spot Swap

4. Database Requirements

Your backend database needs these tables:

-- Users
CREATE TABLE users (
  id TEXT PRIMARY KEY,
  email TEXT UNIQUE NOT NULL,
  password_hash TEXT NOT NULL,
  display_name TEXT,
  role TEXT DEFAULT 'user',
  credits INTEGER DEFAULT 0,
  reliability_score INTEGER DEFAULT 100,
  referral_code TEXT UNIQUE,
  spam_score INTEGER DEFAULT 0,
  is_restricted BOOLEAN DEFAULT FALSE,
  is_suspended BOOLEAN DEFAULT FALSE,
  two_fa_enabled BOOLEAN DEFAULT FALSE,
  two_fa_secret TEXT,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Spots
CREATE TABLE spots (
  id TEXT PRIMARY KEY,
  latitude REAL NOT NULL,
  longitude REAL NOT NULL,
  status TEXT DEFAULT 'pending',
  offered_by TEXT REFERENCES users(id),
  claimed_by TEXT REFERENCES users(id),
  notes TEXT,
  expires_at TIMESTAMP,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Referrals
CREATE TABLE referrals (
  id TEXT PRIMARY KEY,
  referrer_id TEXT REFERENCES users(id),
  referred_user_id TEXT REFERENCES users(id),
  status TEXT DEFAULT 'pending',
  credits_awarded INTEGER DEFAULT 0,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Push Tokens
CREATE TABLE push_tokens (
  id TEXT PRIMARY KEY,
  user_id TEXT REFERENCES users(id),
  token TEXT NOT NULL,
  platform TEXT,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Add indexes for performance
CREATE INDEX idx_spots_location ON spots(latitude, longitude);
CREATE INDEX idx_spots_status ON spots(status);
CREATE INDEX idx_users_email ON users(email);

5. Security Checklist

Before going live:

6. Testing Checklist

Before submitting to App Store:


Quick Start for Backend Development

If you’re building the backend yourself, here’s a recommended tech stack:

Option 1: Node.js + Express

npm init -y
npm install express cors bcryptjs jsonwebtoken stripe

Option 2: Firebase

Option 3: Supabase

The frontend is already set up to work with any REST API. Just implement the endpoints described above and set EXPO_PUBLIC_API_URL to your server URL.


Summary

Category Status Your Action
Frontend App ✅ Complete None needed
API Client ✅ Complete None needed
Push Notifications ✅ Complete Works automatically with EAS builds
Email Service ✅ Complete Already configured
Supabase Backend Connected Tables created, API integrated
Stripe Connect Connected ENV variable set
Database ✅ Complete Supabase PostgreSQL

Backend Integration Status (COMPLETED)

The app is now connected to your Supabase backend!

Environment Variables Configured

What’s Connected

| Service | Status | Details | |———|——–|———| | Authentication | ✅ Live | Supabase Auth (email/password) | | User Profiles | ✅ Live | Auto-created on signup with referral codes | | Parking Spots | ✅ Live | Create, search, claim spots | | Transactions | ✅ Live | Credit tracking with history | | Referrals | ✅ Live | Validate codes, award credits | | Hold Requests | ✅ Live | Create, accept, decline, complete | | Vehicles | ✅ Live | Save and manage vehicles |

Database Tables Created

All tables are set up in your Supabase project:

Row Level Security (RLS)

RLS is enabled on all tables with policies for:

What’s Ready for Production

  1. ✅ Users can sign up and sign in
  2. ✅ Users can offer parking spots
  3. ✅ Users can find and claim spots
  4. ✅ Credits are tracked and persisted
  5. ✅ Referral codes work
  6. ✅ Hold requests are saved

Demo Mode for App Store Review

The app includes mock parking spots for testing purposes. All users can see and interact with these mock spots to test the app’s functionality.

Mock Spots (Visible to All Users): | Spot | Type | Status | Hold Available | Description | |——|——|——–|—————-|————-| | Demo Alex | Offered | pending | Yes | Within 1-minute hold period - “Request Paid Hold” button visible | | Demo Sarah | Offered | pending | Yes | Within 1-minute hold period - “Request Paid Hold” button visible | | Demo Mike | Offered | available | No | Past 1-minute hold period - Navigate only | | Demo Chris | Pin Drop | available | No | Pin drops never have hold option | | Demo Jordan | Offered | available | No | Past 1-minute hold period - Navigate only |

Demo Account (For App Store Reviewers):

Demo Mode Features for Demo Account:

How Hold a Spot Works:

  1. Offering User Flow: When someone offers their parking spot, a 1-minute countdown starts
  2. During Countdown (status: pending): Requesting users who select this spot see the “Request Paid Hold ($2/min)” button
  3. After Countdown (status: available): The spot becomes generally available; Hold is no longer an option
  4. Payment Requirement: Both parties must have payment set up - requester needs a card, holder needs a bank account

Demo Disclaimer Banner:

Production Status - ALL COMPLETE ✅

1. Stripe Production Setup ✅

| Component | Status | Details | |———–|——–|———| | Publishable Key | ✅ LIVE | pk_live_51SjWVt... | | Secret Key | ✅ LIVE | sk_live_51SjWVt... | | Webhook | ✅ Active | playful-jubilee endpoint configured | | Edge Functions | ✅ Deployed | All Stripe functions deployed to Supabase | | Secrets | ✅ Set | STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET configured |

Real card payments are now enabled in production.

2. Email System ✅

| Component | Status | Details | |———–|——–|———| | SendGrid API | ✅ Connected | API key configured | | Domain Auth | ✅ Verified | em9522.parkingspotswap.com | | Link Branding | ✅ Verified | url6643.parkingspotswap.com | | Sender Email | ✅ Ready | no-reply@parkingspotswap.com | | Supabase Template | ✅ Correct | Uses `` |

Email confirmations are working in production.

3. Database & Auth ✅

| Component | Status | |———–|——–| | Supabase Connection | ✅ Connected | | User Authentication | ✅ Working | | RLS Policies | ✅ Enabled | | All Tables | ✅ Created |

4. Ready for App Store


Production Checklist - COMPLETE