Inspiration
Local government impacts our daily lives more than any other level of government, yet civic participation is at an all-time low. Why? Because the information is completely inaccessible. Last week, major zoning and transit motions passed in Toronto City Council, but everyday residents had no idea because the details were buried in 40-page, jargon-filled PDFs. I realized that the problem isn't voter apathy; it's a massive UX problem. I built Civic Toronto because democracy shouldn't require a law degree.
What it does
Civic Toronto is a legislative transparency and grassroots tracking platform designed for the everyday citizen.
AI-Powered Translation Layer: It pulls real-time municipal notices and meeting agendas from the City of Toronto Open Data API and uses Claude 3 to translate dense "legalese" into nonpartisan, 8th-grade reading-level summaries (3 simple bullet points: What is happening, who it affects, and how to participate).
Ward-Level Context: An interactive map visualizes which wards have the most active development or legislative motions.
Voting Record Dashboards: It provides historical context on how local councilors vote on specific categories (Housing, Transit, Budget), empowering users to hold their representatives accountable.
How I built it
I utilized a decoupled full-stack architecture:
Backend: I built a lightweight REST API using Python and FastAPI. This server fetches raw JSON data from the Toronto Open Data portals and acts as the secure middleman to the Anthropic API.
AI Prompt Engineering: I carefully engineered our Claude prompts to act as a "nonpartisan civic educator," strictly stripping out political bias and focusing solely on factual impact to maintain ethical alignment.
Frontend: I used React (Next.js) and Tailwind CSS for a clean, accessible UI. I integrated Recharts for the voting data visualizations and React-Leaflet to map Toronto's GeoJSON ward boundaries.
Challenges I ran into
Dependency & Environment Hell: I hit several roadblocks setting up our Python virtual environments, managing CORS policies between our local frontend and backend ports, and securely handling API keys in Windows PowerShell without exposing them.
Ethical AI Guardrails: It was challenging to ensure the LLM didn't accidentally introduce bias or "tell the user how to vote." I had to iterate on our prompt engineering heavily to ensure the output remained purely informational and objective.
Messy Open Data: Municipal data is notoriously unstructured. Parsing the raw, nested JSON from the City of Toronto API and matching it to specific ward geometries required significant data wrangling.
Accomplishments that I'm proud of
I are incredibly proud of successfully bridging the gap between a raw, intimidating government database and a sleek, user-friendly dashboard. Watching Claude successfully take a wall of terrifying municipal zoning text and instantly turn it into three simple, unbiased bullet points felt like a massive win for civic accessibility.
What I learned
I learned a massive amount about full-stack integration (connecting React to FastAPI), the intricacies of open data ecosystems, and the deep ethical considerations required when applying generative AI to democratic processes. I learned that AI's best use case here isn't making decisions for people, but lowering the barrier to comprehension so they can make their own.
What's next for Civic Toronto
I want to expand the data pipeline to include other Ontario municipalities like Waterloo Region and Ottawa. I also plan to build an SMS notification system so residents can subscribe to their specific ward and get a text message summary whenever a relevant motion is proposed.
Log in or sign up for Devpost to join the conversation.