Appearance
F-019: ZIP Codes / Postal Areas
Status: Done · Priority: P1 · Branch: feature/F-019-zip-codes · Updated: Mar 5, 2026
Summary
Full postal code browsing system for Montreal rentals. Two levels of granularity: FSA (3-character prefix like H2T) pages with boundary polygons on Google Maps, and full 6-digit postal code pages (like H2T 2Y2) with pin markers. Index page shows all 193 Greater Montreal FSA boundaries on an interactive map.
Requirements
- [x]
postal_areastable — 193 FSAs with boundary polygons from Statistics Canada - [x]
postal_codestable — ~101K full codes from GeoNames (CC BY 4.0) - [x] FSA boundary conversion (Statistics Canada shapefiles, EPSG:3347 → WGS84 via proj4)
- [x] Seed script for postal areas (H + J prefix within ~50km of Montreal)
- [x] Seed script for postal codes (batch insert 500 at a time, onConflictDoNothing)
- [x] API:
GET /postal-areas— list all FSAs with listing stats + boundaries - [x] API:
GET /postal-areas/:fsa— FSA detail with boundary, listings, postal codes, stats - [x] API:
GET /postal-areas/code/:code— full 6-digit postal code detail - [x] Index page with interactive FSA boundary map (color-coded by listing count, click popup)
- [x] FSA detail page with boundary map, stats bar, postal codes grid, listings grid
- [x] Full postal code detail page with pin center + FSA boundary context
- [x] Header navigation link
- [x] Bilingual translations (EN/FR)
- [x] Fix: bedroom grouping (4+ instead of separate 4, 5)
- [x] Fix: /mo/mo duplicate price suffix
- [x] Documentation updates
Design
Data Sources
- FSA boundaries: Statistics Canada census boundary files (NAD83/Lambert Conformal Conic → WGS84). 187 of 193 FSAs have polygons.
- Postal code centroids: GeoNames CA_full.txt (free, CC BY 4.0). ~101K codes for Greater Montreal.
- LDU boundaries: Not available as open data. Commercial sources (DMTI/CanMap, geocoder.ca) cost $800+. The
boundarycolumn onpostal_codesis reserved for future generation from accumulated listing coordinate data.
Coverage
Greater Montreal: H-prefix (Montreal island, Laval) + J-prefix suburbs within ~50km of downtown (45.5, -73.57). Includes Brossard, Longueuil, South Shore, Laval, and surrounding areas.
Map Interactions
- Index map: All FSA boundaries rendered as Google Maps Data layer. Blue fill scaled by listing count, gray for empty. Click shows AdvancedMarker popup with FSA info + "View area" link.
- FSA map: Single boundary polygon + price markers for each listing.
- Code map: Pin center for postal code + parent FSA boundary for context.
Discussion Notes
Mar 5, 2026
- Built complete postal code browsing system: DB tables, seed scripts, API endpoints, frontend pages
- Expanded from H-prefix only to full Greater Montreal (H + J prefix within 50km radius)
- Seeded ~101K postal codes from GeoNames (56K H-prefix + 45K J-prefix)
- Converted 187 FSA boundaries from Statistics Canada shapefiles (Lambert → WGS84 via proj4)
- Fixed bedroom grouping bug (4+ bucket), /mo/mo display bug, missing ListingSummary fields
- Index map: click shows popup tile (not direct navigation) per user request
- LDU boundaries confirmed as commercially gated only — reserved boundary column for future data accumulation
Implementation Notes
Key Files
packages/database/src/schema.ts— postal_areas + postal_codes tablespackages/database/src/seed.ts— seedPostalAreas() + seedPostalCodes()packages/database/data/fsa-boundaries-mtl.json— 187 FSA boundary polygons (WGS84)packages/database/data/postal-codes-mtl.tsv— 101K postal code centroidspackages/database/scripts/convert-fsa-boundaries.ts— proj4 boundary conversionservices/api/src/routes/postal-areas.ts— 3 API endpointsservices/web/app/[locale]/postal/— route pagesservices/web/components/postal/— all postal UI componentsservices/web/lib/api.ts— postalAreasApi client