MapApp
Wildfire exposure assessment for Canadian properties: country-scale raster risk layers made interactive in a browser, with an escape-time estimate attached to a specific address.
Built at Tezeract, where I was Lead Engineer. I architected and developed this product personally: the AI pipeline, the backend and the system design.
Architecture Overview
A geospatial pipeline in Python producing pre-computed raster layers, served to a React map client as pyramid tiles. Fuel classification and risk scoring run offline over source rasters and vector datasets, writing results into a tiled pyramid plus a queryable store for point lookups. The browser never sees full-resolution national data. It requests the resolution appropriate to its zoom level, and area selections resolve server-side against the underlying data rather than against the rendered tiles.
The Challenges
Problem
The risk surface covers Canada at a resolution fine enough to distinguish one property from its neighbour. That dataset cannot be sent to a browser, and a map that only works when zoomed in is useless for the country-level overview the product opens with.
Solution
Standard geospatial answer applied properly: pre-compute a tile pyramid so each zoom level carries only the resolution it can display, and keep the analytical queries away from the tiles entirely. The visual layer is a rendering artefact; when a user selects a region, the numbers come from a server-side query against the source data at full resolution. Conflating the two, by computing statistics from the tiles being displayed, is the easy mistake here, and it silently makes every reported figure a function of the user's zoom level.
Problem
The inputs came from different agencies at different resolutions, projections, vintages and classification schemes. Fuel-type data, forest cover, historical fire perimeters and parcel boundaries did not agree on grid, and naively resampling everything to a common grid quietly manufactures precision that the coarsest input does not support.
Solution
We normalised to a common projection and grid, but carried the provenance and native resolution of each input through the pipeline rather than discarding it at ingest. Where a derived value depended on a coarse input, that constraint remained attached to the output, so the interface could avoid presenting a property-level number that was really a kilometre-scale number resampled small. Getting this wrong is not a rendering bug. It is the difference between an assessment and a confident-looking fabrication.
Problem
The most compelling number the app produces is also the most dangerous one. An estimate of how long a fire would take to reach a property is a model output derived from fuel, terrain and distance under assumed conditions, and a user reading it as a countdown could make a genuinely fatal decision on a windy day the model did not anticipate.
Solution
We treated the framing as part of the engineering, not as copywriting applied afterwards. The estimate is presented as a comparative planning figure under stated assumptions rather than a prediction, expressed as a range, and paired with the inputs that drove it so a user can see it is conditional. The product's job is to tell someone their exposure is materially worse than they assumed and that they should have a plan. It is explicitly not an evacuation timer, and building it so that it could never be mistaken for one was a requirement rather than a disclaimer.