# Toronto Neighbourhood Dashboard — Implementation Plan **Document Type:** Execution Guide **Target:** Transition from TRREB-based to Neighbourhood-based Dashboard **Version:** 2.0 | January 2026 --- ## Overview Transition from TRREB district-based housing dashboard to a comprehensive Toronto Neighbourhood Dashboard built around the city's 158 official neighbourhoods. **Key Changes:** - Geographic foundation: TRREB districts (~35) → City Neighbourhoods (158) - Data sources: PDF parsing → Open APIs (Toronto Open Data, Toronto Police, CMHC) - Scope: Housing-only → 5 thematic tabs (Overview, Housing, Safety, Demographics, Amenities) --- ## Phase 1: Repository Cleanup ### Files to DELETE | File | Reason | |------|--------| | `portfolio_app/toronto/schemas/trreb.py` | TRREB schema obsolete | | `portfolio_app/toronto/parsers/trreb.py` | PDF parsing no longer needed | | `portfolio_app/toronto/loaders/trreb.py` | TRREB loading logic obsolete | | `dbt/models/staging/stg_trreb__purchases.sql` | TRREB staging obsolete | | `dbt/models/intermediate/int_purchases__monthly.sql` | TRREB intermediate obsolete | | `dbt/models/marts/mart_toronto_purchases.sql` | Will rebuild for neighbourhood grain | ### Files to MODIFY (Remove TRREB References) | File | Action | |------|--------| | `portfolio_app/toronto/schemas/__init__.py` | Remove TRREB imports | | `portfolio_app/toronto/parsers/__init__.py` | Remove TRREB parser imports | | `portfolio_app/toronto/loaders/__init__.py` | Remove TRREB loader imports | | `portfolio_app/toronto/models/facts.py` | Remove `FactPurchases` model | | `portfolio_app/toronto/models/dimensions.py` | Remove `DimTRREBDistrict` model | | `portfolio_app/toronto/demo_data.py` | Remove TRREB demo data | | `dbt/models/sources.yml` | Remove TRREB source definitions | | `dbt/models/schema.yml` | Remove TRREB model documentation | ### Files to KEEP (Reusable) | File | Why | |------|-----| | `portfolio_app/toronto/schemas/cmhc.py` | CMHC data still used | | `portfolio_app/toronto/parsers/cmhc.py` | Reusable with modifications | | `portfolio_app/toronto/loaders/base.py` | Generic database utilities | | `portfolio_app/toronto/loaders/dimensions.py` | Dimension loading patterns | | `portfolio_app/toronto/models/base.py` | SQLAlchemy base class | | `portfolio_app/figures/*.py` | All chart factories reusable | | `portfolio_app/components/*.py` | All UI components reusable | --- ## Phase 2: Documentation Updates | Document | Action | |----------|--------| | `CLAUDE.md` | Update data model section, mark transition complete | | `docs/PROJECT_REFERENCE.md` | Update architecture, data sources | | `docs/toronto_housing_dashboard_spec_v5.md` | Archive or delete | | `docs/wbs_sprint_plan_v4.md` | Archive or delete | --- ## Phase 3: New Data Model ### Star Schema (Neighbourhood-Centric) | Table | Type | Description | |-------|------|-------------| | `dim_neighbourhood` | Central Dimension | 158 neighbourhoods with geometry | | `dim_time` | Dimension | Date dimension (keep existing) | | `dim_cmhc_zone` | Bridge Dimension | 15 CMHC zones with neighbourhood mapping | | `bridge_cmhc_neighbourhood` | Bridge | Zone-to-neighbourhood area weights | | `fact_census` | Fact | Census indicators by neighbourhood | | `fact_crime` | Fact | Crime stats by neighbourhood | | `fact_rentals` | Fact | Rental data by CMHC zone (keep existing) | | `fact_amenities` | Fact | Amenity counts by neighbourhood | ### New Schema Files | File | Contains | |------|----------| | `toronto/schemas/neighbourhood.py` | NeighbourhoodRecord, CensusRecord, CrimeRecord | | `toronto/schemas/amenities.py` | AmenityType enum, AmenityRecord | ### New Parser Files | File | Data Source | API | |------|-------------|-----| | `toronto/parsers/toronto_open_data.py` | Neighbourhoods, Census, Parks, Schools, Childcare | Toronto Open Data Portal | | `toronto/parsers/toronto_police.py` | Crime Rates, MCI, Shootings | Toronto Police Portal | ### New Loader Files | File | Purpose | |------|---------| | `toronto/loaders/neighbourhoods.py` | Load GeoJSON boundaries | | `toronto/loaders/census.py` | Load neighbourhood profiles | | `toronto/loaders/crime.py` | Load crime statistics | | `toronto/loaders/amenities.py` | Load parks, schools, childcare | | `toronto/loaders/cmhc_crosswalk.py` | Build CMHC-neighbourhood bridge | --- ## Phase 4: dbt Restructuring ### Staging Layer | Model | Source | |-------|--------| | `stg_toronto__neighbourhoods` | dim_neighbourhood | | `stg_toronto__census` | fact_census | | `stg_toronto__crime` | fact_crime | | `stg_toronto__amenities` | fact_amenities | | `stg_cmhc__rentals` | fact_rentals (modify existing) | | `stg_cmhc__zone_crosswalk` | bridge_cmhc_neighbourhood | ### Intermediate Layer | Model | Purpose | |-------|---------| | `int_neighbourhood__demographics` | Combined census demographics | | `int_neighbourhood__housing` | Housing indicators | | `int_neighbourhood__crime_summary` | Aggregated crime by type | | `int_neighbourhood__amenity_scores` | Normalized amenity metrics | | `int_rentals__neighbourhood_allocated` | CMHC rentals allocated to neighbourhoods | ### Mart Layer (One per Tab) | Model | Tab | Key Metrics | |-------|-----|-------------| | `mart_neighbourhood_overview` | Overview | Composite livability score | | `mart_neighbourhood_housing` | Housing | Affordability index, rent-to-income | | `mart_neighbourhood_safety` | Safety | Crime rates, YoY change | | `mart_neighbourhood_demographics` | Demographics | Income, age, diversity | | `mart_neighbourhood_amenities` | Amenities | Parks, schools, transit per capita | --- ## Phase 5: Dashboard Implementation ### Tab Structure ``` pages/toronto/ ├── dashboard.py # Main layout with tab navigation ├── tabs/ │ ├── overview.py # Composite livability │ ├── housing.py # Affordability │ ├── safety.py # Crime │ ├── demographics.py # Population │ └── amenities.py # Services └── callbacks/ ├── map_callbacks.py ├── chart_callbacks.py └── selection_callbacks.py ``` ### Layout Pattern (All Tabs) Each tab follows the same structure: 1. **Choropleth Map** (left) — 158 neighbourhoods, click to select 2. **KPI Cards** (right) — 3-4 contextual metrics 3. **Supporting Charts** (bottom) — Trend + comparison visualizations 4. **Details Panel** (collapsible) — All metrics for selected neighbourhood ### Graphs by Tab | Tab | Choropleth Metric | Chart 1 | Chart 2 | |-----|-------------------|---------|---------| | Overview | Livability score | Top/Bottom 10 bar | Income vs Crime scatter | | Housing | Affordability index | Rent trend (5yr line) | Dwelling types (pie/bar) | | Safety | Crime rate per 100K | Crime breakdown (stacked bar) | Crime trend (5yr line) | | Demographics | Median income | Age pyramid | Top languages (bar) | | Amenities | Park area per capita | Amenity radar | Transit accessibility (bar) | --- ## Phase 6: Jupyter Notebooks ### Purpose One notebook per graph to document: 1. **Data Reference** — How the data was built (query, transformation steps, sample output) 2. **Data Visualization** — Import figure factory, render the graph ### Directory Structure ``` notebooks/ ├── README.md ├── overview/ ├── housing/ ├── safety/ ├── demographics/ └── amenities/ ``` ### Notebook Template ```markdown # [Graph Name] ## 1. Data Reference ### Source Tables - List tables/marts used - Grain of each table ### Query ```sql SELECT ... FROM ... ``` ### Transformation Steps 1. Step description 2. Step description ### Sample Data ```python df = pd.read_sql(query, engine) df.head(10) ``` ## 2. Data Visualization ```python from portfolio_app.figures.choropleth import create_choropleth_figure fig = create_choropleth_figure(...) fig.show() ``` ``` Create one notebook per graph as each is implemented (15 total across 5 tabs). --- ## Phase 7: Final Documentation Review After all implementation, audit and update: - [ ] `CLAUDE.md` — Project status, app structure, data model, URL routes - [ ] `README.md` — Project description, installation, quick start - [ ] `docs/PROJECT_REFERENCE.md` — Architecture matches implementation - [ ] Remove or archive legacy spec documents --- ## Data Source Reference | Source | Datasets | URL | |--------|----------|-----| | Toronto Open Data | Neighbourhoods, Census Profiles, Parks, Schools, Childcare, TTC | open.toronto.ca | | Toronto Police | Crime Rates, MCI, Shootings | data.torontopolice.on.ca | | CMHC | Rental Market Survey | cmhc-schl.gc.ca | --- ## CMHC Zone Mapping Note CMHC uses 15 zones that don't align with 158 neighbourhoods. Strategy: - Create `bridge_cmhc_neighbourhood` with area weights - Allocate rental metrics proportionally to overlapping neighbourhoods - Document methodology in `/toronto/methodology` page --- *Document Version: 2.0* *Trimmed from v1.0 for execution clarity*