Australian Inactive Housing Map
Official government spatial datasets are often locked behind sluggish, academic dashboards that fail to provide immediate local feedback. I built this interactive, instant-load WebGL mapping dashboard to demonstrate how we can better visualise ABS vacancy datasets for everyday users.
View the Demo →The Origin
This project was born out of a desire to build a more responsive, interactive spatial visualization tool than the standard resources provided by the government.
After attending a lecture on housing statistics, I began looking into the official numbers compiled by the Australian Bureau of Statistics (ABS). I found that the ABS does provide a map—specifically an ArcGIS-based storymap—but the visualiser was sluggish to navigate, lacked immediate local feedback, and felt a little too academic.
I wanted an excuse to experiment with client-side WebGL mapping engines and responsive visual states. The goal was to build a lightweight, standalone client application that could load large spatial boundaries instantly and let users query their local area, then estimate a human cost.
Key Engineering Decisions
Rather than building a standard database-driven web application, the project was structured around three specific architectural decisions to optimise speed and data clarity.
1. Zero-API Static Ingestion (Local Data)
Instead of querying slow external government ArcGIS servers at runtime—which introduces network latency and CORS complications—the application operates on a Zero-API architecture.
All geographic boundary shapes and statistics are pre-compiled and bundled directly as local JSON/GeoJSON files. By pre-simplifying high-density polygons using the Visvalingam-Whyatt algorithm, I compressed over 540 Councils and 2,300 Suburbs into a single client-side asset under 5MB that parses instantly. Largely done because I felt a larger download footprint was significantly less noticeable than a 5-15 second compiling delay on page load.
Data is cheap, but phones are slow
2. Multi-Mode Leaderboards & Urban-Only Filtering
Comparing metropolitan cities directly against small holiday towns on a single vacancy rate index produces skewed results (e.g., a tiny holiday village showing 25% vacancy but only 50 units, versus a major city showing 1.5% vacancy but representing thousands of empty homes).
To make the comparisons meaningful, I designed a multi-mode sorting dashboard in the sidebar:
- By Volume: Sorts by the absolute count of empty dwellings to highlight high-density areas where vacancy volume is greatest.
- By Percentage: Sorts by raw vacancy rate to highlight regional spec-holding hubs.
- By State Aggregate: Dynamically rolls up all active councils to highlight regional/jurisdictional trends.
- The "Urban Only" Toggle: Filters out small regional/holiday communities by isolating councils with ≥ 15,000 dwellings, focusing analytical attention on areas experiencing high-density rental and buying stress.
3. Humanising the Numbers (Household Size Multipliers)
Raw vacancy percentages (e.g., "1.3%") feel highly abstract. To ground these numbers in real terms, the dashboard sidebar translates counts into housing capacity using a straightforward multiplier:
By mapping average household size constants derived from local Census data for each individual council area, the map estimates exactly how many people could be accommodated. In Salisbury Council, a multi-agency MADIP indicator identifies 267 inactive dwellings. Multiplied against the local constant of 2.66 persons per household, it outputs a capacity of 710 displaced people, humanising a dry statistic.
Calculations & Testing Precision
To ensure the AI didn't get bored and wander, I integrated automated unit tests early on to validate calculations across varying data subsets.
Smart Meter Denominator Correction
A mistake the AI loved to make was multiplying the electricity inactivity percentage against the council's Total Dwellings. In councils with lower smart-meter coverage, this overstates empty units by up to 27%.
// Example Salisbury Council Math
Total Dwellings = 56,759
Dwellings with smart meter data = 44,693
Electricity Inactivity rate = 1.3%
✕ Naive count: 56,759 × 1.3% = 738 empty homes
✓ Correct count: 44,693 × 1.3% = 581 empty homes AI Workflow Series — Part 01
The Spec is the Product
In a post-AI world, the idea and the code for a project like this is valueless; only the spec holds value.
This project was built as an AI-led implementation experiment, with human-authored spec and review gates. Gemini 3 Flash acted as an enthusiastic (if a bit dim) coworker. I usually write high performance C++ or C, so this project was an experiment in delegating the implementation layer entirely. The unit tests were an absolute must, as was providing a way to test the UI/UX with Playwright.
My core philosophy is to treat the AI similarly to how I work with human juniors, but driven through a series of markdown files. A robust spec for this workflow needs four distinct components:
- Goal & Intent: The soft goal of the work: why we want to make it, and for whom.
- Scope & Specification: What it is, what it isn't, and how it should work and feel.
- UI/UX: General tone and feel, as well as detailing out specific components. With the caveat that if I don't detail it, it's not important to me, which I left entirely up to the AI to decide.
- Implementation Details: Architecture, coding principles, libraries to use, and deployment strategy.
With the spec defined, I let an AI agent break those down into an implementation plan, ensuring there were clear stages where I could manually review progress and direction. The process ended up more iterative than I planned—the spec needed more detail upfront.
One key finding: AI has a predilection to agree with the user too much. I regularly had to instruct it to be antagonistic towards me, or pretend I didn't write the spec, just so it would criticise the design fairly.