Skip to main content
← Back to portfolio

Building a Zero-Cost Grant Monitoring Microservice

App Development · June 2026

With our three team roles confirmed funded through FY27, I began transitioning into a grants-facing capacity alongside my UX engineering responsibilities, taking on the early infrastructure work that a dedicated grants professional would otherwise own.

Building a Zero-Cost Grant Monitoring Microservice

Role: Product Owner / UX Engineer
Tools: Python, Playwright (browser automation), Claude (architecture planning & iteration partner)
Timeline: Summer 2026, initiated during federal funding instability affecting Morehouse School of Medicine

Context

The Health Equity Tracker (HET) at the Satcher Health Leadership Institute (SHLI) is a small, three-person engineering team building open-source public health data infrastructure. For several years, our funding model leaned heavily on federal sources — a dependency that became structurally untenable in 2025–2026 as DOGE-related cuts hit Morehouse School of Medicine broadly. With our three team roles confirmed funded through FY27, I began transitioning into a grants-facing capacity alongside my UX engineering responsibilities, taking on the early infrastructure work that a dedicated grants professional would otherwise own.
The first problem I encountered wasn't writing proposals — it was knowing when and where to write them. Foundation grant cycles are time-sensitive and poorly publicized; a window can open and close in weeks. Rather than monitoring dozens of foundation websites manually or investing in a grant database subscription that tracked historical awards rather than live open calls, I scoped and built Grant Watchdog: a lightweight automation tool that watches the live web pages of curated funder targets for changes, flags potential new opportunities, and generates a plain-language report the whole team can read.

The Problem

Three constraints shaped every decision in this project:

  1. Institutional capacity without institutional infrastructure. HET has no grants staff, no subscription to a live opportunity database, and no budget to add either in the near term. Any solution had to work within what already existed — including the fact that our team already uses Playwright for testing, meaning the dependency was familiar rather than foreign.
  2. Information that's only useful when it's timely. A grant opportunity missed by two weeks is the same as a grant opportunity that never existed. The system needed to surface signal — not noise — at the moment it became actionable, not during a periodic manual sweep that might happen monthly if at all.
  3. A tool the whole team could maintain, not just the person who built it. I wouldn't be the only person touching this. Any funder could be added, removed, or updated by a teammate without reading the core codebase. The interface layer for non-engineers had to be legible on its own terms.

Design Process

Starting with the failure mode of the original plan

The initial concept called for using the Candid Grants API to identify target foundations programmatically. Candid is the standard institutional tool for this work, and I had access to a 30-day trial key pending delivery from their developer team. But reading through their API documentation before the key arrived surfaced a critical structural mismatch: their data tracks historical, closed grant transactions — IRS 990 filings — rather than live, open application windows. Even a well-funded, maintained integration would tell us who gave to whom in prior years, not whether a foundation had just posted an FY27 RFP.
This was a UX insight before it was a technical one. The question wasn't "can we access the Candid data?" but "does the Candid data answer the question we're actually asking?" It didn't. I pivoted the design to use Candid's trial key for a one-time harvest — building a master target list of foundations with a history of funding health equity, open-source tech, and HBCUs — and replaced the ongoing API dependency with a Playwright scraper that monitors the live grant pages of those targets directly.

Configuration as the real user interface

Once I'd committed to a scraper-first architecture, the most consequential design decision wasn't the Python script — it was what sat between the script and the humans who would use it. I structured the funder list as a standalone JSON file (targets.json) with human-readable fields: name, URL, CSS selector, tags, and a notes field for institutional context like access model, grant size range, and timing intel.
This separation meant targets.json became the system's de facto user interface. A teammate adding a new foundation doesn't need to understand asyncio or browser automation — they need to know a URL and a few field conventions, both of which are documented in a CONTRIBUTING.md written for our existing fork-and-PR workflow. The scraper is infrastructure; the target list is editorial judgment, and I wanted those two concerns owned by different people under different conditions.

Dual-signal detection over single-metric confidence

My first instinct for change detection was element counting: watch for DOM elements matching a CSS selector, flag any increase as a potential new opportunity. That's the obvious approach, and it works — until a foundation redesigns their grants page, which most do at some point without warning. A redesign could zero out a previously reliable count not because the opportunity landscape changed, but because the class name did.
The fix was a second, independent signal: a content hash of the full visible page text, captured on every sweep and compared against the previous run. Element count and content hash now work in tandem. A count increase triggers a high-confidence alert. A count-stable hash mismatch triggers a softer "worth a manual look" flag. A scrape error preserves the previous good state rather than zeroing the baseline. No single point of brittleness produces a false all-clear.
This mirrors something I think about in user research as well — a single metric can be gamed or misread; a converging pair of signals is harder to misinterpret, even when one of them breaks.

Designing the report for the person reading it at 8am on a Monday

The scraper outputs a human-readable HTML report after every sweep. I spent more design time on this than on any other piece of the output. The audience for this report isn't the person who built the tool — it's a small team of engineers and a soon-to-be grants-adjacent PM who need to scan it quickly and know exactly what to do next.
That meant the report couldn't just display data. It had to interpret it. Each row pairs an element count with a status label that describes what the combination means in plain language: "ALERT — New opportunities likely," "Page content changed — manual review suggested," "No change." A documentation section in the README explains every possible combination of count and status with a corresponding action — including the edge case most people would miss on a first read: a count of 1 with a main selector almost never means one opportunity exists; it means the entire page body matched, and the content hash is doing the real detection work.
Writing that interpretation guide was itself a UX exercise. The question wasn't "what did the tool find?" but "what does the person reading this need to do next, and how confident should they feel doing it?"

Scoping the funder list as a research act

Populating targets.json with foundations wasn't a data entry task — it was the first substantive grants research the HET team has done outside a federal context. I approached it by mapping our team's profile against funder priorities: health equity data infrastructure, open-source technology, HBCU institutional home, BIPOC and veteran team composition, and an emerging AI/LLM roadmap. That mapping surfaced targets I wouldn't have found by searching "health equity grants" alone — including the Patrick J. McGovern Foundation's Data Practice Accelerator (rolling applications, up to $125K, directly aligned with HET's data infrastructure work) and Humanity AI (a $10M open call from a ten-foundation coalition, explicitly prioritizing community-led groups closest to AI's impact, launching summer 2026).
The funder list is currently 17 entries. It will grow significantly once the Candid trial key arrives and a one-time harvest of the institutional database can be run — the tool was designed from the start to receive that import cleanly.

Reflection

This project forced me to think carefully about what "product ownership" actually means when the product's primary user is also its builder and the team is three people working across overlapping roles. In a larger organization, I'd have handed this requirement to a developer and reviewed the output. Instead, I scoped it, built it, debugged a Python 3.13 / Playwright compatibility error on my own machine, and wrote the documentation that would let someone else take it over.
That compression of roles clarified something I'd understood abstractly but hadn't felt as acutely: the moment you write the spec and execute it and write the user documentation, the gaps between those three activities become immediately visible. The README section on interpreting the report didn't exist in my mental model of the tool until I tried to explain what a main-selector count of 1 actually meant to someone who hadn't watched me build it. That explanation didn't emerge from the code — it emerged from imagining a real person reading a real output and being uncertain what to do.
The pivot away from the Candid API is also worth naming as a leadership moment, not just a technical one. It would have been easy to wait for the API key, build the integration I'd already planned, and discover six months later that the data didn't answer the question. Reading the documentation before the key arrived — and being willing to redesign around what I found rather than commit to the sunk cost of the original plan — is the kind of judgment that's harder to build than the technical skill to implement either approach.

grant-watchdog.gif
Health EquitySoftware EngineeringEquityData Visualization

Outcomes

  • A functioning Playwright-based monitoring microservice watching 17 foundation grant pages, running at zero ongoing cost
  • Dual-signal change detection (DOM element counting + content hash comparison) that survives foundation website redesigns without losing baseline state
  • A human-readable HTML report generated after every sweep, with plain-language status labels and a full interpretation guide for non-technical team members
  • A targets.json configuration layer and CONTRIBUTING.md that enable teammates to add, edit, or remove funder targets via standard PR workflow without modifying core code
  • An initial curated funder list built from team profile analysis, including active open calls (McGovern Data Practice Accelerator, Humanity AI summer 2026 open call) identified during the research process
  • A documented import path for Candid API harvest data, positioning the tool to scale significantly once institutional database access is available

Related work

Work of ServiceAug 2026

ETL Cohort Hub Portfolio Pipeline, Part 2

The technical build here is the smaller half of the story — the harder part was closing the gap between "I know how to do this" and "someone with zero technical background can actually finish it without me in the room." Most of the real fixes came from watching an actual classmate get stuck, not from re-testing my own assumptions.

Designed and built a portal-embedded wizard that lets non-technical cohort members generate their own QE-compliant portfolio site prompt — no code, no cost, backed by Google Sheets instead of a database they'd have to learn.

Software EngineeringAI LiteracyEd TechUX Design
Work of ServiceJul 2026

Designing a Private, Cross-Cohort Community Platform, Part 1

K1 graduated into a real institutional gap, with no established infrastructure or settled precedent for what the cohort even was yet. Underneath the platform, this case study is really about the leadership calls that come with building for a still-forming community — who gets access, what counts as consent, and how much structure the moment actually called for.

K1 is the first cohort of the Ed.D. in Educational Technology Leadership to graduate under Kean University's acquisition of NJCU — a transitional moment with no established infrastructure for cohort identity, alumni connection, or shared academic tracking. Rather than defaulting to a spreadsheet or a static Google Site (the pattern used by prior cohorts, C1–C13), I set out to build a living, access-controlled web application: a private hub for directory, academic calendar, and coursework tracking, with a path to eventually connect graduates across cohort years.

Software EngineeringAI LiteracyEd TechUX Design
Talk/PresentationApr 2026

Social Responsibilities Round Table Talk

From Data to Action: How Open-Source Health Data Platforms Democratize Research and Empower Community Advocacy

Open-source platforms like HET democratize research, transforming health equity from an academic concept to a community tool

Health EquityEquityData VisualizationData Analysis

Let's connect

Reach out — I'd love to hear from you.