A full-stack web application that displays and tracks bus routes in real time using FastAPI, Firebase Realtime Database, and Leaflet.js.
- Node.js (v14+)
- npm (v6+)
- Python (v3.7+)
- pip
- Virtual environment tool (e.g.,
venv) - Firebase service account JSON file (stored securely, outside the repo)
project-root/
├── backend/
│ ├── server.py
│ ├── requirements.txt
│ └── .env ← contains FIREBASE_DB_URL (and optional dotenv secrets)
└── frontend/
├── index.html
├── package.json
├── webpack.config.js
└── src/
└── main.js
Create a .env file in backend/ (add to .gitignore):
# path to your Firebase service account (GOOGLE_APPLICATION_CREDENTIALS is file-URL set externally)
# FIREBASE_SERVICE_ACCOUNT_JSON optional if using ADC
FIREBASE_DB_URL=https://<YOUR-PROJECT-ID>.firebaseio.com
Additionally, set:
- GOOGLE_APPLICATION_CREDENTIALS → path to service account JSON on disk:
# macOS/Linux export GOOGLE_APPLICATION_CREDENTIALS="/secure/path/serviceAccount.json" # Windows (PowerShell) setx GOOGLE_APPLICATION_CREDENTIALS "C:\secure\path\serviceAccount.json"
-
Navigate to the backend folder:
cd project-root/backend -
Create and activate a virtual environment:
python3 -m venv venv source venv/bin/activate # macOS/Linux .\venv\Scripts\Activate.ps1 # Windows PowerShell
-
Install Python dependencies:
pip install fastapi uvicorn httpx firebase-admin python-dotenv
-
Use the provided
app.py(FastAPI async server) or adapt as needed. -
Run the FastAPI server:
uvicorn app:app --reload --host 0.0.0.0 --port 5000
-
Navigate to the frontend folder:
cd project-root/frontend -
Install Node.js dependencies:
npm install
-
Build the production bundle:
npm run build
This generates dist/bundle.js, served under /static/bundle.js.
- Live coding (frontend):
# in frontend/ npx webpack --watch - Live reload (backend): uvicorn's
--reloadflag will pick up code changes.
Open your browser at:
http://localhost:5000/
Select a route, track buses in real time, search addresses, or input coordinates to draw custom routes.
- Keep your service account JSON outside version control.
- Rotate service account keys via Firebase console.
- Authenticate and rate-limit
/api/bus1before public deployment. - Harden HTTP headers with middleware (e.g., FastAPI-Talisman or Starlette middleware) to enforce CSP, HSTS, etc.
- Use a CDN/WAF (Cloudflare, AWS CloudFront) for DDoS protection.
To compare Flask vs. FastAPI backend performance, follow these steps:
-
Run both servers on different ports
- Flask (default port 5000):
# in backend-flask/ export FIREBASE_DB_URL="https://<PROJECT>.firebaseio.com" export GOOGLE_APPLICATION_CREDENTIALS="/path/to/serviceAccount.json" source venv/bin/activate # or Windows equivalent python app.py --port 5000
- FastAPI (port 5001):
# in backend-fastapi/ source venv/bin/activate uvicorn server:app --reload --host 0.0.0.0 --port 5001
- Flask (default port 5000):
-
Select a benchmarking tool: (e.g.,
hey)# Chocolatey on Windows choco install hey -
Run load tests:
# Benchmark Flask hey -n 10000 -c 100 http://localhost:5000/api/bus1 > flask_results.txt # Benchmark FastAPI hey -n 10000 -c 100 http://localhost:5001/api/bus1 > fastapi_results.txt
-
Analyze results: Compare throughput, latencies, error rates.
A. Eliminating duplicate Firebase hits
Polling 10 000 clients every 2 s means 5 000 Firebase calls per second—that alone will choke both your server and Firebase quotas.
Solution: Cache the Bus1 JSON in memory for a short TTL (e.g. 1–2 s). All 1 000 req/s hit your cache, not Firebase.
B. Server-Sent Events
Instead of polling, open an SSE connection per client. One backend fetch → broadcast update to all sockets.
uvicorn app:app --host 0.0.0.0 --port 5000 --workers 1 --limit-concurrency 100 --limit-max-requests 1000This ensures you don’t overwhelm the 0.1 CPU, queues excess requests, and recycles the worker periodically.