A Streamlit app analyzing commute time data (collected from a GPS API) between Palaiseau and Paris, used to find the best time of day to travel.
traffic_analysis/
├── app.py # Streamlit UI
├── src/
│ └── data_loader.py # Data loading/filtering logic (unit tested)
├── tests/
│ └── test_data_loader.py # Pytest suite
├── data/
│ ├── data_X_solfe.json # Palaiseau -> Paris trip records
│ └── data_solfe_X.json # Paris -> Palaiseau trip records
├── Dockerfile
├── requirements.txt
├── requirements-dev.txt
└── .github/workflows/ci.yml # CI: lint, test, Docker build
Each JSON file is a list of trip records:
{
"timestamp": "2025-10-05T15:12:52.076311",
"duration_seconds": 2319,
"duration_minutes": 38.65,
"distance_meters": 26041,
"distance_km": 26.041,
"base_duration": 1921,
"traffic_delay": 398
}python -m venv venv
source venv/bin/activate
pip install -r requirements-dev.txt
streamlit run app.pypytest tests/ -v --cov=srcdocker build -t traffic-analysis .
docker run -p 8501:8501 traffic-analysisThen open http://localhost:8501.
GitHub Actions (.github/workflows/ci.yml) runs on every push/PR to main:
- Lints
src/andapp.pywith flake8 - Runs the pytest suite (with coverage) on Python 3.11 and 3.12
- Builds the Docker image to confirm it's buildable
- Dependencies are pinned in
requirements.txt/requirements-dev.txt. - Data loading and transformation logic lives in
src/data_loader.py, separate from the Streamlit UI, so it can be unit tested without a browser. - The Docker image installs dependencies before copying code, so rebuilds are fast when only app logic changes.