SmartPark Responsive Web App Development

Anxhela Shaholli

SmartPark - How to Build a Responsive Web App with Emergent

Overview

SmartPark is a real-time parking availability web app designed and built with Emergent.sh. It consumes a Flask/OpenCV backend that detects stall occupancy from a single camera and publishes a live MJPEG stream plus JSON endpoints. The web UI lets users see live availability, browse a slot map, and check lot health, while operators can sign in to view admin metrics. On the reference lot, SmartPark tracks 396 stalls and updates availability in real time.

Design Direction

We used a clear, transport-friendly palette for trust and readability: • white for content surfaces and clarity • charcoal for text and layout structure • emerald green as a positive/available accent • safety red for occupied/error states Typography • headlines: bold modern sans (e.g., Inter/Manrope) for high legibility • body text: geometric sans for clean paragraphs and data labels

Prompt Strategy

Code
Preview
Deploy
Build a complete “Smart Parking System Using Camera-Based Detection” that runs on CPU and demonstrates real-time stall availability from a single fixed camera. Produce a runnable repo, a README with exact commands, and an MP4 demo video that records both the OpenCV overlay window and the web dashboard. Target a clean, no-errors experience on first run.
Objectives
Localize stalls via a binary mask aligned to the video frame.
Classify each stall as empty/occupied using a two-path pipeline: a fast heuristic baseline and a learned HOG+LogisticRegression model.
Reduce compute with temporal scheduling (classify every N frames) and SSIM-based change triggers.
Render a desktop overlay (green = empty, red = occupied) and expose a Flask web API with MJPEG streaming and JSON status.
Include sample assets and an automated demo so the evaluator can see the system running without extra setup.
Tech stack and constraints
• Python 3.10+; CPU-only.
• OpenCV (video I/O, drawing, MJPEG stream), scikit-learn (LogReg), scikit-image or OpenCV for SSIM, numpy, flask, joblib.
• Pin versions in requirements.txt for reproducibility.
• Code quality: type hints, docstrings, consistent logging, small focused modules.
Repository layout (exact)
requirements.txt
.env.example
smart_parking/
config.py # reads env/CLI, validates paths and thresholds
capture.py # video source (file/camera/RTSP), optional downscale
mask.py # load binary mask; connectedComponentsWithStats -> boxes
tracker.py # ROIChangeTracker with SSIM, per-stall caches
features.py # HOG extractor for 64×64 gray crops
heuristic.py # background subtraction + foreground density baseline
model.py # load/save joblib; LogReg inference; thresholding
pipeline.py # main perception loop, scheduling every N frames
overlay.py # draw boxes and HUD “Available: {avail} / {total}”
web.py # Flask app: /stream (MJPEG), /status (JSON), /slots (JSON)
run_cli.py # launches overlay window + optional web server
tools/
make_dataset_from_video.py # crops ROI images from video+mask for training
train_classifier.py # trains HOG+LogReg, saves models/spot_clf.joblib
gen_synthetic_assets.py # creates a 28s synthetic clip + matching mask
models/
spot_clf.joblib # optional; if missing, system runs with heuristic path
assets/
sample_video.mp4 # 28s demo clip (cropped lot); shipped by default
sample_mask.png # white rectangles per stall, aligned to video
demo/
record_demo.py # captures overlay window and web UI into demo.mp4
demo.mp4 # generated by record_demo.py
Functional details (exact behavior to implement)
• Binary mask: a single-channel PNG at the working resolution; white rectangles = stalls. On startup, compute connected components once and store stable bounding boxes and IDs [0..K–1].
• Temporal policy: classify each stall every CLASSIFY_EVERY_N_FRAMES (default 30).
• SSIM gate: if SSIM(prev_crop, curr_crop) < SSIM_THRESHOLD (default 0.85), force re-classification immediately (don’t wait for the cadence).
• Heuristic baseline: background subtractor per ROI + foreground area ratio; combine with simple morphology; return label and confidence.
• HOG+LogReg path: 64×64 grayscale crop → HOG → StandardScaler (if used) → LogisticRegression; produce probability for “empty”. Threshold configurable; default chosen to favor precision on the empty class.
• Aggregation: at each frame, recompute available = count of labels == empty; total = number of stalls from mask.
• Overlay: draw green boxes for empty, red for occupied; top-left HUD panel text: “Available: {available} / {total}”.
• Web: Flask app on 0.0.0.0:5000
– GET /status → {"total": 396, "available": 123} (keys total, available)
– GET /slots → per-stall list of {id, x, y, w, h, label, confidence}
– GET /stream → MJPEG stream of annotated frames
• Performance target on reference HW: with FRAME_MAX_WIDTH=960 and N=30, sustain ~24–28 FPS end-to-end with stable latency.
• Determinism: set all random seeds and provide consistent defaults.
Configuration (via .env and CLI flags)
• VIDEO_SOURCE: path or integer index or RTSP URL (default ./assets/sample_video.mp4)
• MASK_PATH: path to binary mask (default ./assets/sample_mask.png)
• FRAME_MAX_WIDTH: int (default 960)
• CLASSIFY_EVERY_N_FRAMES: int (default 30)
• SSIM_THRESHOLD: float 0.85
• MODEL_PATH: ./models/spot_clf.joblib
• OPEN_BROWSER: true/false (default true) to auto-open the dashboard on start
All config also overrideable via CLI, e.g.:
python -m smart_parking.run_cli --video ./assets/sample_video.mp4 --mask ./assets/sample_mask.png --frame-max-width 960 --every 30 --ssim 0.85 --open-browser false
Training and dataset utilities
• tools/make_dataset_from_video.py: iterate video, crop each stall at interval, write to datasets/{empty,occupied}/. Deduplicate near-identical crops; support split 75/25.
• tools/train_classifier.py: trains HOG+LogReg on the dataset; prints Accuracy/Precision/Recall/F1; saves models/spot_clf.joblib and confusion matrix + PR curve PNGs in models/.
• If no model is present, runtime gracefully falls back to heuristic with a log warning.
Sample assets and default behavior
• Provide assets/sample_video.mp4 (28 seconds, forward+reverse concat for continuous motion) and assets/sample_mask.png. Configure the default mask to define 396 stalls so that the running demo displays “Available: 123 / 396” at least for part of the timeline (it can fluctuate realistically).
• Provide tools/gen_synthetic_assets.py that can re-generate a synthetic sample video and aligned mask if a maintainer wants to reproduce assets from scratch.
Web and CLI UX parity
• The overlay window and the web MJPEG stream must show identical annotations and the same HUD count at all times.
• Include a simple index page at http://127.0.0.1:5000/
that embeds the MJPEG <img> and links to /status and /slots.
Logging and health
• Standard logging with timestamps and per-stage timings.
• /health returns {"ok": true} when capture is live and mask is aligned.
• Early fail if mask resolution does not match the working frame size (print corrective suggestion).
Automated demo video (must be created by the build/run)
• demo/record_demo.py should:
Launch the CLI overlay and Flask server.
Wait 2–3 seconds.
Open the dashboard in a headless browser to show the index page.
Record a 25–30 second screen capture that includes both the overlay window and a browser window showing the dashboard and, once, the /status JSON in a tab.
Save demo/demo.mp4 (1080p or matching desktop resolution).
• If desktop capture is not feasible in headless CI, alternatively compose the video by stitching frames from the overlay and a programmatic render of the dashboard UI into a single side-by-side video using OpenCV’s VideoWriter. The final output must still be demo/demo.mp4.
README.md (authoritative instructions) must include
• What the app does, architecture summary, and a small diagram.
• How to set up: python -m venv venv; source venv/bin/activate; pip install -r requirements.txt.
• How to run with defaults:
– python -m smart_parking.run_cli
(set OPEN_BROWSER=false if auto-open is undesired)
• How to train a model and enable it:
– python tools/make_dataset_from_video.py --video assets/sample_video.mp4 --mask assets/sample_mask.png --out ./datasets --interval 15
– python tools/train_classifier.py --data ./datasets --out ./models
• Troubleshooting: mask alignment errors, low FPS remedies (set FRAME_MAX_WIDTH=960, increase N), and how to switch between heuristic and ML paths.
• Acceptance checklist (see below). Include screenshots of the overlay and web index.
Acceptance criteria (must pass)
First run produces no exceptions and renders an overlay with colored boxes and HUD text.
Web server starts at :5000 and serves /status with JSON keys total and available; /stream returns a valid MJPEG stream; /slots returns per-stall states.
With default assets and settings, the app sustains near real-time (≥22 FPS) on CPU and the availability count updates when cars move in the clip.
demo/demo.mp4 is created and shows both the overlay and the dashboard, including a moment where a stall flips state and the headline count changes accordingly.
README contains exact commands and mentions OPEN_BROWSER=false to disable auto-open behavior.
If models/spot_clf.joblib is missing, the app still runs using the heuristic baseline.
Testing
• Provide minimal unit tests for: mask → boxes extraction, SSIM change gate logic, /status schema, and a smoke test that runs the pipeline for 5 seconds and asserts no exceptions.
Notes
• Keep the code modular and readable; prefer small pure functions.
• Ensure all long-running threads/processes shut down cleanly on Ctrl-C.
• Use deterministic seeds for any randomness.
• Keep external dependencies minimal and widely available.
Deliverables
• Zipped repository with the structure above, ready to pip install and run.
• demo/demo.mp4 showing the app in action.
• Screenshots saved to demo/ (overlay.png, dashboard.png) for inclusion in documents.

Features Built

✔️ Public landing with headline availability counter ✔️ Live MJPEG stream embed from Flask /stream ✔️ Slot map from /slots with filter and search ✔️ Supabase auth and protected Operator Dashboard ✔️ Status polling from /status with resilient fetch and loaders ✔️ Health check from /health with inline alerts ✔️ Mobile-first responsive layout with accessible components ✔️ Theming with white/charcoal base, green/red semantic accents
Sign In Screen - Email-based sign-in with clear error states and disabled submit during network calls.
Sign In Screen - Email-based sign-in with clear error states and disabled submit during network calls.

Challenges & Troubleshooting

Mixed content and CORS The MJPEG stream at http://127.0.0.1:5000/stream failed under HTTPS. Fix: during local dev, run both front-end and Flask over HTTP on localhost; in production, proxy the Flask service behind the same domain/TLS. Added a clear banner if the stream fails to load and a retry link.
Env configuration and Supabase auth Initial auth errors due to missing variables. Fix: created .env with VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY; documented setup and added defensive checks with friendly messages.
Polling and stale UI Naive polling caused jitter. Fix: standardized a 2s polling interval with exponential backoff on failures; added skeleton loaders and “last updated” timestamps.
Homepage
Homepage
Operator Dashboard
Cards for totals, availability history sparkline, backend health, FPS (if provided), and a recent changes table.
Operator Dashboard Cards for totals, availability history sparkline, backend health, FPS (if provided), and a recent changes table.

Results

SmartPark delivers a clean, responsive UI that mirrors the backend’s real-time perception: • fully responsive, mobile-first UI • live stream and live counter from Flask/OpenCV • per-stall status with quick filters • operator dashboard behind Supabase auth • accessible color and type system aligned to parking semantics
SmarPark Reservation System
SmarPark Reservation System
SmartPark - Reservations
SmartPark - Reservations

Takeaways

Precise prompts dramatically speed up Bolt builds when you specify pages, data contracts, and visual language. Handling MJPEG and CORS requires early planning, and small UX touches (loaders, timestamps, retries) keep trust high during network hiccups. Keeping the accent colors semantic (green for available, red for occupied) reduces cognitive load and speeds decision-making.
Like this project

Posted Oct 5, 2025

Developed a responsive web app for real-time parking availability using Emergent.sh and Flask/OpenCV.

Likes

0

Views

1

Timeline

Sep 1, 2025 - Oct 5, 2025

Clients

SmartPark

M&E Beauty Salon – Landing Page With Framer
M&E Beauty Salon – Landing Page With Framer
KryptoShare – Crypto Investment Platform WordPress Website
KryptoShare – Crypto Investment Platform WordPress Website
WordPress Website Blog -empowermelife.com
WordPress Website Blog -empowermelife.com

Join 50k+ companies and 1M+ independents

Contra Logo

© 2025 Contra.Work Inc