AI grant matching with self-healing scrapers.
OpenFunds crawls foundations, research offices, conference CFPs, and residencies — then ranks every deadline against your profile. When page layouts drift, the pipeline detects broken selectors and can heal them automatically via Bright Data.
Built for WeMakeDevs · Into the Scrape-Verse (August 2026).
Live demo: openfunds.ronakpaul.com
- Multi-source scraping — scheduled crawls of grant and opportunity listings
- Drift detection & self-heal — detects missing fields / empty results and repairs selectors via Bright Data (collector ID stays stable)
- AI profile matching — ranks grants against your research profile (Pinecone + OpenRouter, with local fallbacks)
- Live scraper health — real-time run logs over SSE on the Scraper Health dashboard
- Knowledge base — inspect scraped knowledge and source status
- Deadlines feed — upcoming opportunities in one place
- Heal demo target —
target/ships Meridian Foundation, a controllable fake funder so you can break and heal layouts on purpose - Graceful fallbacks — runs in local-fallback mode when Bright Data, Pinecone, or OpenRouter are unset
flowchart LR
Client["client Vite React"] -->|"/api proxy"| Server["server Express"]
Target["target Meridian Foundation"] -.->|"scrape / heal demo"| Server
Server --> MongoDB
Server --> BrightData
Server --> Pinecone
Server --> OpenRouter
| Package | Role |
|---|---|
client/ |
React dashboard + marketing site (Vite) |
server/ |
Express API, scraping pipeline, integrations |
target/ |
Meridian Foundation — demo site with flipable markers for self-heal demos |
More detail: client/README.md · server/README.md
Client — React 19, TypeScript, Vite 8, Tailwind CSS 4, TanStack Query, React Router, Framer Motion, Three.js
Server — Express, TypeScript, MongoDB / Mongoose, Cheerio, node-cron, Zod
Target — React 19, Vite, Tailwind (standalone Meridian Foundation site)
Integrations — Bright Data (Scraper Studio), Pinecone (vectors), OpenRouter (LLM)
- Node.js 20+
- MongoDB locally, or an Atlas connection string
- Optional: Bright Data, Pinecone, and OpenRouter API keys (the app works without them in fallback mode)
Clone the repo, then start the API and the client in two terminals.
cd server
cp .env.example .env
# edit MONGODB_URI if needed
npm install
npm run seed # requires a running MongoDB
npm run devWithout local MongoDB you can still smoke-test the API:
cd server && npm run smokecd client
cp .env.example .env # optional — defaults work for local dev
npm install
npm run devIn development the client calls relative /api paths. Vite proxies them to VITE_API_PROXY (http://localhost:4000 by default), so no CORS setup is needed for local work.
For self-heal demos, run Meridian Foundation and point a source at it:
cd target
npm install
npm run devServer (server/.env.example)
| Variable | Required | Notes |
|---|---|---|
MONGODB_URI |
Yes | e.g. mongodb://127.0.0.1:27017/openfunds |
PORT |
No | Default 4000 |
CLIENT_ORIGIN |
No | Default http://localhost:5173 |
BRIGHTDATA_API_TOKEN |
No | Leave blank for local-fallback scraping |
BRIGHTDATA_UNLOCKER_ZONE |
No | Mid-tier unlocker zone name |
PINECONE_API_KEY |
No | Vector matching; falls back locally if unset |
PINECONE_INDEX |
No | Default openfunds-grants |
OPENROUTER_API_KEY |
No | LLM matching / agent features |
SCRAPE_ENABLED |
No | Default true |
SCRAPE_CRON |
No | Default */15 * * * * |
SCRAPE_MAX_ROWS |
No | Cap rows per scrape; default 12 |
Client (client/.env.example)
| Variable | Required | Notes |
|---|---|---|
VITE_API_PROXY |
No | Dev proxy target; default http://localhost:4000 |
VITE_API_URL |
No | Set to the deployed API origin for production builds (no trailing slash) |
| Script | Description |
|---|---|
npm run dev |
Dev server with hot reload (tsx watch) |
npm run build |
Compile TypeScript to dist/ |
npm start |
Run the compiled server |
npm run seed |
Seed MongoDB with sample data |
npm run smoke |
In-memory API smoke suite (no local MongoDB required) |
npm run typecheck |
Type-check without emitting |
| Script | Description |
|---|---|
npm run dev |
Vite dev server with /api proxy |
npm run build |
Type-check + production build |
npm run lint |
ESLint |
npm run preview |
Serve the production build |
| Script | Description |
|---|---|
npm run dev |
Vite dev server for Meridian Foundation |
npm run build |
Production build |
npm run preview |
Serve the production build |
.
├── client/ # Vite + React frontend
│ └── src/
│ ├── components/ # UI, dashboard, marketing, 3D
│ ├── lib/ # api, queries, types, SSE helpers
│ └── pages/ # Home + dashboard screens
├── server/ # Express + TypeScript API
│ └── src/
│ ├── integrations/ # Bright Data, Pinecone, OpenRouter
│ ├── jobs/ # Cron scraper scheduler
│ ├── models/ # Mongoose models
│ └── modules/ # agent, analytics, grants, knowledge,
│ # matching, profile, runs, scraping,
│ # settings, sources
└── target/ # Meridian Foundation (heal demo site)
└── src/
├── components/
├── data/ # opportunities + layout markers
└── pages/ # listing + detail
| Route | Screen |
|---|---|
/dashboard |
Overview |
/dashboard/onboarding |
Profile onboarding |
/dashboard/deadlines |
Deadlines feed |
/dashboard/profile |
Matched profile |
/dashboard/scraper-health |
Scraper health + live runs |
/dashboard/knowledge |
Knowledge base |
/dashboard/digest |
Digest settings |
/dashboard/settings |
Integrations & settings |
/dashboard/help |
Help |
See CONTRIBUTING.md for setup expectations, branch naming, and PR checks.
See CHANGELOG.md.
Parts of the UI and application logic were shaped with help from coding agents and AI brainstorming sessions.
MIT © 2026 Ronak Pal
