Scouting for Food Drive Coordinator

WebMobileGISOperations
Vanilla JS Node.js Service Worker SVG Maps County GIS (ArcGIS REST) OpenStreetMap Python Playwright Docker Cloudflare Tunnel

Project Overview

Who

I built this for Cub Scout Pack 51 in Modesto. It's for the leaders who run our Scouting for Food drive and the families who walk the routes. Scouts drop bags on doors one day and pick up the food a few days later. This year that's 13 routes and about 2,300 bags.

What

A mobile web app that replaces the route binder. Each route has a private link and a QR code printed on its sheet. A family scans the code, checks in, and gets a map of the houses on their route. They can check off houses, jump to the next house, get directions, and send leaders a supply request, an emergency alert, or a message.

Leaders get a dashboard that refreshes every few seconds. It shows which groups are out, progress on each route, and any open alerts. Leaders can message one route or all of them. There's also a route editor, so leaders can change streets without me, and every route prints as one double-sided sheet with the map, street list, checklist, and QR code.

More than one family can work the same route. Each family checks in and out on its own. The page also works without signal. Check-offs are saved on the phone and sync when it reconnects.

When

October 2026, for the November 2026 drive. I had a working demo in a day. The rest of that week went into entering the 13 real routes, locking it down for real families, writing a leader guide, and building the test suite.

Where

It runs as its own small container next to the pack's website at scouting-51.com. It's self-hosted on my homelab and published through Cloudflare Tunnel. Families only get in through their route link. Leaders sign in with the same accounts they use for the website.

Why

The drive ran on a paper binder and phone calls. Leaders couldn't easily tell which routes were done or who was still out. Families worked from marked-up printouts. The binder's house counts also didn't always match the streets listed.

I wanted everyone looking at the same live picture. Since real families' names and phone numbers go into it, I also wanted it locked down. Each route has its own access key, the app is kept separate from the website accounts, and contact info is deleted automatically after the drive.

How It Works

  • House locations come from Stanislaus County's public address data. Streets come from OpenStreetMap. A Python script rebuilds each route from the binder's street list and side-of-street notes, then flags any house that isn't on a route so a leader can decide where it goes.
  • The maps are drawn as SVG straight from that data, with no map library. That keeps the page to one file the phone can hold onto offline.
  • A family's link only opens their own route. They can't see other families' phone numbers. Leaders are checked against the website's accounts, and there's a separate lower-access role just for food drive leaders.
  • Contact info is purged on a set date, including backups. CSV exports leave phone numbers out unless a leader asks for them.
  • 128 automated Playwright tests run the real page in a headless browser against a throwaway copy of the server. They cover the lockdown, the route editor, multiple families on a route, the purge, and the print layout.
  • The leader guide is written for people who aren't technical. It's searchable and has a FAQ. The family pages are also in Spanish.

Still open: the first real drive hasn't happened yet. My location, next house, and directions can't be tested by the automated suite, so they still need a real phone test outdoors. Part of the Spanish text still needs a native speaker to review it.

Stack & Tools

App Type
Mobile web app, works offline
Frontend
Vanilla JS, SVG, no build step
Offline
Service Worker, queued writes
Backend
Node.js, no dependencies
Map Data
County GIS, OpenStreetMap
Data Build
Python
Testing
Playwright, 128 checks
Print
Double-sided route sheets, QR codes
Containers
Docker, Docker Compose
Remote Access
Cloudflare Tunnel