# πŸ—οΈ Smart Parking Finder - System Architecture Documentation ## πŸ“‹ Table of Contents 1. [System Overview](#system-overview) 2. [Architecture Patterns](#architecture-patterns) 3. [Technology Stack](#technology-stack) 4. [Data Structure & Schema](#data-structure--schema) 5. [System Design](#system-design) 6. [API Documentation](#api-documentation) 7. [Database Design](#database-design) 8. [Security & Performance](#security--performance) --- ## 🎯 System Overview ### Project Description Smart Parking Finder is a real-time parking management system that helps users find available parking spots in urban areas. The system provides interactive mapping, route optimization, and real-time availability tracking. ### Core Features - πŸ—ΊοΈ Interactive map with OpenStreetMap integration - πŸ” Real-time parking spot search - 🧭 GPS-based navigation and routing - πŸ“± Responsive web application - πŸ”„ Real-time data synchronization - πŸ“Š Analytics and reporting ### System Goals - **Performance**: Sub-second response times for searches - **Scalability**: Support 10,000+ concurrent users - **Reliability**: 99.9% uptime availability - **Usability**: Intuitive interface for all user types --- ## πŸ›οΈ Architecture Patterns ### 1. Microservices Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Client Layer β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Next.js Frontend (React 18 + TypeScript + Tailwind CSS) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ API Gateway β”‚ β”‚ (NestJS Router) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β” β”‚ Auth Service β”‚ β”‚ Parking Service β”‚ β”‚Routing Serviceβ”‚ β”‚ (JWT) β”‚ β”‚ (CRUD + Search) β”‚ β”‚ (Valhalla) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Data Layer β”‚ β”‚ PostgreSQL + Redisβ”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### 2. Layered Architecture - **Presentation Layer**: Next.js React Components - **Business Logic Layer**: NestJS Services & Controllers - **Data Access Layer**: TypeORM Repositories - **Database Layer**: PostgreSQL with Redis Cache ### 3. Event-Driven Architecture - Real-time updates using WebSocket connections - Event sourcing for parking availability changes - Message queuing for background tasks --- ## πŸ› οΈ Technology Stack ### Frontend Stack ```json { "framework": "Next.js 14", "runtime": "React 18", "language": "TypeScript 5.x", "styling": "Tailwind CSS 3.x", "mapping": "React Leaflet + OpenStreetMap", "state": "React Query (TanStack Query)", "forms": "React Hook Form", "testing": "Jest + React Testing Library" } ``` ### Backend Stack ```json { "framework": "NestJS 10", "runtime": "Node.js 18+", "language": "TypeScript 5.x", "database": "PostgreSQL 15", "cache": "Redis 7", "orm": "TypeORM", "authentication": "JWT + Passport", "validation": "Class Validator", "documentation": "Swagger/OpenAPI", "testing": "Jest + Supertest" } ``` ### Infrastructure Stack ```json { "containerization": "Docker + Docker Compose", "routing": "Valhalla Routing Engine", "mapping": "OpenStreetMap Data", "monitoring": "Health Check Endpoints", "logging": "Winston Logger", "process": "PM2 Process Manager" } ``` --- ## πŸ“Š Data Structure & Schema ### 1. Database Schema #### Users Table ```sql CREATE TABLE users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email VARCHAR(255) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, full_name VARCHAR(255) NOT NULL, phone VARCHAR(20), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, is_active BOOLEAN DEFAULT true, role user_role DEFAULT 'customer' ); CREATE TYPE user_role AS ENUM ('customer', 'operator', 'admin'); ``` #### Parking Lots Table ```sql CREATE TABLE parking_lots ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(255) NOT NULL, address TEXT NOT NULL, latitude DECIMAL(10,8) NOT NULL, longitude DECIMAL(11,8) NOT NULL, total_spots INTEGER NOT NULL DEFAULT 0, available_spots INTEGER NOT NULL DEFAULT 0, price_per_hour DECIMAL(10,2) NOT NULL, operating_hours JSONB, amenities TEXT[], created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, is_active BOOLEAN DEFAULT true ); -- Spatial index for location-based queries CREATE INDEX idx_parking_lots_location ON parking_lots USING GIST ( ll_to_earth(latitude, longitude) ); ``` #### Parking Spots Table ```sql CREATE TABLE parking_spots ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), parking_lot_id UUID REFERENCES parking_lots(id) ON DELETE CASCADE, spot_number VARCHAR(20) NOT NULL, spot_type spot_type DEFAULT 'regular', is_occupied BOOLEAN DEFAULT false, is_reserved BOOLEAN DEFAULT false, last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(parking_lot_id, spot_number) ); CREATE TYPE spot_type AS ENUM ('regular', 'disabled', 'electric', 'compact'); ``` #### Reservations Table ```sql CREATE TABLE reservations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES users(id) ON DELETE CASCADE, parking_spot_id UUID REFERENCES parking_spots(id) ON DELETE CASCADE, start_time TIMESTAMP NOT NULL, end_time TIMESTAMP NOT NULL, total_cost DECIMAL(10,2) NOT NULL, status reservation_status DEFAULT 'pending', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TYPE reservation_status AS ENUM ('pending', 'confirmed', 'active', 'completed', 'cancelled'); ``` ### 2. API Data Models #### Parking Lot Response Model ```typescript interface ParkingLot { id: string; name: string; address: string; coordinates: { latitude: number; longitude: number; }; availability: { totalSpots: number; availableSpots: number; occupancyRate: number; }; pricing: { hourlyRate: number; currency: string; discounts?: Discount[]; }; operatingHours: { [day: string]: { open: string; close: string; is24Hours: boolean; }; }; amenities: string[]; distance?: number; estimatedWalkTime?: number; metadata: { createdAt: string; updatedAt: string; isActive: boolean; }; } ``` #### Search Request Model ```typescript interface ParkingSearchRequest { location: { latitude: number; longitude: number; }; radius: number; // in meters filters?: { maxPrice?: number; amenities?: string[]; spotTypes?: SpotType[]; availableOnly?: boolean; }; sorting?: { field: 'distance' | 'price' | 'availability'; order: 'asc' | 'desc'; }; pagination?: { page: number; limit: number; }; } ``` #### Route Response Model ```typescript interface RouteResponse { route: { distance: number; // in meters duration: number; // in seconds coordinates: [number, number][]; // [lng, lat] pairs }; instructions: RouteInstruction[]; summary: { totalDistance: string; totalTime: string; estimatedCost: number; }; } interface RouteInstruction { text: string; distance: number; time: number; sign: number; interval: [number, number]; } ``` --- ## 🎨 System Design ### 1. Frontend Architecture #### Component Hierarchy ``` App (layout.tsx) β”œβ”€β”€ Header β”œβ”€β”€ LocationDetector β”œβ”€β”€ MapView β”‚ β”œβ”€β”€ LeafletMap β”‚ β”œβ”€β”€ ParkingMarkers β”‚ β”œβ”€β”€ RouteLayer β”‚ └── LocationMarker β”œβ”€β”€ ParkingList β”‚ β”œβ”€β”€ ParkingCard β”‚ └── PaginationControls β”œβ”€β”€ BookingModal β”œβ”€β”€ TransportationSelector └── GPSSimulator (dev only) ``` #### State Management ```typescript // Global State Structure interface AppState { user: { profile: UserProfile | null; authentication: AuthState; preferences: UserPreferences; }; location: { current: Coordinates | null; permissions: LocationPermission; tracking: boolean; }; parking: { searchResults: ParkingLot[]; selectedLot: ParkingLot | null; filters: SearchFilters; loading: boolean; error: string | null; }; routing: { currentRoute: RouteResponse | null; isCalculating: boolean; transportMode: TransportMode; }; ui: { mapCenter: Coordinates; mapZoom: number; sidebarOpen: boolean; modalState: ModalState; }; } ``` ### 2. Backend Architecture #### Service Layer Design ```typescript // Parking Service Architecture @Injectable() export class ParkingService { constructor( private readonly parkingRepository: ParkingRepository, private readonly cacheService: CacheService, private readonly geoService: GeoService ) {} async findNearbyParking(searchDto: ParkingSearchDto): Promise { // 1. Check cache first const cacheKey = this.generateCacheKey(searchDto); const cached = await this.cacheService.get(cacheKey); if (cached) return cached; // 2. Perform spatial query const results = await this.parkingRepository.findWithinRadius({ latitude: searchDto.latitude, longitude: searchDto.longitude, radius: searchDto.radius }); // 3. Apply filters and sorting const filtered = this.applyFilters(results, searchDto.filters); const sorted = this.applySorting(filtered, searchDto.sorting); // 4. Cache results await this.cacheService.set(cacheKey, sorted, 300); // 5 min cache return sorted; } } ``` #### Repository Pattern ```typescript @EntityRepository(ParkingLot) export class ParkingRepository extends Repository { async findWithinRadius(params: SpatialQueryParams): Promise { return this.createQueryBuilder('parking') .select() .addSelect(` (6371 * acos( cos(radians(:lat)) * cos(radians(latitude)) * cos(radians(longitude) - radians(:lng)) + sin(radians(:lat)) * sin(radians(latitude)) )) AS distance `) .where(` (6371 * acos( cos(radians(:lat)) * cos(radians(latitude)) * cos(radians(longitude) - radians(:lng)) + sin(radians(:lat)) * sin(radians(latitude)) )) <= :radius `) .andWhere('is_active = true') .setParameters({ lat: params.latitude, lng: params.longitude, radius: params.radius / 1000 // Convert to km }) .orderBy('distance', 'ASC') .getMany(); } } ``` ### 3. Real-time Updates #### WebSocket Integration ```typescript // WebSocket Gateway for real-time updates @WebSocketGateway({ cors: { origin: '*' }, transports: ['websocket', 'polling'] }) export class ParkingGateway implements OnGatewayConnection, OnGatewayDisconnect { @WebSocketServer() server: Server; async handleConnection(client: Socket) { // Subscribe client to location-based updates const { latitude, longitude, radius } = client.handshake.query; const room = this.generateLocationRoom(latitude, longitude, radius); client.join(room); } @SubscribeMessage('parkingUpdate') async handleParkingUpdate(client: Socket, data: ParkingUpdateDto) { // Broadcast to relevant clients const affectedRooms = this.getAffectedRooms(data.location); affectedRooms.forEach(room => { this.server.to(room).emit('parkingAvailabilityChanged', { parkingLotId: data.parkingLotId, availableSpots: data.availableSpots, timestamp: new Date().toISOString() }); }); } } ``` --- ## πŸ”— API Documentation ### Authentication Endpoints ```typescript POST /api/auth/login POST /api/auth/register POST /api/auth/refresh DELETE /api/auth/logout GET /api/auth/profile PUT /api/auth/profile ``` ### Parking Endpoints ```typescript GET /api/parking/search GET /api/parking/:id POST /api/parking/:id/reserve GET /api/parking/reservations PUT /api/parking/reservations/:id DELETE /api/parking/reservations/:id ``` ### Routing Endpoints ```typescript POST /api/routing/calculate GET /api/routing/modes POST /api/routing/optimize ``` ### Health & Monitoring ```typescript GET /api/health GET /api/health/database GET /api/health/cache GET /api/metrics ``` --- ## πŸ—„οΈ Database Design ### Indexing Strategy ```sql -- Spatial indexes for location queries CREATE INDEX idx_parking_lots_location ON parking_lots USING GIST (ll_to_earth(latitude, longitude)); -- Compound indexes for filtering CREATE INDEX idx_parking_lots_active_price ON parking_lots (is_active, price_per_hour); CREATE INDEX idx_parking_spots_lot_available ON parking_spots (parking_lot_id, is_occupied); -- Time-based indexes for reservations CREATE INDEX idx_reservations_time_range ON reservations (start_time, end_time); CREATE INDEX idx_reservations_user_status ON reservations (user_id, status, created_at); ``` ### Data Partitioning ```sql -- Partition reservations by month for better performance CREATE TABLE reservations_2024_01 PARTITION OF reservations FOR VALUES FROM ('2024-01-01') TO ('2024-02-01'); -- Automated partition management CREATE OR REPLACE FUNCTION create_monthly_partition() RETURNS void AS $$ DECLARE start_date date; end_date date; table_name text; BEGIN start_date := date_trunc('month', CURRENT_DATE + interval '1 month'); end_date := start_date + interval '1 month'; table_name := 'reservations_' || to_char(start_date, 'YYYY_MM'); EXECUTE format('CREATE TABLE %I PARTITION OF reservations FOR VALUES FROM (%L) TO (%L)', table_name, start_date, end_date); END; $$ LANGUAGE plpgsql; ``` --- ## πŸ”’ Security & Performance ### Security Measures 1. **Authentication**: JWT with refresh tokens 2. **Authorization**: Role-based access control (RBAC) 3. **Input Validation**: DTO validation with class-validator 4. **SQL Injection**: Protected by TypeORM parameterized queries 5. **Rate Limiting**: API rate limiting per user/IP 6. **CORS**: Configured for specific origins 7. **HTTPS**: TLS encryption in production ### Performance Optimizations 1. **Caching**: Redis for frequently accessed data 2. **Database**: Optimized indexes and query planning 3. **CDN**: Static asset delivery optimization 4. **Compression**: Gzip compression for API responses 5. **Lazy Loading**: Component and route-based code splitting 6. **Pagination**: Efficient pagination for large datasets 7. **Connection Pooling**: Database connection optimization ### Monitoring & Logging ```typescript // Health Check Implementation @Controller('health') export class HealthController { constructor( private readonly healthCheckService: HealthCheckService, private readonly databaseHealthIndicator: TypeOrmHealthIndicator, private readonly redisHealthIndicator: RedisHealthIndicator ) {} @Get() @HealthCheck() check() { return this.healthCheckService.check([ () => this.databaseHealthIndicator.pingCheck('database'), () => this.redisHealthIndicator.checkHealth('redis'), () => this.checkExternalServices() ]); } } ``` --- ## πŸ“ˆ Scalability Considerations ### Horizontal Scaling - **Load Balancing**: Multiple application instances - **Database Sharding**: Geographic or user-based sharding - **Microservices**: Independent service scaling - **CDN Integration**: Global content distribution ### Vertical Scaling - **Database Optimization**: Query optimization and indexing - **Memory Management**: Efficient caching strategies - **CPU Optimization**: Algorithmic improvements - **Storage Optimization**: Data archiving and compression ### Future Enhancements - **Machine Learning**: Predictive parking availability - **Mobile Apps**: Native iOS/Android applications - **Payment Integration**: Online payment processing - **IoT Integration**: Smart parking sensor integration - **Multi-language**: Internationalization support --- *Last Updated: August 3, 2025* *Version: 1.0.0*