A kiosk display for BirdNET-Go. Shows live bird detections, species spotlights, rare visitors, daily top birds, and local weather on a rotating full-screen hero panel. Designed for a wall-mounted screen/iPad to show your live detections and statistics in a beautiful way, without any interaction necessary.
This may just be so you can have a nice display at home for your family. But works particularly well in public places. Maybe you want to promote awareness of birds to those in the area and you could even place a screen in your front window to show the neighbours the wildlife they are living with!
Note: Beakwatch is built as a fixed-layout for large screens (≥1280px wide) and iPads in landscape. It does not have a responsive mobile layout.
- Live detections sidebar — newest detection per species, deduplicated.
- Rotating hero — last identified, species spotlight, top 10 over 30 days, 6 rarest visitors, today's species hourly chart.
- On-demand bird images — fetched from Wikipedia the first time a species appears, then cached on disk forever. The repo ships zero images.
- Local weather — current conditions from Open-Meteo (no API key).
- Multi-server support — point at one or several BirdNET-Go instances and switch between them from the UI.
- Node.js 20+ (uses global
fetch). - A reachable BirdNET-Go instance with the v2 HTTP API enabled.
1. Clone and install
git clone https://github.com/beaktech/beakwatch
cd beakwatch
npm install2. Create your config
Copy the example file to server/.env (note the server/ subfolder — that's where the app reads it from):
cp .env.example server/.envOpen server/.env in an editor and set at least BIRDNET_GO_URL to your BirdNET-Go instance, including the http:// prefix and port:
BIRDNET_GO_URL=http://192.168.1.10:8080Everything else is optional — see Configuration below. (Running more than one BirdNET-Go? Use BIRDNET_GO_URLS instead.)
3. Build and run
npm run build # compile the frontend into dist/
npm start # serve the app + APIThen open http://localhost:2325 in a browser.
Just want to develop/tweak the UI? Skip the build and run
npm run devinstead — see Development.
All config lives in server/.env (see .env.example).
| Variable | Default | Description |
|---|---|---|
BIRDNET_GO_URL |
(unset) | URL of your BirdNET-Go instance, e.g. http://192.168.1.10:8080. Required. |
BIRDNET_GO_URLS |
(unset) | Comma-separated URLs for multiple instances. Overrides BIRDNET_GO_URL. |
BIRDNET_GO_NAMES |
hostname | Comma-separated display names matching BIRDNET_GO_URLS (e.g. Garden,Office). |
LAT |
51.5074 |
Latitude for the weather widget. |
LON |
-0.1278 |
Longitude for the weather widget. |
PORT |
2325 |
Port the kiosk server listens on. Dev mode proxies to this too. |
Browser ──/api/*─▶ Express (server/index.js) ──▶ BirdNET-Go (REST)
│
├──/birds/*─▶ cache/birds/ (disk)
│ │ miss
│ ▼
│ Wikipedia REST API
│
└──static────▶ dist/ (built React app)
- Express (
server/): proxies BirdNET-Go, serves the built frontend, and runs the on-demand image cache. - React + Vite (
src/): the kiosk UI. Tailwind for styling, Vitest for tests. - Image cache (
server/birdImages.js): on a request for/birds/<slug>.jpg?name=<commonName>&w=<width>, serves fromcache/birds/<slug>-<width>.jpgif present; otherwise hits Wikipedia for the species summary, downloads the sized thumbnail, writes it to disk, and serves it. Concurrent requests for the same image are deduped; outbound traffic is capped at 2 concurrent requests with backoff on HTTP 429.
The cache/ directory is gitignored and grows organically as new species are detected (~50–200 KB per species).
npm install
cp .env.example server/.env
npm run dev # vite (5173, or next free port) + nodemon-watched express (2325)Vite proxies /api and /birds/*.jpg to Express, so you don't need a separate build. Open the URL Vite prints on startup (usually http://localhost:5173).
| Command | What it does |
|---|---|
npm run dev |
Vite + Express in watch mode |
npm run build |
Build the React app to dist/ |
npm start |
Serve dist/ and the API from Express |
npm test |
Run the Vitest suite once |
npm run test:watch |
Vitest in watch mode |
Beakwatch is designed for a trusted LAN and has no authentication. Specifically:
- The
/api/serverPOST route lets any client on the network switch the active BirdNET-Go instance. - The
/birds/*.jpgroute lets any client trigger Wikipedia downloads and disk writes tocache/, and the?name=parameter controls which Wikipedia page an image is cached from — so a client could fill the disk or poison cached images.
If you expose Beakwatch beyond a network you trust, put it behind a reverse proxy with auth, or gate these routes yourself.
Issues and PRs are welcome. Before opening a PR, run npm run lint && npm test — CI runs both plus a build.
Bird photos and summaries come from Wikipedia and Wikimedia Commons. Each photo is displayed with its photographer credit and licence (src/components/Attribution.jsx). Keep this attribution visible — it is the licence requirement for reusing those images.
Weather data from Open-Meteo under their terms of use.
MIT — see LICENSE.




