Community Gardens

An interactive map for finding and adding community gardens around New Zealand. You browse gardens on a clustered map, open any one for a full profile, and if you're logged in you can submit a new garden with photos and a deep set of environmental details.

Community garden profile page for Newtown Garden, Wellington
A garden profile, pulled from a GeoJSON feature and rendered with its address, contacts, stats and a location map.

Tech Stack

  • ·Frontend: React 19 with TypeScript, built on Vite and styled with Tailwind v4. Routing uses React Router 7's createBrowserRouter pattern. Deployed on Vercel.
  • ·Backend: Express 5 on Node with ES modules, MongoDB through Mongoose, deployed on Railway. Images go to Google Cloud Storage rather than the app server.

How It Works

The map loads every garden from the backend as a GeoJSON FeatureCollection. I went with GeoJSON as the transport format on purpose: it plays nicely with mapping libraries out of the box, and it keeps geometry and properties cleanly separated. On the frontend I convert each GeoJSON feature back into a typed Garden interface so everything stays type-safe across the boundary.

Clustering runs client-side with supercluster (75px radius, recalculated on every pan and zoom). Individual gardens render as a custom leaf SVG; clusters render as a dark green circle with a count, and clicking one zooms to exactly the level that breaks it apart.

Map of the Wellington region with gardens grouped into green leaf markers and count bubbles
Supercluster grouping nearby gardens into count bubbles that break apart into leaf markers as you zoom in.

Auth is JWT-based. You register or log in, the backend hashes and checks the password and signs a token, and the frontend stores it in localStorage. Protected actions (adding a garden, uploading a photo) send the token as a Bearer header, and middleware on the server verifies it before letting the request through. The UI hides the add button when you're logged out, but the real enforcement is server-side.

The add-garden form is the most involved part of the frontend. It's a big form with a lot of dynamic array fields: facilities, rules, events, produce types, soil types, water conservation methods, a full seasonal planting calendar, opening hours with a 'copy Monday to every day' shortcut. Each field offers preset checkboxes plus the option to type your own. Photos upload to GCS and come back as URLs that get stored on the garden record.

Photo gallery on a community garden profile page
Each garden carries a photo gallery, rendered in a masonry-style grid on the profile page and in the map's quick-look drawer.

Decisions

  • ·Offloading images to GCS keeps the API server lightweight and uses in-memory buffers so there are no temp files lying around.
  • ·Client-side clustering means the server just hands over all the points and the browser does the grouping work, which is fine at this scale.