SmartSustain
Type
Platform
Status
In production
Context
CGLS Tech · Full Stack Software Engineer · technology lead · Innovate UK funded
Period
2026 – present
Source
Private
700+
sites scored 0–100
5
councils served
M+
records through ETL
I lead the technology for SmartSustain, working with technical colleagues, planning officers and council stakeholders to turn loosely defined planning requirements into working features and explain the trade-offs in plain terms. I designed and built the FastAPI backend on PostgreSQL and SQLAlchemy, with async endpoints for site search, assessment, scoring, map data and the AI assistant; wrote the ETL pipelines that clean, normalise and load millions of records from inconsistent government and open-data sources; and built the map-driven React frontend on top. The hard requirement was never computing a number but defending it: the scoring engine is deterministic and weighted, and the AI agent answers questions grounded in the data for that specific site rather than in free generation.
FastAPI + SQLAlchemy on PostgreSQL · ETL pipelines over millions of government records · spatial queries with bounds-based loading and Redis caching · Elasticsearch site search with faceted filters · weighted 4-pillar scoring engine · LangChain agent with tool calling · RAG on pgvector with location and metadata filters · React + MapLibre frontend · AWS
- 01Led the technology for an Innovate UK funded platform used across five West Yorkshire councils, turning loosely defined planning requirements into working features with planning officers and council stakeholders.
- 02Designed and built the FastAPI backend on PostgreSQL and SQLAlchemy, with async endpoints for site search, assessment, scoring, map data and the AI assistant.
- 03Wrote ETL pipelines that clean, normalise and load millions of records from inconsistent government and open-data sources, and designed the data model and indexes to keep queries responsive at that size.
- 04Built geospatial queries over flood risk, road noise, air quality and other environmental layers, with Redis caching and bounds-based queries so the map only loads data for the area in view.
- 05Built an AI agent workflow with Python, LangChain and OpenAI models: planning officers ask natural-language questions, the agent invokes backend tools, retrieves site-specific information and synthesises actionable planning insights.
- 06Built the assistant's RAG pipeline on pgvector, combining vector search with location and metadata filters so answers are grounded in the data for that specific site.
- 07Built Elasticsearch site search by address, postcode, council or developer, with typo-tolerant matching and faceted filters by sustainability score, developability and site size.
- 08Implemented a deterministic, weighted scoring engine that rates 700+ candidate sites from 0 to 100 across environmental, economic, social and regulatory pillars.
- 09Delivered the map-driven React and MapLibre frontend consuming the platform APIs.
Drawn from the source
Services, data ownership, message flow and failure paths. Drag to pan, scroll to zoom, or open any diagram fullscreen.
End-to-end platform architecture
Millions of government records flow through per-dataset loaders and domain processors into a MongoDB geospatial layer, out through a scoring engine, and into a map-driven interface used by planning assessors across five councils.
The decisions worth talking through: where the interesting work was choosing between options, not writing the code.
Note 01
The product was auditability, not the score
A planning officer cannot act on a number they cannot defend at committee. That single constraint shaped the architecture: scoring had to be deterministic and decomposable rather than a fitted model, weights had to be inspectable, and the AI agent had to be a reader of that structure — calling backend tools and retrieving site data — rather than an independent source of claims.
Note 02
Only load what the map can see
Environmental layers are large and most of them are irrelevant to the area on screen. Bounds-based queries return only the features inside the current viewport, and Redis caches the expensive spatial results underneath, so panning the map stays fast while every score stays live.
Python / FastAPI / PostgreSQL / SQLAlchemy / pgvector / Elasticsearch / Redis / LangChain / OpenAI / React / TypeScript / MapLibre GL / AWS