Skip to content
ZwandrejPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GrantDash (local grants dashboard)

Local, self-hosted dashboard to search funding calls (Austria/EU mix) from configurable sources.

Documentation (handover)

Start here:

  • docs/HANDOVER.md

More:

  • docs/ARCHITECTURE.md
  • docs/SOURCES.md
  • docs/OPERATIONS.md
  • docs/AI_MATCHING.md

Quickstart

  1. Start the server:
    • python3 /Users/ajz/Desktop/notes/Work/Coxed/app.py serve
  2. Open the UI:
  3. Pull data (optional; can take a bit):
    • python3 /Users/ajz/Desktop/notes/Work/Coxed/app.py refresh --source ffg
    • python3 /Users/ajz/Desktop/notes/Work/Coxed/app.py refresh --source eu

AI matching (cloud first)

The dashboard can rank calls against pasted CV text using OpenAI embeddings (and optionally generate short match explanations).

Setup:

  • Set an API key in your shell (server-side only):
    • export OPENAI_API_KEY="..." (or GRANTDASH_OPENAI_API_KEY)

Models:

  • Embeddings: text-embedding-3-small via POST /v1/embeddings.
  • Explanations: gpt-4.1-mini via POST /v1/responses (configurable).

Notes:

  • Your CV text is only sent when you click Find matches.
  • Don’t put the API key in any browser code; it must stay in environment variables on the server.

AI matching (Ollama local)

You can run matching fully locally with Ollama:

  1. Install and start Ollama (it runs a local HTTP server on http://localhost:11434).
  2. Pull models you want to use, e.g.:
    • ollama pull embeddinggemma (embeddings)
    • ollama pull gemma3 (optional explanations)
  3. Start GrantDash with Ollama selected:
    • export GRANTDASH_AI_PROVIDER=ollama
    • python3 app.py serve

Environment variables:

  • GRANTDASH_AI_PROVIDER=ollama|openai (auto-selects if unset)
  • GRANTDASH_OLLAMA_HOST (default http://localhost:11434)
  • GRANTDASH_OLLAMA_EMBED_MODEL (default embeddinggemma)
  • GRANTDASH_OLLAMA_CHAT_MODEL (default gemma3)

Ollama endpoints used:

  • POST /api/embed for embeddings
  • POST /api/chat for optional explanations

Limits / “why do I only see N results?”

There are two separate limits:

  1. How much you ingest (refresh): refresh pulls a finite number of pages per source (default --max-pages 3).
    • Increase it to ingest more: python3 app.py refresh --source eu --max-pages 20
  2. How much the UI shows per request: the UI paginates results (25/50/100 per page). Use Load more to page through.

Cache update strategy (recommended)

The safe way to avoid missing open/upcoming calls for scraped sources is:

  • Fetch “open + forthcoming” (not just open), and
  • Refresh frequently (daily/weekly depending on how often the source changes), and
  • Use --max-pages 0 occasionally as a backfill to make sure you’re not capped by paging.

Suggested cadence:

  • EU (search backend): daily if you cache; otherwise live query + optional small cache for resilience.
  • FFG (HTML listings): daily/2–3x per week.
  • Other funders without APIs (HTML/PDF pages): daily/weekly depending on volume.

Backfill example (scan until exhausted):

  • python3 app.py refresh --source eu --max-pages 0
  • python3 app.py refresh --source ffg --max-pages 0

This project also tracks first_seen_at / last_seen_at per call in the DB so you can audit freshness.

Sources status

Implemented:

  • eu (EU Funding & Tenders portal-backed search)
  • ffg (FFG HTML listing scrape)
  • fwf (FWF portfolio program pages scrape; open submissions only)
  • vw (VolkswagenStiftung HTML listing scrape)
  • thyssen (Fritz Thyssen Stiftung “Nächste Fristen” scrape; lightweight)

UI placeholders (checkboxes exist, fetchers not implemented yet): (none)

Configuration

Environment variables:

  • GRANTDASH_DB_PATH (default: ./data/grants.db)
  • GRANTDASH_PORT (default: 8765)
  • GRANTDASH_EU_API_KEY (default: SEDIA)

Notes:

  • The EU source uses the same api.tech.ec.europa.eu/search-api endpoint that powers the Funding & Tenders Portal search (multipart/form-data). It is not an officially documented public API and may change.
  • FFG currently does not advertise a public API for open calls; this project parses the public HTML pages.

Contributing / maintenance checklist

For student assistants and future maintainers.

Daily workflow

  • Create a feature branch: git checkout -b <topic>
  • Make changes, keep them small and source-scoped.
  • Quick sanity checks:
    • PYTHONPYCACHEPREFIX=/private/tmp/grantdash-pycache python3 -m py_compile app.py grantdash/server.py
    • Start server: python3 app.py serve and smoke test:
      • Update database (1–2 sources)
      • Search (keyword + filter)
      • Find matches (if AI is configured)
  • Commit + push:
    • git add -A && git commit -m "<message>" && git push

Adding a new source safely

  1. Implement in grantdash/sources/<source>.py with a fetch_<source>_calls(...) function.
  2. Wire into grantdash/refresh.py (_fetch_source_calls).
  3. Add UI checkbox in static/index.html + static/app.js.
  4. Document it in docs/SOURCES.md.
  5. Run a refresh for that one source and verify:
    • non-zero results
    • stable IDs (<source>:<url-or-key>)
    • deadlines/status parse as expected

Release / handover

  • Update user-facing copy in static/index.html if UX changes.
  • Update docs when behavior changes:
    • docs/HANDOVER.md for workflows
    • docs/SOURCES.md for ingest changes/known limitations
    • docs/AI_MATCHING.md for provider/model config

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages