A modern web application for real-time campus parking availability at UNC Charlotte. Built with React, Node.js, and MongoDB.
- Node.js 18+ (with npm)
- MongoDB 4.4+
- Git
# Clone repository
git clone <your-repo-url>
cd parkez
# Install frontend dependencies
npm install
# Install backend dependencies
cd server
npm install
cd ..Option A: Local MongoDB
# Install MongoDB (macOS)
brew install mongodb-community
brew services start mongodb-community
# Or install MongoDB (Ubuntu/Linux)
sudo apt-get install mongodb
sudo systemctl start mongodbOption B: Docker MongoDB
# Start MongoDB with Docker Compose
docker-compose up -dCreate .env file in project root:
# Backend API URL
VITE_API_BASE_URL=http://localhost:3000
# MongoDB Connection
MONGODB_URI=mongodb://localhost:27017
DB_NAME=ezpark
# OR for Docker:
# MONGODB_URI=mongodb://admin:password@localhost:27017/ezpark?authSource=admin
# JWT Secret (change in production)
JWT_SECRET=your-secret-key-change-in-production# Import parking data
cd server
npm run import
cd ..# Start both frontend and backend concurrently
npm run dev
# Backend: http://localhost:3000
# Frontend: http://localhost:5173Open browser to: http://localhost:5173
Default test account:
- Email:
[email protected] - Password:
password123
Or register a new account.
# Build and run production containers
docker-compose -f docker-compose.prod.yml up -d
# Application will be available on port 3000# Build frontend
npm run build
# Frontend build output: dist/
# Serve dist/ folder with any static file server
# Backend
cd server
NODE_ENV=production npm startNODE_ENV=production
MONGODB_URI=<your-production-mongodb-uri>
DB_NAME=ezpark
JWT_SECRET=<strong-secret-key>
PORT=3000parkez/
├── src/ # Frontend React application
│ ├── api.js # API client functions
│ ├── App.jsx # Main app component with routing
│ ├── main.jsx # React entry point
│ ├── components/
│ │ ├── CampusMap.jsx # Interactive 3D campus map
│ │ ├── SpotGrid.jsx # Parking spot visualization
│ │ ├── layout/ # Layout components (Header, Nav, etc)
│ │ └── ui/ # Reusable UI components
│ ├── contexts/ # React contexts (Auth, Theme, Preferences)
│ ├── pages/ # Route pages
│ │ ├── Dashboard.jsx # Main dashboard with map & current spot
│ │ ├── DeckSelection.jsx # List of parking decks
│ │ ├── LevelsView.jsx # Levels within a deck
│ │ ├── SpotAvailability.jsx # Individual parking spots
│ │ ├── QRScanner.jsx # QR code scanner
│ │ ├── Login.jsx & Register.jsx
│ │ ├── Profile.jsx
│ │ └── ReportStatus.jsx
│ ├── hooks/ # Custom React hooks
│ └── utils/ # Utility functions
│
├── server/ # Backend Node.js API
│ ├── index.js # Server entry point
│ ├── config/
│ │ └── database.js # MongoDB connection & schema
│ ├── middleware/
│ │ └── auth.js # JWT authentication
│ ├── routes/ # API endpoints
│ │ ├── auth.js # Login/register/logout
│ │ ├── decks.js # Parking decks
│ │ ├── levels.js # Deck levels
│ │ ├── spots.js # Parking spots & sessions
│ │ ├── reports.js # Issue reporting
│ │ └── users.js # User management
│ └── utils/ # Helper functions
│
├── mockData/ # Initial parking data (JSON)
├── public/ # Static assets
│ ├── images/ # Campus and deck images
│ └── qrcodes/ # QR codes for spots
├── scripts/ # Utility scripts
└── docker-compose.yml # Docker configuration
Interactive 3D map showing all parking decks on campus.
- Uses Maplibre GL for 3D rendering
- Clickable markers for each parking deck
- Navigate to Deck button opens device's maps app (Apple Maps on iOS, Google Maps on Android/Desktop)
- Navigates to deck levels when clicked
- Real GPS coordinates for accuracy
Displays parking spots in realistic deck layout.
- Vertical columns with central driving lane
- Color-coded spots:
- Green = Available
- Blue = Your occupied spot
- Red = Occupied by others
- Real-time updates every second
- Click to check-in/check-out
Main dashboard showing:
- Currently occupied spot (if any)
- Interactive campus map
- Quick navigation to all features
QR code scanner for quick check-in/check-out.
- Camera-based scanning
- Handles spot conflicts
- Works on mobile devices
Core functionality for parking spot management:
- GET
/api/spots/my-spot- Get current user's spot - POST
/api/spots/:id/check-in- Check in to a spot - POST
/api/spots/:id/check-out- Check out of a spot - POST
/api/spots/:id/toggle- Toggle spot status - Atomic operations prevent race conditions
- Tracks spot sessions and history
User authentication:
- POST
/api/auth/register- Create new account - POST
/api/auth/login- Login with JWT - POST
/api/auth/logout- Logout - GET
/api/auth/me- Get current user - Uses bcrypt for password hashing
- JWT tokens for session management
MongoDB connection and schema:
- Auto-creates 7 collections (decks, levels, spots, users, sessions, history, reports)
- Optimized indexes for fast queries
- Connection pooling for performance
- Spots page refreshes every 1 second
- Dashboard refreshes every 30 seconds
- Prevents race conditions with atomic DB operations
- Atomic
findOneAndUpdateprevents double-booking - Pre-check validation before check-in
- Clear error messages when spot is taken
- Responsive design for all screen sizes
- Fixed viewport prevents page zoom
- Safe area insets for notched devices
- Bottom nav bar always visible
- Touch-optimized interactions
- One-click navigation to parking decks from map
- Automatically detects device platform (iOS/Android/Desktop)
- Opens native maps app with turn-by-turn directions
- iOS: Opens Apple Maps
- Android: Opens Google Maps via geo URI
- Desktop: Opens Google Maps in browser
- JWT authentication on protected routes
- Password hashing with bcrypt
- User can only free their own spots
- Input validation on all endpoints
decks - Parking deck buildings
building-code,building-name,total-spaceslatitude,longitudefor map displayaliases,contacts,addressinfo
levels - Levels within each deck
_id,deckId,index,name
spots - Individual parking spaces
id,levelId,label,handicapuser_id(null = free, userId = occupied)available,occupiedAt
users - App users
email(unique),name,password(hashed)
spotSessions - Check-in/out sessions
spotId,userId,startedAt,endedAt
spotStateHistory - Audit log of spot changes
spotReports - User-reported issues
# Development
npm run dev # Start frontend + backend
npm run dev:frontend # Start frontend only
npm run dev:backend # Start backend only
# Production
npm run build # Build frontend for production
npm run preview # Preview production build
# Utilities
npm run kill:3000 # Kill process on port 3000
npm run kill:5173 # Kill process on port 5173
npm run kill:all # Kill both ports
# Backend
cd server
npm run dev # Start backend with auto-reload
npm run start # Start backend (production)
npm run import # Import parking data to MongoDB- React 19 - UI library
- React Router 7 - Client-side routing
- TanStack Query - Data fetching & caching
- Tailwind CSS - Utility-first styling
- Radix UI - Accessible components
- Maplibre GL - 3D mapping
- ZXing - QR code scanning
- Vite - Build tool
- Node.js - Runtime
- Fastify - Web framework
- MongoDB - Database
- JWT - Authentication
- bcryptjs - Password hashing
POST /api/auth/register- Create accountPOST /api/auth/login- LoginPOST /api/auth/logout- LogoutGET /api/auth/me- Get current user
GET /api/decks- List all decksGET /api/decks/:id/levels- Get levels in a deckGET /api/decks/:id/availability- Get deck availabilityGET /api/levels/:id/spots- Get spots in a levelGET /api/levels/:id/availability- Get level availability
GET /api/spots/my-spot- Get user's current spotPOST /api/spots/:id/check-in- Check in to spotPOST /api/spots/:id/check-out- Check out of spotPOST /api/spots/:id/toggle- Toggle spot status
POST /api/spots/:id/report- Report incorrect statusGET /api/reports- Get user's reports
- User registers with email/password
- Password is hashed with bcrypt (10 rounds)
- Login returns JWT token
- Token stored in localStorage
- Token sent in Authorization header:
Bearer <token> - Backend middleware validates token on protected routes
- Viewport locked - No accidental page zoom
- Safe area support - Works with notched devices
- Touch optimized - Large tap targets
- Responsive layout - Adapts to all screen sizes
- Bottom navigation - Always visible, never clipped
- Login to dashboard
- View interactive 3D campus map
- Click on a parking deck marker
- Optional: Click "Navigate to Deck" to open directions in your maps app
- Click "View Levels & Spots" to see deck details
- Select a level
- View available spots (green)
- Click spot to check-in
- Go to parking spot
- Tap "Scan" in bottom nav
- Scan QR code on parking sign
- Auto check-in/check-out
- View dashboard
- Click "Free This Spot" on occupied spot card
- Confirm action
- Spot becomes available to others
# Import mock data
cd server
npm run importRegister through the app or use:
- Email:
[email protected] - Password:
password123
- Spots auto-refresh every second for real-time availability
- Map uses free OpenStreetMap tiles (no API key needed)
- Race conditions prevented with atomic DB operations
- All times displayed in user's local timezone
- Mobile-first responsive design
Built by Scrum & Coke team for ITCS-8112 SSDI course project at UNC Charlotte.
ISC