When I was younger, my family went through times when we needed help from local charities, food pantries, clothing programs, and things like that. I do not need to get into all the details, but I remember being surprised by how generous people could be when we really needed it.
A lot of people have perfectly useful stuff they want to donate. Coats, food, hygiene products, electronics, household items, whatever. The annoying part is figuring out where to actually bring it.
Every organization accepts different things, their needs change, and the information is usually spread across a bunch of different pages.
You type in what you have in normal language and enter a ZIP code or city. Sprinkle finds nearby organizations, checks what they accept, looks for current needs, and matches your items with what it finds.
Each result also includes a verification label and the sources it used, so you can double-check everything before loading up the car and driving somewhere.
The whole idea is pretty simple: make it easier for useful things to end up somewhere they are actually needed.
Sprinkle shows what it is doing while it parses the items, searches for nearby organizations, researches their donation info, and builds the matches.
A brand-new search can take a little while because it is doing live research instead of just pulling results from a static directory.
Sprinkle is built with React and TypeScript and runs through a single Cloudflare Worker.
The Worker handles the API, calls Gemini, streams progress back to the UI, and uses Cloudflare KV for caching and rate limiting. The Gemini API key stays on the server.
The research flow is split into four parts: Parse: gemini-3.5-flash-lite turns whatever someone typed into structured donation items with categories and conditions. Discover: gemini-3.7-flash uses Google Search grounding to find nearby organizations that might accept those items. Research: Gemini uses Google Search plus URL context to read public donation pages and pull out things like accepted items, things they do not take, drop-off details, and current needs. Match: Gemini compares the donated items with each organization's policies, then TypeScript handles the final score and sorting.
I originally tried doing discovery and research in one call because it was cheaper, but the results were noticeably thinner and I got fewer useful sources.
Splitting it into two stages worked much better. Sprinkle can first figure out which organizations are worth looking into, then spend the research call actually reading the pages that matter.
The verification system was also really important to me because I did not want the app confidently telling someone to drive across town based on shaky information.
If Gemini gives a confident answer but does not have a valid source URL to back it up, the Worker automatically knocks it down to Call first. The same thing happens when an organization's donation info is vague or contradictory, even if the actual item match looks good.
The UI gets progress updates through server-sent events. Cold searches can take a bit, so instead of staring at a spinner, you can actually see whether Sprinkle is finding organizations, researching them, or building the final matches.
Discovery results are cached for five days, and organization research is cached for 36 hours.
I intentionally do not cache Unknown results, because if a lookup fails once, I would rather let it try again next time than treat that failure as permanent.
