About
Funding Monitor tracks EU / EU-entity-eligible funding opportunities (national portals, EU-wide calls, cascade/FSTP calls, PRIMA, Interreg), extracts structured details with AI, and ranks them against your organizations' profiles and preferences. No US federal/state/foundation grants are in scope.
Version: 0.5
Roadmap
Last updated: 27/07/2026
future (planned)
- The items below were originally sketched as two separate near-term milestones ("0.4" and "1.0 — commercial platform") before 0.5's infrastructure work shipped ahead of them. Folded into one backlog now that there's no fixed next version number attached — these are the acknowledged next priorities, not dated commitments.
- GOAL (commercial platform): turn this from a single-tenant tool into a real multi-tenant product — sized against ~200 CONCURRENT users. This is a foundational rearchitecture (auth + tenancy touch nearly every route), not an incremental feature. Nothing in this section is built yet.
- Authentication: real login (currently none — the live site has no auth wall at all, anyone who finds the URL can reach every page and every action)
- A role-BUILDER, not just fixed tiers: Platform Admins define roles by ticking which specific tools/features that role can access (checkboxes against real permissions — "manage sources," "override matches," "manage billing," "invite users," "access AI provider settings," "run bulk actions," etc.), rather than being stuck with a hardcoded 3-tier list. Ships with a couple of sensible default role templates (Platform Admin / Organization Admin / Organization User) so most organizations never need to touch the builder, but anyone with unusual needs (e.g. a read-only auditor role) isn't stuck
- Consultancy model: a single account that manages MULTIPLE organizations (e.g. a consultancy handling several client profiles) — needs a many-to-many user↔organization relationship, not the current implicit "whoever's running the app owns every profile" model, plus a way to switch/scope which organization's data is in view
- Data model changes this implies: a User table, a Role/Permission table (see role builder above), an organization-membership table (many-to-many), and every existing query (Opportunities, Matches, Sources, Overrides) scoped by the requesting user's accessible organization(s) and permissions instead of returning everything unconditionally
- Admin-configurable settings instead of hardcoded constants — starting with the matching-weight blend (AI_SCORE_WEIGHT/TAG_OVERLAP_WEIGHT in matching/engine.py, currently 65/35 fixed in code) and extending to things like candidates-per-check defaults, taxonomy edits, and which sources are shared vs. per-tenant
- Commercial-readiness: billing/subscription handling, usage limits per plan, and deciding what's shared infrastructure (sources, the taxonomy, AI provider config) vs. what's genuinely per-tenant (organization profiles, matches, overrides, workflow state)
- IMPORTANT sizing point: AI compute does NOT scale with USER count — Opportunity rows are already global/shared (extracted once, used by every tenant) and Match rows are keyed per (opportunity, organization profile), not per user. 200 concurrent users spread across a modest number of organizations is a far smaller AI workload than 200 separate organizations would be — cost/throughput planning should size against expected ORGANIZATION count, not user count
- A real cloud AI provider (Claude/OpenAI) as a proper fallback, not just a nice-to-have — the live site currently depends on the office's own Ollama being reachable over the internet (static IP + port-forward + firewall rule), which is a genuinely fragile chain (office internet, power, or IP changes would silently break AI extraction on the live site)
- Monitoring/alerting stack — nothing beyond manual server-admin-GUI checks exists yet; no automated uptime/error alerting
- Finish the off-VPS backup story — the server-side pull mechanism (restricted, chrooted, read-only SSH account) is ready, but the actual scheduled pull job on the user's own backup device still needs configuring on that device
- Security hardening beyond the deployment basics already in place: rate limiting on login and on AI-triggered/expensive endpoints (stops one runaway client or bug from generating a large, unexpected AI bill), an audit log for role/permission/billing changes and match overrides, and per-organization AI usage/cost tracking (useful for spotting anomalies early and for usage-based pricing later)
- A staging environment to rehearse risky changes (schema migrations, auth rollout) somewhere reversible before they touch the live database
- Partner recommendations from an Odoo contact export (companies + tags) matched against each call's domain/technology tags — needs a decision on live sync vs. CSV export and a tag-mapping scheme between Odoo's tags and this app's taxonomy
- Document/template link extraction for non-eu_portal (HTML/RSS) sources — currently eu_portal-only, since only its conditions text is parsed with links preserved
- Per-source candidate-link tuning for PRIMA/Interreg (news-heavy sites without a clean listing→detail-page structure produce a lot of AI calls on non-call pages)
- Scheduled unattended periodic source checks
- Claude/OpenAI providers exercised end-to-end alongside Ollama
- Cross-source duplicate detection (the same call sometimes appears on more than one portal)
- Email/notification alerts on new high-match opportunities
- Proposal-drafting assist
- Calendar view of upcoming deadlines
Agreed execution order — what we do first
Phase 1 — Auth & multi-tenancy (the big rearchitecture; build on the already-live 0.5 infrastructure, not on SQLite)
- User model + real login (bcrypt/argon2 password hashing, sessions)
- Role/Permission model + role-builder admin tool — ships with default templates, supports custom roles
- Org-membership table (many-to-many — supports both single-org users and a consultancy account managing multiple client organizations)
- Scope every existing query (Opportunities, Matches, Sources, Overrides) by the requesting user's accessible organization(s) and permissions
Phase 2 — Commercial mechanics
- Billing/subscriptions (Stripe or similar), usage limits per plan
- Admin-configurable settings (matching weights, taxonomy edits) instead of hardcoded constants
- ToS/privacy policy/GDPR compliance (this handles EU business data)
- Self-serve organization onboarding flow
Phase 3 — Scale validation & launch prep
- Load-test at ~200 concurrent users
- AI-cost strategy decision: office Ollama vs. a real cloud fallback — remember AI compute scales with ORGANIZATION count, not user count
- Security review before opening to real customers
- Pricing model decision (per-org / per-user / per-match)
First concrete step: Design the User/Role/Permission/org-membership data model and the role-builder UI before writing any auth code — this is the actual starting point now that Phase 0's infrastructure (containers, Postgres, the priority queue, live TLS) already shipped in 0.5.
v0.5 (current)
- Moved from a local-only tool to a live, containerized deployment: https://funding.ecect.eu — real HTTPS (Let's Encrypt), deployed onto shared self-hosted infrastructure (Docker + Nginx Proxy Manager) alongside another project, reusing its existing reverse-proxy/TLS tooling rather than building a new stack
- Database moved from SQLite to PostgreSQL — all real production data (opportunities, matches, sources, organization profiles, overrides, settings) migrated and verified row-for-row; local SQLite + the original in-process threading remain fully supported for local development, unaffected
- Background jobs moved to a real priority queue (Redis + RQ) in the deployed environment: three queues ("high"/"default"/"low"), always drained in that order — one-off user-triggered actions (add-by-URL, PIF upload, recompute matches, test source) get priority over routine bulk work (the full EU-portal sync, the multi-model benchmark sweep). Replaces the old "any job blocks any other job equally" behavior
- Automated nightly database backups with an actually-tested restore (not just an assumption it would work) — plus a dedicated, tightly restricted pull mechanism (chrooted, read-only, key-auth-only SSH account) so backups can be pulled off the server on a real schedule
- The office's local Ollama instance is now securely reachable by the live deployment (scoped firewall rule + router forwarding), so AI extraction works on the hosted site using existing local hardware rather than requiring a cloud AI subscription on day one
- Two real cross-database bugs found and fixed during the move to PostgreSQL: a SQLite-only performance tweak (`PRAGMA journal_mode=WAL`) that was firing on every database connection regardless of which database was in use, and a startup race between the web process and the background-job worker both trying to set up the database schema at once
v0.3 (shipped)
- EU Funding & Tenders Portal: fixed a pagination bug that silently capped discovery at 500 of ~750+ live calls (missing exactly the near-term-deadline ones); results now sort soonest-deadline-first instead of newest-start-date-first
- EU portal opportunities now carry real structured fields straight from the portal's own API (not AI-guessed): Programme, Call identifier, Type of action, Deadline model, Planned opening date, Model Grant Agreement type, and Submission status (Open/Forthcoming) — plus a "Load more details" button to backfill older rows
- Fixed a bug where a candidate's identifier was re-derived from its URL instead of carried from discovery, which silently failed on ~78% of EU-portal candidates in one observed run; also fixed the source's "last checked" timestamp permanently showing "never" whenever any candidate in a run failed
- Deadline-range filter, results-per-page control (100/250/500/1000), and a configurable per-source "candidates processed per Check now run" cap (was a fixed 60) so a full catch-up run can process everything in one go
- Domain (~30 EU-portal topic categories) and Technology (Cascade Funding Hub's own taxonomy) tagging — AI-classified on every opportunity, human-picked (colour-coded chip picker) on organization profiles — plus a Field-of-expertise picker for profiles. Both feed into filtering and into the AI match-scoring prompt
- Matching-prompt rewrite so domain/technology tag overlap (including a profile's more specific tag matching an opportunity's broader one) is explicitly weighed in the score and named in the rationale
- Fixed two real hard-filter bugs found via user-made overrides: eligibility phrased as plain "EU countries" (not spelled out as "European Union"/"member state") and "EU entities" (a blanket org-type allowance, not a specific type) were both silently excluding genuinely-eligible organizations — affected 74 of 720 existing match rows
- Human-in-the-loop match override: correct any match's score by hand with a reason, without ever losing the system's own original score/rationale; a dedicated /overrides/ page reviews every correction across the whole app and flags rule-filter corrections specifically as likely code bugs; AI-scored matches also feed a profile's past corrections back into future scoring prompts as calibration
- Star/favorite flag, a "Starred only" filter and "Starred first" sort
- Workflow tracking per opportunity — New → Viewed (automatic) → In progress → Decided (manual) — with a filter row and a quick "In progress" link
- Best Match column/sort: defaults to best-match-first (was deadline-first), and now shows every organization's score, not just the top one
- Document/template links (application form, evaluation form, MGA, guidance annexes) extracted from the EU portal's own conditions text and shown on the opportunity detail page — not yet available for non-eu_portal sources (see 0.4)
- Light/dark theme toggle, defaulting to light regardless of OS preference (previously dark-preference systems had no way to switch within the app)
- Add an organization profile from an uploaded Partner Identification Form (PDF or Word) as an alternative to crawling a website — same AI drafting and human-in-the-loop review as a URL crawl, including auto-tagged domains/technologies/expertise. The full extracted document text is kept permanently on the profile as a reference, viewable on the review screen
- Update an EXISTING profile from a newly-uploaded PIF (not just create a new one) — re-drafts every field in place and always drops back to "pending review" so the redraft gets a fresh look before it's trusted for matching again
- "Add organization" consolidated to one entry point with a website/PIF toggle, instead of three separate buttons/pages
- Richer AI extraction: description and past-experience prompts now ask for real detail (one paragraph per named project, not one compressed sentence) instead of a generic summary, since domain/technology auto-tagging is grounded in exactly this text
- Weighted matching: AI-scored matches now blend the AI's semantic judgment with a deterministic domain/technology tag-overlap score (65% AI / 35% tag overlap by default), with the breakdown shown in the rationale — the "yes/no eligibility gate, then a weighted score" structure made explicit and transparent instead of one opaque AI number
- Review-profile page redesign: grouped into Identity / Description & experience / Domains-technologies-expertise sections, 2-column layout for compact fields, and a live "selected tags" summary bar above each picker (with one-click removal) so you don't have to hunt through ~30 collapsed domain categories to see or edit what's already chosen
v0.2 (shipped)
- Deadline-urgency status — Expired / Act now (≤30d) / Prepare now (30-90d) / Future (90d+), computed live against today's date, plus a manual Archive override
- Opportunities list: checkbox filters for Status, Matching level (0-20/20-50/50-70/70-100%/not-yet-scored) and Source, a free-text Search box, and Sort (deadline/match%/budget/newest)
- RSS/Atom feed support for sources, as an alternative to HTML-listing crawling — more reliable candidate discovery on sites that offer a feed
- "Test source" dry run: verifies a source is configured correctly (finds candidates, confirms a sample look like real calls) before committing to a full, possibly multi-minute "Check now"
- LAN access — reachable from other devices on the network, not just this machine
- Matching-engine fix: eligibility checks now understand synonyms (non-profit/NGO, SME, EU member states, etc.) instead of requiring literal text matches — a profile could previously score 0% on everything if its org type/country was phrased differently than the source text
v0.1 (shipped)
- Manual "Check now" ingestion from monitored sources, with a live progress bar
- Five seeded sources: Cyprus Funding Programmes Portal, EU Funding & Tenders, Cascade Funding Hub, PRIMA, Interreg Euro-MED
- Ollama (local) AI provider, with Claude/OpenAI available in Settings
- Human-in-the-loop organization profile creation from a multi-page crawl (homepage + About/Team/Projects-style pages) synthesized into an AI research brief before structured extraction
- Hard-filter (eligibility, budget, call type, duration, intensity) + AI Matching% scoring
- Manual add-opportunity-by-URL
- Background jobs for every crawl/extraction step, so the UI never blocks