← Back to Home
Live — Web App Android Companion in Development

Lost & Found

lostfound.vectorintelligencelabs.ca

Overview

Lost & Found is a community lost-and-found board. When a pet bolts through an open gate, a wallet falls out of a jacket, or a bike disappears from a rack, the information that matters is scattered across group chats, phone calls and paper posters — and the first few hours are the ones that count. Lost & Found puts it all on one map.

Anyone can report a case: what is missing, a description, photos, identifying details, and the last place it was seen. Anyone can report a sighting — a photo, the location, and how confident they are. Every case gets a short, human-readable case number you can read out loud, text to a neighbour, or paste into a search box. The result is a single shared picture of where something was last seen and who has looked for it since, instead of a dozen half-told stories.

It comes in two halves: a public web app you can open in any browser without installing anything, and an Android companion app for the people actually out walking the streets and knocking on doors.

How it works

  1. Report the case. Pick a type — missing person, missing pet, or lost item — then add a title, a description, photos, subject details (name, age, distinguishing features, what they were wearing) and the last-known location, dropped as a pin on the map or taken from your current position.
  2. Add sightings. A sighting is a photo plus the place it was taken. In the Android app the photo and the GPS fix are captured together, and the photo's own EXIF metadata is stripped on the device before it is uploaded — the location comes from the sighting you are reporting, not from hidden data inside the image.
  3. Watch it on the live map. Every public case appears on one clustered map, colour-coded by status (pending, resolved, archived and the rest) with the sightings layered on top of the last-known position. Click a marker and you are on the case page. Zoomed out, nearby sightings collapse into a cluster badge so a busy neighbourhood stays readable.
  4. Follow a case. Follow the ones you care about and get notified when a new sighting, comment or status change lands — in the web app, or as a push notification from the Android app.
  5. Let the engine suggest, then decide. A correlation engine compares each new case against nearby and similar existing ones — proximity, type and timing — and proposes matches above a confidence threshold. Nothing is ever linked automatically: a human accepts or rejects every suggestion, and the UI says so.
  6. Resolve it. A case moves through a real lifecycle — pending, active, resolved, cancelled, archived — and the illegal transitions are rejected by the server, not just hidden by the interface. Archived cases stay readable, because a resolved case is still useful to the next person searching for a match.

Screenshots

The Lost & Found web app's live map: clustered case markers over an OpenStreetMap basemap, with a colour legend for pending, resolved, cancelled and archived cases.
The live map (web): every public case, clustered, with a status legend and a click-through to the case page.
A Lost & Found case page in the browser: case number and status badges, title, description, the last-seen map with a last-known marker, a case photo, a subject card with identifying details, and the start of the comments thread.
A case page (web): status badges, the last-seen map, photos, subject details and comments in one place.
The Lost & Found Android app's Map tab: a full-screen OpenStreetMap basemap with case markers and the app's bottom navigation bar for Home, Search, Map, Alerts and Profile.
The Android app's map tab: the same cases, offline-friendly tiles, and one tap to the case.
The Lost & Found Android app's Report a sighting screen: a camera preview area above the note that the photo and GPS location are attached to the sighting and that GPS data in the photo is stripped on-device before upload, with Cancel and Take photo buttons.
Reporting a sighting (Android): take the photo, and the GPS fix and EXIF-stripping happen on the device.

Captured from the live deployment and from the Android app on a physical device.

Who it's for

  • Neighbourhood and community groups — one shared board instead of five competing group chats, with a map everyone can read.
  • Pet owners — the highest-traffic case type, with the details that actually help (markings, temperament, the last place the gate was open).
  • Rescues, shelters and clinics — a stray that turns up at a clinic can be matched against open cases in minutes.
  • Event organisers — a festival or a tournament is a lost-and-found office for two days; this gives it a map and a case number.
  • Anyone coordinating a search — sightings from people you have never met, all attached to one case with a timeline.

Privacy and trust

  • EXIF stripped on-device. Sighting photos are sanitised before upload, so a photo posted to a public case cannot leak the photographer's home address or camera details.
  • Short-lived media links. Photos are served through time-limited signed URLs rather than public object paths, and the media endpoints are not open directories.
  • Writes are gated. Accounts are required to create or change anything; registration, sign-in and every write endpoint sit behind Cloudflare Turnstile and per-IP rate limiting.
  • Sightings carry a confidence state. New sightings start unconfirmed; supporters can back one, and the case owner or a moderator can verify it or mark it disputed. Nobody's guess is silently presented as fact.
  • Public or restricted. A case's visibility is a property of the case, so sensitive ones can be kept out of the public map and search.
  • Nothing is auto-accepted. Related-case suggestions are proposals with a score — a human makes the link.

How it's built

The whole thing runs on Cloudflare's edge, with no server to babysit:

  • Cloudflare Pages + Pages Functions — the web app and its TypeScript API (auth, cases, observations, comments, follows, notifications, search, media) deploy together, with the API versioned under /api/v1.
  • D1 — the SQL database behind cases, sightings, comments, followers, notifications and rate-limit state.
  • R2 — three buckets (originals, public derivatives, thumbnails) so full-resolution uploads and what visitors download are managed separately.
  • Durable Objects — MediaProcessor for the image pipeline, CorrelationEngine for case matching, and CaseLive for per-case live updates over a WebSocket, so a case page reflects a new sighting without a refresh.
  • Queues — media processing, analysis, notification fan-out and correlation run asynchronously off the request path, so uploading a photo never blocks a sighting.
  • Firebase Authentication — email/password identity with verified email; the API verifies Firebase ID tokens against Google's rotating key set (cached, with a graceful fallback if the cache is unavailable).
  • Astro + React islands — static pages with interactive islands only where they earn their weight.
  • MapLibre GL JS with MapTiler/OpenStreetMap tiles on the web; osmdroid and OpenStreetMap tiles in the Android app.
  • Android: Kotlin + Jetpack Compose, on-device EXIF sanitisation, and Firebase Cloud Messaging for push.

Try it

The web app is live and free to browse — you only need an account to report, follow or comment:

Status

The web app and API are live at lostfound.vectorintelligencelabs.ca. The Android companion app is in development: it runs against the same production API and is used for on-device testing, but it is not published to Google Play yet. If you would like a build, get in touch.

The screenshots above are the real thing — taken from the live deployment and from the Android app on a test device, not mockups.