Neighborhood Prayer
Overview
Neighborhood Prayer was born from a simple idea: what if you could look at your street from above and instantly know who lives where, what they're going through, and how to pray for them? The result is a tool that makes a neighborhood feel smaller, more personal, and more intentional. It transforms any aerial photo of a neighborhood into a living community directory — letting users pin houses directly on their actual street and attach names, prayer requests, and contact info to each one. Everything runs locally in the browser. No server, no account, no data ever leaves the device.
Features
- Upload any aerial photo and click directly on houses to place pins with normalized coordinates that scale correctly at any window size
- Full neighbor profiles: names, address, fun facts, prayer requests, and contact info — all fields optional
- Drag-to-reposition pins in Edit mode with smart click-vs-drag detection (5px threshold)
- Prayer status tracking — answered prayers glow green on the map and display a confirmation badge
- Full-screen neighbor directory filterable by prayer status, printable as a clean two-column dated handout
- All data persists to localStorage automatically, with JSON export/import for backup and device sharing
- Edit and View mode toggle with keyboard shortcuts (E / V) so you never accidentally move a pin
Technical Details
The entire application is a single self-contained HTML file — no external dependencies, no build step, no backend. Built with vanilla HTML, CSS, and JavaScript. Neighborhood photos are stored as base64 data URLs in localStorage so the image persists across sessions without any server upload. Pin positions are stored as normalized floats (0.0–1.0) relative to the image dimensions so they always point to the right house regardless of screen size. The printable directory is generated as an in-memory HTML fragment triggered with window.print(), with CSS @media print rules hiding the app UI.
Engineering Challenge
The trickiest part was the drag-to-reposition system — distinguishing between a click that should open the editor and a drag that should move the pin, without accidentally triggering the wrong one. A 5px movement threshold on mousedown/mousemove/mouseup events solved this cleanly, with CSS transitions disabled during active drags for smooth real-time movement.