Mobile Application

CityFix:
Civic Engagement

A React Native community platform empowering citizens to report issues with geotagged photo evidence, propose solutions, and fund local sustainability projects.

UN SDG 114 external APIsGoogle Maps clustering

CORE CAPABILITIES

Issue Reporting

Geolocation & photo evidence tracking

SDG Alignment

Aligned with UN SDG 11: Sustainable Cities

Interactive Maps

Google Maps clustering & visualization

Crowdfunding

Fundraising for local initiatives

Real-time Chat

Community coordination messaging

Gamification

Points, rewards, and leaderboards

App Showcase

Six screens, one per capability — tap any to open it full size.

Home Dashboard
Location + Photo Upload
Proposals System
Explore Map View
Funding Dashboard
Gamification Leaderboard

My part

The server side

CityFix was a team build for the GNEC International Hackathon. Being specific about who did what matters more on a group project than on a solo one: I built the backend — the Express and Prisma REST API, and the database schema underneath it. The React Native client was not mine.

That split shaped what I had to get right. A mobile client on a patchy connection is an unforgiving consumer of an API: every response is something a phone has to render before the user loses patience, and the app cannot compensate for a schema that made the wrong thing hard to query.

The services deploy to Railway, split rather than bundled, so the pieces of the system can be restarted and reasoned about independently.

WHY THIS SHAPE

MongoDB, for one query

The central question this product answers is “what is broken near me”, which is a radius search over points on a sphere. MongoDB answers that natively with geospatial indexing rather than through an extension or a bounding-box approximation, and once the primary read path is a geo query, that is the decision that should drive the store.

Prisma over it anyway

A document store makes it easy for a schema to exist only in the heads of whoever wrote the last insert — which is exactly what a hackathon produces. Prisma forces the schema to be a written artefact several people can read and the client to be typed against it.

Firebase for identity

Authentication is the least differentiated part of a civic app and the easiest to get subtly wrong. Handing it to Firebase meant the API only ever has to verify a token, and no password ever reaches infrastructure we were maintaining.

Expo for reach

A reporting tool that only exists on one mobile platform reports half a street. React Native under Expo made both platforms one build, which for a civic product is closer to a requirement than an optimisation.

The workflow

A report is the start, not the end

Most civic reporting apps are a suggestion box: you file something, it vanishes into a queue, and you never learn whether anything happened. The design here treats a report as the opening move in a conversation with several possible participants — the reporter, an authority, and other residents — each of whom can act on it.

01Report it where it is

A report is a location before it is anything else. The reporter captures the spot and attaches photo evidence, so the record is a claim someone can go and check rather than a description that has to be trusted.

02Decide whether an authority is needed

Escalation is an explicit toggle at report time, not an automatic route. A cracked pavement and an unsafe transformer are both potholes in the data model and very different things in practice, and the person standing in front of it is the one who knows which.

03Find what is broken near you

Reports surface on a shared map, clustered and filtered by radius, so the question a resident actually asks — what is wrong around here — is answered directly instead of through a list they have to scan.

04Propose a fix

Both an authority and the community can put forward a resolution against an existing report. A proposal is a distinct object from the report, which is what allows more than one to exist for the same problem.

05The reporter accepts or declines

Proposals do not resolve anything on their own. The person who raised the issue accepts or denies, which keeps the final say with whoever is actually affected rather than with whoever replied first.

06Fund it and follow it

Work that needs money becomes a community project with a funding target and a visible timeline, so the gap between a reported problem and a paid-for fix is something residents can watch close rather than guess at.

Points and a leaderboard sit across the whole loop. Gamification on a civic product is easy to sneer at and hard to do without: the honest problem is that reporting a pothole benefits everyone slightly and the reporter barely at all, and something has to close that gap before the map has enough on it to be worth opening.

FOUR EXTERNAL SERVICES

Google Maps

Rendering, clustering and the map interaction itself.

OpenRoute

Geocoding — turning a dropped pin into something a person recognises, and an address back into coordinates.

OpenWeather

Conditions at a location, which is context a report frequently needs.

AQICN

Air quality, which is the one civic problem residents cannot see and therefore rarely report.

Each of the four answers a question the app cannot answer from its own data. None of them own anything: a report stays valid and readable if any one of them is unavailable, which is the only sane way to depend on four third parties at once.

Context

Built against SDG 11

The brief was the United Nations' eleventh Sustainable Development Goal — sustainable cities and communities — and that constraint is visible in the product rather than bolted onto it. The goal is about inclusive, safe and resilient urban settlement, which is why the app is as interested in who gets to propose a fix and who funds it as it is in logging the problem.

It took third place at the GNEC International Hackathon in 2024.

3rd place — GNEC International Hackathon, 2024
Team project. My contribution: backend API and database schema.

TECHNICAL ARCHITECTURE

frontend

  • React Native

    Expo Framework

  • NativeWind

    Tailwind for Mobile

  • JavaScript

    Core language

  • Zustand

    State management

backend

  • Node.js

    Runtime environment

  • Express.js

    Web framework

  • TypeScript

    Type-safety

  • Prisma ORM

    Database toolkit

infrastructure

  • MongoDB Atlas

    Cloud database

  • Firebase Auth

    Authentication

  • Railway

    Deployment

apis

  • Google Maps

    Map integration

  • OpenRoute

    Geocoding

  • OpenWeather

    Weather data

  • AQICN

    Air quality