Some checks failed
CI / lint-and-test (push) Has been cancelled
Phase 1 - Architecture Documentation: - Add Architecture section with Mermaid flowchart to README - Create docs/DATABASE_SCHEMA.md with full ERD Phase 2 - CI/CD: - Add CI badge to README - Create .gitea/workflows/ci.yml for linting and tests - Create .gitea/workflows/deploy-staging.yml - Create .gitea/workflows/deploy-production.yml Phase 3 - Operational Scripts: - Create scripts/logs.sh for docker compose log following - Create scripts/run-detached.sh with health check loop - Create scripts/etl/toronto.sh for Toronto data pipeline - Add Makefile targets: logs, run-detached, etl-toronto Phase 4 - Runbooks: - Create docs/runbooks/adding-dashboard.md - Create docs/runbooks/deployment.md Phase 5 - Hygiene: - Create MIT LICENSE file Phase 6 - Production: - Add live demo link to README (leodata.science) Closes #78, #79, #80, #81, #82, #83, #84, #85, #86, #87, #88, #89, #91 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
198 lines
6.0 KiB
Markdown
198 lines
6.0 KiB
Markdown
# Analytics Portfolio
|
|
|
|
[](https://gitea.hotserv.cloud/lmiranda/personal-portfolio/actions)
|
|
|
|
**Live Demo:** [leodata.science](https://leodata.science)
|
|
|
|
A personal portfolio website showcasing data engineering and visualization capabilities, featuring an interactive Toronto Neighbourhood Dashboard.
|
|
|
|
## Live Pages
|
|
|
|
| Route | Page | Description |
|
|
|-------|------|-------------|
|
|
| `/` | Home | Bio landing page |
|
|
| `/about` | About | Background and experience |
|
|
| `/projects` | Projects | Portfolio project showcase |
|
|
| `/resume` | Resume | Professional CV |
|
|
| `/contact` | Contact | Contact form |
|
|
| `/blog` | Blog | Technical articles |
|
|
| `/blog/{slug}` | Article | Individual blog posts |
|
|
| `/toronto` | Toronto Dashboard | Neighbourhood analysis (5 tabs) |
|
|
| `/toronto/methodology` | Methodology | Dashboard data sources and methods |
|
|
| `/health` | Health | API health check endpoint |
|
|
|
|
## Toronto Neighbourhood Dashboard
|
|
|
|
An interactive choropleth dashboard analyzing Toronto's 158 official neighbourhoods across five dimensions:
|
|
|
|
- **Overview**: Composite livability scores, income vs safety scatter
|
|
- **Housing**: Affordability index, rent trends, dwelling types
|
|
- **Safety**: Crime rates, breakdowns by type, trend analysis
|
|
- **Demographics**: Income distribution, age pyramids, population density
|
|
- **Amenities**: Parks, schools, transit accessibility
|
|
|
|
**Data Sources**:
|
|
- City of Toronto Open Data Portal (neighbourhoods, census profiles, amenities)
|
|
- Toronto Police Service (crime statistics)
|
|
- CMHC Rental Market Survey (rental data by zone)
|
|
|
|
## Architecture
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
subgraph Sources
|
|
A1[City of Toronto API]
|
|
A2[Toronto Police API]
|
|
A3[CMHC Data]
|
|
end
|
|
|
|
subgraph ETL
|
|
B1[Parsers]
|
|
B2[Loaders]
|
|
end
|
|
|
|
subgraph Database
|
|
C1[(PostgreSQL/PostGIS)]
|
|
C2[dbt Models]
|
|
end
|
|
|
|
subgraph Application
|
|
D1[Dash App]
|
|
D2[Plotly Figures]
|
|
end
|
|
|
|
A1 & A2 & A3 --> B1 --> B2 --> C1 --> C2 --> D1 --> D2
|
|
```
|
|
|
|
**Pipeline Stages:**
|
|
- **Sources**: External APIs and data files (City of Toronto, Toronto Police, CMHC)
|
|
- **ETL**: Python parsers extract and validate data; loaders persist to database
|
|
- **Database**: PostgreSQL with PostGIS for geospatial; dbt transforms raw → staging → marts
|
|
- **Application**: Dash serves interactive dashboards with Plotly visualizations
|
|
|
|
For detailed database schema, see [docs/DATABASE_SCHEMA.md](docs/DATABASE_SCHEMA.md).
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
# Clone and setup
|
|
git clone https://gitea.hotserv.cloud/lmiranda/personal-portfolio.git
|
|
cd personal-portfolio
|
|
|
|
# Install dependencies and configure environment
|
|
make setup
|
|
|
|
# Start database
|
|
make docker-up
|
|
|
|
# Initialize database schema
|
|
make db-init
|
|
|
|
# Run development server
|
|
make run
|
|
```
|
|
|
|
Visit `http://localhost:8050` to view the portfolio.
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
portfolio_app/
|
|
├── app.py # Dash app factory
|
|
├── config.py # Pydantic settings
|
|
├── pages/
|
|
│ ├── home.py # Bio landing (/)
|
|
│ ├── about.py # About page
|
|
│ ├── contact.py # Contact form
|
|
│ ├── projects.py # Project showcase
|
|
│ ├── resume.py # Resume/CV
|
|
│ ├── blog/ # Blog system
|
|
│ │ ├── index.py # Article listing
|
|
│ │ └── article.py # Article renderer
|
|
│ └── toronto/ # Toronto dashboard
|
|
│ ├── dashboard.py # Main layout with tabs
|
|
│ ├── methodology.py # Data documentation
|
|
│ ├── tabs/ # Tab layouts (5)
|
|
│ └── callbacks/ # Interaction logic
|
|
├── components/ # Shared UI components
|
|
├── figures/ # Plotly figure factories
|
|
├── content/
|
|
│ └── blog/ # Markdown blog articles
|
|
├── toronto/ # Toronto data logic
|
|
│ ├── parsers/ # API data extraction
|
|
│ ├── loaders/ # Database operations
|
|
│ ├── schemas/ # Pydantic models
|
|
│ └── models/ # SQLAlchemy ORM
|
|
└── errors/ # Exception handling
|
|
|
|
dbt/
|
|
├── models/
|
|
│ ├── staging/ # 1:1 source tables
|
|
│ ├── intermediate/ # Business logic
|
|
│ └── marts/ # Analytical tables
|
|
|
|
notebooks/ # Data documentation (15 notebooks)
|
|
├── overview/ # Overview tab visualizations
|
|
├── housing/ # Housing tab visualizations
|
|
├── safety/ # Safety tab visualizations
|
|
├── demographics/ # Demographics tab visualizations
|
|
└── amenities/ # Amenities tab visualizations
|
|
|
|
docs/
|
|
├── PROJECT_REFERENCE.md # Architecture reference
|
|
├── CONTRIBUTING.md # Developer guide
|
|
└── project-lessons-learned/
|
|
```
|
|
|
|
## Tech Stack
|
|
|
|
| Layer | Technology |
|
|
|-------|------------|
|
|
| Database | PostgreSQL 16 + PostGIS |
|
|
| Validation | Pydantic 2.x |
|
|
| ORM | SQLAlchemy 2.x |
|
|
| Transformation | dbt-postgres |
|
|
| Data Processing | Pandas, GeoPandas |
|
|
| Visualization | Dash + Plotly |
|
|
| UI Components | dash-mantine-components |
|
|
| Testing | pytest |
|
|
| Python | 3.11+ |
|
|
|
|
## Development
|
|
|
|
```bash
|
|
make test # Run pytest
|
|
make lint # Run ruff linter
|
|
make format # Format code
|
|
make ci # Run all checks
|
|
make dbt-run # Run dbt models
|
|
make dbt-test # Run dbt tests
|
|
```
|
|
|
|
## Environment Variables
|
|
|
|
Copy `.env.example` to `.env` and configure:
|
|
|
|
```bash
|
|
DATABASE_URL=postgresql://user:pass@localhost:5432/portfolio
|
|
POSTGRES_USER=portfolio
|
|
POSTGRES_PASSWORD=<secure>
|
|
POSTGRES_DB=portfolio
|
|
DASH_DEBUG=true
|
|
SECRET_KEY=<random>
|
|
```
|
|
|
|
## Documentation
|
|
|
|
- **For developers**: See `docs/CONTRIBUTING.md` for setup and contribution guidelines
|
|
- **For Claude Code**: See `CLAUDE.md` for AI assistant context
|
|
- **Architecture**: See `docs/PROJECT_REFERENCE.md` for technical details
|
|
|
|
## License
|
|
|
|
MIT
|
|
|
|
## Author
|
|
|
|
Leo Miranda
|