Inspiration
Since May 2023, multiplexes of up to four homes have been allowed on residential lots across Toronto. On October 2, 2026 the City released four free pre-approved multiplex designs. But nothing tells you whether one of those designs fits on your lot, and nobody shows, ward by ward, where multiplexes could go next to where they've actually been permitted. We built Suplex to answer both for any address in Toronto.
What it does
Type a Toronto address. The street builds itself in 3D and a City design rises on your lot, floor by floor. Then you can zoom out to your ward.
- Address check: a rules engine (code, not AI) tests all four designs against your lot and Zoning By-law 569-2013. Each design gets a result: fits, too close to call, doesn't fit, or not checked. You see the rule, the margin and the by-law section. City lot lines aren't survey-accurate, so anything within 0.5 m (or 2 percentage points of lot coverage) is "too close to call". The check ends with next steps toward a permit, taken from City pages.
- Ward map: lots where a design may fit (an upper bound), next to the multiplex permits actually issued since May 2023, with a monthly trend chart. No rankings, no addresses on the map, and no list or export of lots.
- Ward briefing: a one-page summary written by Gemini, using only numbers our engine computed. Every number links to its source. It reads in English or French.
Every result says "Screening only, not a permit or legal advice."
How we built it
- Engine: Python with Shapely and pyproj. All distances and areas are in metres, and every rule carries its by-law section. The same engine runs the live check and the citywide batch, so the map and the check never disagree.
- Data pipeline: GeoPandas, built on City of Toronto Open Data (property boundaries, zoning, building permits, 3D massing, address points, wards).
- API and AI service: FastAPI
- Frontend: React, TypeScript and Vite. The 3D street is three.js with react-three-fiber, and the ward map is MapLibre GL with OpenFreeMap tiles.
- AI: Gemini API for the address explanations, the ward briefing and the French translation.
- Database: Tiger Data (TimescaleDB on PostgreSQL) for the permit history and the trend chart.
Challenges we ran into
The City's data was the hardest part. The property boundary file has no street parcels, so we couldn't tell which side of a lot faces the road. We rebuilt the streets ourselves from the gaps between lots. The unit limits in the zoning GIS data are older than the 2023 multiplex rules, so we wrote those rules by hand from the by-laws. And one 3D massing polygon often covers a whole row of houses, so we had to measure buildings lot by lot.
Matching the City's permit count took a while. For May 2023 to November 2024, our first count was 1,278 multiplex permits. The City says 452. About 830 of ours were a single suite added to a house, which the permit data labels as a "2 Unit" structure. Once we only counted permits that create 2 to 6 homes, we got 446, and Ward 04 matched the City exactly (42 and 42).
We also had to stop Gemini from making up numbers. It never sees the real values, only placeholders like {{lot_width_actual}}, and a validator rejects any draft with a number we didn't give it. The night before the demo, while taking a screenshot for the slides, we found the AI cache was missing every request from the browser. JavaScript writes 22.0 as 22, so the browser and our Python code made different cache keys. Every demo request would have been a live Gemini call.
Accomplishments that we're proud of
We ran all 495,456 lots in Toronto through the engine, 421,204 of them house lots, and the 19 lots we measured by hand against the by-law still get the same answers. An address check took at most 43 ms in our tests. Our permit count is 446 against the City's 452, and Gemini can't put a number on screen that our code didn't calculate.
What we learned
There's a lot of room for multiplexes in Toronto. A free design may fit on up to 191,174 house lots (45.4%), and only 1,447 multiplex permits have been issued since May 2023. In Ward 04 it's up to 3,992 lots against 83 permits. These are upper bounds, since we don't check every rule (site-specific exceptions, heritage and trees, for example), but the gap is still big.
We also learned that the data takes far longer than the model. Rebuilding streets and matching permits took more time than the whole AI part.
What's next for Suplex
- Read site-specific zoning exceptions. In Ward 04, 88% of lots carry one, and right now we only flag them.
- Track whether permits go up now that the free designs are out.
- Host it publicly so anyone can use it.
A longer narrated walkthrough can be found here.
Built With
- fastapi
- gemini
- geopandas
- maplibre
- openfreemap
- postgresql
- pyproj
- python
- react
- react-three-fiber
- shapely
- three.js
- tiger-data
- timescaledb
- typescript
- vite
