Finds and verifies supporting resources for your teaching.
Give Bowerbird a topic, a document, a worksheet, or any piece of teaching content, and it returns supporting resources: videos, websites, podcasts, research papers, white papers and consultant reports. Every returned resource is verified to exist and presented with enough context for a human to judge it quickly.
Try the hosted version · Download the desktop app · Self-host with Docker
Perplexity, NotebookLM, Elicit and Consensus already do topic-to-sources retrieval. Bowerbird's wedge is not retrieval — it is what happens after retrieval:
| Bowerbird | General topic-to-source tools | |
|---|---|---|
| Verification | Every link resolved, every DOI validated against Crossref / Semantic Scholar / OpenAlex. Retrieval-grounded only — no generated references, ever. | Citations may be generated or unchecked; hallucinated references are a known failure mode. |
| Institutional plumbing | Licensing status (OER, Creative Commons, library-subscription, link-only), library permalinks, accessibility notes (captions, transcripts, tagged PDFs), LMS-ready export. | Links only; the lecturer does the licensing and accessibility legwork. |
| Pedagogical framing | A rationale per suggestion (why this one, what it adds, what it doesn't cover), source-type labels (peer-reviewed / practitioner / vendor / journalism / government), a commercially-interested flag on consultant material, and (v2) a counterpoint mode that deliberately surfaces disagreeing material. | Relevance-ranked lists with no teaching rationale. |
| Deliberate diversity | Balances format and voice by default — one video, one paper, one practitioner piece, an explicit pass for non-Anglo sources — so the retrieval layer's biases don't become the reading list's biases. | Whatever ranks highest, which is often five similar blog posts. |
| Deployment freedom | Hosted, self-hosted Docker, desktop app, CLI, npm library. Local LLM via Ollama — your content never has to leave your machine. | Hosted SaaS only. |
The framing is conversation, not delegation: Bowerbird gives you the evidence and context to exercise your own judgement quickly, rather than handing you an answer to paste.
| You are | Use | Get it |
|---|---|---|
| A colleague or student | Hosted web UI | app.bowerbird.eduserver.au |
| A power user | Desktop app | Latest release |
| Self-hosting | Docker | See below |
| Scripting / batch | CLI | npm install -g @michaelborck/bowerbird-cli |
| Building on it | Library | npm install @michaelborck/bowerbird-core |
| Free hosted | Self-host / Desktop | |
|---|---|---|
| Input | One topic or document | Batch: a semester of topics at once |
| Sources | Papers, podcasts, books, web | All of those plus video search, with your own YouTube key |
| Thumbnails | oEmbed and og:image | Full screenshots |
| Verification | Yes | Yes |
| LLM | Quota'd, or bring your own key | Local Ollama, or your own key |
| Export | Markdown | Markdown, LMS HTML, reading list, citations |
Video search is a bring-your-own-key feature by design: a shared YouTube API key on a free public instance would exhaust its quota (and invite abuse) within hours, so the hosted tier ships without one.
The self-host deployment is the same web UI, bundled into a single Docker
image with the server. No source checkout needed — the server only needs the
compose file and a .env:
mkdir -p /opt/bowerbird && cd /opt/bowerbird
curl -fsSLO https://raw.githubusercontent.com/michael-borck/bowerbird/main/docker-compose.yml
curl -fsSL -o .env https://raw.githubusercontent.com/michael-borck/bowerbird/main/.env.example
chmod 600 .env # then edit: OLLAMA_URL, OLLAMA_API_KEY
docker compose up -d
# open http://localhost:3000Updating is docker compose pull && docker compose up -d. To try it without
the queue, run the image directly:
docker run -p 3000:3000 ghcr.io/michael-borck/bowerbird:latestTo build the image from source instead of pulling from GHCR:
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --buildConfiguration lives in a .env file next to docker-compose.yml — copy
.env.example and fill it in (OLLAMA_URL, and
OLLAMA_API_KEY if your Ollama sits behind an authenticating proxy).
Alternatively, bring your own API key under Settings → AI provider.
Two optional retrieval sources are off until configured: set
YOUTUBE_API_KEY for video results, and enable general-web results with
the bundled SearXNG metasearch service:
curl -fsSL --create-dirs -o deploy/searxng/settings.yml \
https://raw.githubusercontent.com/michael-borck/bowerbird/main/deploy/searxng/settings.yml
# in .env: SEARXNG_URL=http://searxng:8080 and SEARXNG_SECRET=$(openssl rand -hex 32)
docker compose --profile websearch up -d
``` BYO keys are held in browser
storage and passed per request only — they are **never persisted server-side**
([ADR-0004](docs/adr/0004-byok-keys-never-persisted-server-side.md)).
## Architecture
TypeScript monorepo. The core is a library with no UI assumptions; the server
exposes it over JSON; web and desktop are both clients of that same contract.
bowerbird/ ├── packages/ │ ├── core/ shared logic: retrieval, verification, ranking, rationale │ ├── cli/ Commander.js CLI │ ├── server/ Express + BullMQ queue │ ├── web/ React + Vite (also the PWA) │ └── desktop/ Electron shell wrapping the web UI (ADR-0010) ├── Dockerfile ├── docker-compose.yml └── package.json workspace root
Verification extends [`@michaelborck/cite-sight-core`](https://www.npmjs.com/package/@michaelborck/cite-sight-core)
rather than duplicating it, so both tools improve at once.
A core principle throughout: **degradation is non-fatal**. If verification,
thumbnail generation or the LLM is unavailable, Bowerbird still returns
results with the affected fields clearly flagged — it never fails a whole
request because one enrichment step failed.
## Documentation
- [Project specification](docs/spec.md)
- [Architecture Decision Records](docs/adr/)
- [Contributing guide](CONTRIBUTING.md)
- [Security policy](SECURITY.md)
## Development
```bash
npm install
npm run build
npm test
Requires Node 20+.
MIT © Michael Borck