Inspiration

Toronto residents can report a pothole, a broken park light, or illegal dumping through 311, then wait. The request is public. The street is still broken. Neighbours who would chip in a few dollars have no way to put money on that block, see progress, or keep a receipt.

ZoneUp started from that gap: the City already publishes the work; residents still cannot fund a specific neighbourhood repair. We wanted a civic marketplace that feels municipal — not a neon startup — and that stays honest about what a hackathon prototype can and cannot claim.

What it does

ZoneUp is a Toronto civic marketplace.

Residents browse open challenges imported from City of Toronto 311 open data (potholes, parks, waste, lighting, signs) plus resident-filed worksites in Custom mode. They donate with an in-app card checkout, receive a demonstration CRA-style tax receipt (sandbox only — not a real CRA filing), and can post a QR code at the physical site that opens a public audit page.

The product also includes:

  • A City Map of open worksites (default centre: downtown Toronto, 43.6532, −79.3832)
  • An Honor Roll ranking residents by total contributions, civic XP, and tier
  • Electronic tax receipts a resident can print or save
  • Completed donations, so fully funded worksites leave the open list
  • Admin controls to remove a challenge (demo resident account)

Demo login: [email protected] / Civic2026!

Live site: https://zoneup-indol.vercel.app

ZoneUp is not affiliated with the City of Toronto or the Canada Revenue Agency.

How we built it

Frontend: React 18, Vite, Tailwind CSS, React Router, Leaflet / React-Leaflet, Lucide icons.

Backend: Flask, SQLAlchemy, SQLite, PyJWT, Stripe, Pillow, qrcode, requests.

Data: City of Toronto 311 customer-initiated service requests via the CKAN open-data catalogue (ZIP snapshot). We keep fundable categories (potholes, bins, parks, lighting, graffiti, signals, and similar) and skip noise that is not a neighbourhood repair. 311 rows often have an FSA or intersection, not a GPS point, so map pins are approximate.

Payments: Stripe test mode. The checkout asks for card number, expiry, and CVC so it looks like a real donation. The browser never sends the raw card number to Flask (PCI). In sandbox we map well-known test cards to Stripe PaymentMethods (for example 4242… → Visa). Estimated tax credit uses a simple Ontario-style rate of $0.33 per dollar for the demonstration receipt.

Hosting: Vercel (React static build + Python serverless API). Because Vercel’s filesystem is ephemeral, registrations and donations are snapshotted to Vercel Blob so the SQLite database survives deploys.

Challenges we ran into

Open data is messier than a mock feed. Toronto’s Open311 endpoint was not usable (access denied). The public CKAN ZIP worked, but it is a snapshot with FSAs and intersections, not lat/lng. We had to geocode approximately and say so on the map, instead of pretending every pin is exact.

Serverless SQLite forgets users. On Vercel the database lived under /tmp and vanished between deploys. People

Built With

Share this project:

Updates

Submission history