Files
personal-portfolio/docs/PROJECT_REFERENCE.md
lmiranda 4818c53fd2 docs: Rewrite documentation with accurate project state
- Delete obsolete change proposals and bio content source
- Rewrite README.md with correct features, data sources, structure
- Update PROJECT_REFERENCE.md with accurate status and completed work
- Update CLAUDE.md references and sprint status
- Add docs/CONTRIBUTING.md developer guide with:
  - How to add blog posts (frontmatter, markdown)
  - How to add new pages (Dash routing)
  - How to add dashboard tabs
  - How to create figure factories
  - Branch workflow and code standards

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 12:27:25 -05:00

7.9 KiB

Portfolio Project Reference

Project: Analytics Portfolio Owner: Leo Miranda Status: Sprint 9 Complete (Dashboard Implementation Done) Last Updated: January 2026


Project Overview

Personal portfolio website with an interactive Toronto Neighbourhood Dashboard demonstrating data engineering, visualization, and analytics capabilities.

Component Description Status
Portfolio Website Bio, About, Projects, Resume, Contact, Blog Complete
Toronto Dashboard 5-tab neighbourhood analysis Complete
Data Pipeline dbt models, figure factories Complete
Deployment Production deployment Pending

Completed Work

Sprint 1-6: Foundation

  • Repository setup, Docker, PostgreSQL + PostGIS
  • Bio landing page implementation
  • Initial data model design

Sprint 7: Navigation & Theme

  • Sidebar navigation
  • Dark/light theme toggle
  • dash-mantine-components integration

Sprint 8: Portfolio Website

  • About, Contact, Projects, Resume pages
  • Blog system with Markdown/frontmatter
  • Health endpoint

Sprint 9: Neighbourhood Dashboard Transition

  • Phase 1: Deleted legacy TRREB code
  • Phase 2: Documentation cleanup
  • Phase 3: New neighbourhood-centric data model
  • Phase 4: dbt model restructuring
  • Phase 5: 5-tab dashboard implementation
  • Phase 6: 15 documentation notebooks
  • Phase 7: Final documentation review

Application Architecture

URL Routes

URL Page File
/ Home pages/home.py
/about About pages/about.py
/contact Contact pages/contact.py
/projects Projects pages/projects.py
/resume Resume pages/resume.py
/blog Blog listing pages/blog/index.py
/blog/{slug} Article pages/blog/article.py
/toronto Dashboard pages/toronto/dashboard.py
/toronto/methodology Methodology pages/toronto/methodology.py
/health Health check pages/health.py

Directory Structure

portfolio_app/
├── app.py                    # Dash app factory
├── config.py                 # Pydantic BaseSettings
├── assets/                   # CSS, images
├── callbacks/                # Global callbacks (sidebar, theme)
├── components/               # Shared UI components
├── content/blog/             # Markdown blog articles
├── errors/                   # Exception handling
├── figures/                  # Plotly figure factories
├── pages/
│   ├── home.py
│   ├── about.py
│   ├── contact.py
│   ├── projects.py
│   ├── resume.py
│   ├── health.py
│   ├── blog/
│   │   ├── index.py
│   │   └── article.py
│   └── toronto/
│       ├── dashboard.py
│       ├── methodology.py
│       ├── tabs/             # 5 tab layouts
│       └── callbacks/        # Dashboard interactions
├── toronto/                  # Data logic
│   ├── parsers/              # API extraction
│   ├── loaders/              # Database operations
│   ├── schemas/              # Pydantic models
│   ├── models/               # SQLAlchemy ORM
│   └── demo_data.py          # Sample data
└── utils/
    └── markdown_loader.py    # Blog article loading

Toronto Dashboard

Data Sources

Source Data Format
City of Toronto Open Data Neighbourhoods (158), Census profiles, Parks, Schools, Childcare, TTC GeoJSON, CSV, API
Toronto Police Service Crime rates, MCI, Shootings CSV, API
CMHC Rental Market Survey CSV

Geographic Model

City of Toronto Neighbourhoods (158) ← Primary analysis unit
CMHC Zones (~20) ← Rental data (Census Tract aligned)

Dashboard Tabs

Tab Choropleth Metric Supporting Charts
Overview Livability score Top/Bottom 10 bar, Income vs Safety scatter
Housing Affordability index Rent trend line, Tenure breakdown bar
Safety Crime rate per 100K Crime breakdown bar, Crime trend line
Demographics Median income Age distribution, Population density bar
Amenities Amenity index Amenity radar, Transit accessibility bar

Star Schema

Table Type Description
dim_neighbourhood Dimension 158 neighbourhoods with geometry
dim_time Dimension Date dimension
dim_cmhc_zone Dimension ~20 CMHC zones with geometry
fact_census Fact Census indicators by neighbourhood
fact_crime Fact Crime stats by neighbourhood
fact_rentals Fact Rental data by CMHC zone
fact_amenities Fact Amenity counts by neighbourhood

dbt Layers

Layer Naming Example
Staging stg_{source}__{entity} stg_toronto__neighbourhoods
Intermediate int_{domain}__{transform} int_neighbourhood__demographics
Marts mart_{domain} mart_neighbourhood_overview

Tech Stack

Layer Technology Version
Database PostgreSQL + PostGIS 16.x
Validation Pydantic 2.x
ORM SQLAlchemy 2.x
Transformation dbt-postgres 1.7+
Data Processing Pandas, GeoPandas Latest
Visualization Dash + Plotly 2.14+
UI Components dash-mantine-components Latest
Testing pytest 7.0+
Python 3.11+ Via pyenv

Branching Strategy

Branch Purpose Deploys To
main Production releases VPS (production)
staging Pre-production testing VPS (staging)
development Active development Local only

Rules:

  • Feature branches from development: feature/{sprint}-{description}
  • Merge into development when complete
  • developmentstagingmain for releases
  • Never delete development

Code Standards

Type Hints (Python 3.10+)

def process(items: list[str], config: dict[str, int] | None = None) -> bool:
    ...

Imports

Context Style
Same directory from .module import X
Sibling directory from ..schemas.model import Y
External import pandas as pd

Error Handling

class PortfolioError(Exception):
    """Base exception."""

class ParseError(PortfolioError):
    """Data parsing failed."""

class ValidationError(PortfolioError):
    """Validation failed."""

class LoadError(PortfolioError):
    """Database load failed."""

Environment Variables

Required in .env:

DATABASE_URL=postgresql://user:pass@localhost:5432/portfolio
POSTGRES_USER=portfolio
POSTGRES_PASSWORD=<secure>
POSTGRES_DB=portfolio
DASH_DEBUG=true
SECRET_KEY=<random>
LOG_LEVEL=INFO

Makefile Targets

Target Purpose
setup Install deps, create .env, init pre-commit
docker-up Start PostgreSQL + PostGIS
docker-down Stop containers
db-init Initialize database schema
run Start Dash dev server
test Run pytest
dbt-run Run dbt models
dbt-test Run dbt tests
lint Run ruff linter
format Run ruff formatter
ci Run all checks

Next Steps

Deployment (Sprint 10+)

  • Production Docker configuration
  • CI/CD pipeline
  • HTTPS/SSL setup
  • Domain configuration

Data Enhancement

  • Connect to live APIs (currently using demo data)
  • Data refresh automation
  • Historical data loading

Future Projects

  • Energy Pricing Analysis dashboard (planned)

Document Purpose
README.md Quick start guide
CLAUDE.md AI assistant context
docs/CONTRIBUTING.md Developer guide
notebooks/README.md Notebook documentation

Reference Version: 3.0 Updated: January 2026