Roadmap
What's been released and what's coming next.
Released
v0.13 — Mobile & On-Device
- Mobile always-on background mode: foreground service, wake lock, WiFi lock, AlarmManager keepalive
- Custom native RecordingService with persistent notification (bird icon, recording stats, pause state)
- Battery optimization exemption prompt on startup
- Fresh MQTT connection on foreground return (handles Android WebSocket suspension)
- Remote satellite log retrieval via MQTT (hub requests, satellite responds with logs)
- Get Logs button on satellite detail page (Pi: journalctl, mobile: in-app logs)
- Mobile app OTA updates: self-hosted APK distribution via hub API
- In-app update banner with download prompt (version check on startup)
- Platform admin: upload APK, manage releases, force update toggle
- Build script auto-upload with API key auth
- Nginx 200MB upload limit for APK files
- Detections overview: species grouped by count with time range tabs (today/week/month/year), server-side sorting
- Species profile revamp: hero image + stats layout, full paginated detection list with filters/sort
- First-of-day/season changed from per-satellite to per-tenant
- Remote satellite log retrieval via MQTT (Get Logs button)
- ConfidenceRing shared component (used on detections overview and analytics)
- Lightbox click no longer triggers parent navigation
v0.16 — Multi-Model BirdNET + Period Picker
- Multi-model BirdNET registry:
birdnet_modelstable, per-detectionmodel_idforeign key, bundled birdnetlib model marked default at install - Catalog of historical models installable from the BirdNET-Analyzer GitHub repo with one click (v2.4 / v2.3 / v2.2 / v2.1)
- Custom model upload (TFLite + labels) stored in MinIO; inference worker resolves the active default within ~60 s of an admin change
- Inference compare mode (A/B): worker runs every enabled non-default model on a configurable sample of chunks, writing to a separate
shadow_detectionstable so user-facing stats stay clean - Model Compare admin page: per-model summary, agreement vs default (compared / agree / default-only / shadow-only / agreement rate), top species the shadow models found that the default missed
- Hard capacity cap for audio retention: third pass that purges keep-best/pinned chunks (oldest first) when usage exceeds the hard cap; bar shows soft + hard markers
- Custom calendar picker for day/week/month/year period navigation across Compare and Timeline; respects the user's "start of week" preference end-to-end (calendar grid, period boundary, hub query)
- Compare page (location comparison) accepts
period=day|week|month|year+offsetinstead of just rollingdays - Platform Settings: styled checkboxes + file inputs globally; Models card with active-model banner and styled file picker
- Migrations 042 (birdnet_models + detections.model_id), 043 (label bundled model with version), 044 (audio_storage_hard_cap_gb), 045 (inference_mode + shadow_detections)
v0.15 — Unified Alerts + Timeline Navigation
- Unified alerts pipeline:
AlertRulesEngineis the sole dispatcher; system rules auto-seeded per tenant (rare_species, first_of_day, first_of_season, satellite_offline) are editable but not deletable - Webhooks merged into
alert_channelsas a channel type; existing webhooks auto-migrated and auto-attached to the system rules matching their event_types - Three fire modes on rules:
cooldown(time-based),once_until_clear(requires acknowledgement),on_state_change(auto-resets when condition clears — used by satellite_offline: alert fires only on transition offline, suppressed while still offline, ready to fire again when the satellite comes back and goes offline next) - Cooldown scope: global / per_species / per_satellite — replaces the old coarse global cooldown
- Message template on rules + payload template on every channel type (email HTML, Slack Block Kit JSON, Telegram HTML, Google Chat cardsV2 JSON, Discord embed JSON, webhook free-form)
- Per-channel-type format toggles: include_image, include_link, use_blocks, use_card, image_in_header, use_embed, embed_color, use_html
- "Load default as starting point" button: dumps the hub's built-in template reflecting the current toggle state into the textarea
- Shared variable namespace across rule + channel templates (27 placeholders: rule/species/satellite/tenant/links to wikipedia/ebird/xeno-canto, etc.)
- Inbox tab in the Alerts page with unread filter, type filter, mark-all-read
- Sidebar "Alerts" link gains an unread-count badge
- Dashboard banner narrowed to warning/critical severity (info-level system alerts live in the inbox)
- eBird-based rarity: species not on the eBird "recently observed near here" list flagged as
is_rarewith reason "unexpected in this region" - Species Timeline: period navigation (prev / now / next) shifts by day/week/month/year, human-readable period label,
Nowreset button - Timeline satellite filter + per-bucket RMS silence detection (bucket painted dark purple when no chunks arrived OR mean RMS below threshold) — surfaces "satellite was running but mic was off" gaps
- Backfill script for
audio_chunks.rms(historical data)
v0.14 — Data Management
- Adjacent clip stitching: consecutive same-species detections merged into single detection with concatenated audio (6s window, max 30s, on-the-fly WAV concatenation)
- Duration badge on stitched detections, stitched audio playback via SpectrogramPlayer
- Audio retention: platform-admin-configurable two-pass purge (capacity cap then time window) to keep MinIO usage bounded
- Keep-best: top-N detections per species by confidence preserved regardless of age (cap may be exceeded)
- User-pinned detections immune to retention (📍 toggle on every detection card)
- Stitched groups preserved as a unit when any member is keep-best
- Detection rows retained forever; only audio blobs purged (audio endpoints return 410 Gone for purged clips)
- Platform Settings UI: live storage usage bar (protected vs purgeable split), cap/days/keep-best inputs, "Run sweep now", last-run summary
- Per-detection call-segment highlights on spectrograms: pink freq × time rectangles per syllable
- Two-stage call-detection pipeline: BirdNET oracle (9s extended audio, 2.5s overlap) localizes the species' coarse region, librosa silence-splitting subdivides into syllables, coverage validation drops non-target syllables, per-species empirical frequency bands filter cross-species noise, per-segment peak/median ratio finds each call's true frequency band
- Empirical species-frequency-bands table refreshed every 12h from trusted detections
- Trust score: logit-space blend of raw BirdNET confidence with neighbor support (same species within ±60s); surfaces weak lone detections
- Trust badge and filter ("Confirmed only") + sort-by-trust on detection cards
- Species Timeline view: one heatmap row per species showing when it's active; period selector (today/week/month/year), sort (recent/count/dawn chorus/A-Z), pink "now" marker, configurable bucket granularity (15 min → 1 day)
- Backfill CLI for call_segments (
--hours,--species,--force)
v0.12 — Satellite Detail & Alerts
- Dedicated per-satellite page with full-width sections (activity, schedule, filters, config, biodiversity, expected species, live audio)
- Stats cards row (status, recording, version, location, CPU, storage, uptime, last seen)
- Today's hourly activity bar chart on satellite detail page
- Schedule 24h bar visualization with sun times for all profiles (right-aligned)
- Editable satellite config with override editor (lock, customize, reset)
- Expected species: centered pills with links to species profile (detected only)
- Alert rules: inline rename, duplicate (disabled by default)
- Alert channels: inline rename
- Species profile: share and comment buttons on detection list
- Chart improvements: pixel-based bar heights, date labels, locale-aware formatting
- Weather correlation: detection bar overlay (from bottom), fixed date format bug
- Dashboard: taller trend and activity charts with detection counts
- i18n: satellite status/recording/version translation keys
- Alert rules: "once per species per day" condition, detection date/time in all channels
- Alert deduplication: watcher_processed flag prevents re-evaluation of detections
- Alert messages: removed redundant detection summary (structured fields only)
- Satellite outbox: auto-recreate corrupted SQLite database on startup
- Live audio overhaul: hub-signaled unfiltered streaming via MQTT (live-start/stop/keepalive)
- Live audio: inline base64 via WebSocket, continuous auto-play with chunk chaining
- Force update button: always visible on satellite detail (bypasses version check)
- Satellite: WAV file cleanup on ack, periodic purge of outbox DB entries
- Satellite: git SHA in startup log and update script output
- Mosquitto ACLs for live-start, live-stop, live-audio, update-status topics
- Mobile app: live audio support (subscribe live-start/stop, publish unfiltered chunks)
- Mobile app: BuildKit Gradle cache for faster APK builds
- Expected species scoped to satellite (not global)
- Activity charts: hide future hours on today's view
- Satellite names: ellipsis truncation on detection lists
- Weather chart: fixed detection date offset (timezone)
- Live audio: gapless LiveSpectrogramPlayer with AudioContext streaming, auto-boost compressor, 15s buffer
- Live audio: hidden when satellite not recording, buffering indicator
- Migration chart: primary language only, compact rows, show all species toggle
- Top species: confidence ring chart (avg + max) replacing two columns
- Satellite immediate heartbeat on state change (recording/error/paused)
v0.11 — Satellite Polish & Live Audio
- Pi satellite audio device autodetection (when AUDIO_DEVICE is not set)
- Satellite heartbeat reports "error" state after consecutive capture failures with auto-recovery
- Remote update via MQTT with status feedback and detached script execution
- Git authentication for remote updates (HTTPS token or SSH key via .env)
- Version and audio device logged on satellite startup
- Chunk filter stats: aggregate tracking (processed/sent/rejected by reason) in heartbeat
- Filter stats display in satellite detail panel with pass rate bar
- Per-session filter pass rate on timeline ("X% sent" pill)
- Live audio streaming: "Listen live" on satellite detail with SpectrogramPlayer
- Field notes API and migration (text, photos, weather, location — backend ready)
- First-of-day/first-of-season duplicate alert fix (atomic conditional UPDATE)
- SpectrogramPlayer: auto-boost (peak normalization), buffering indicator, spectrogram alignment fix
- Species profile: sort detections by confidence or date
- Shared detection page: today's count, static OG page for link previews (Discord, Slack, Telegram, etc.)
- Open Graph link previews for bot-detected platforms (Discord, Slack, Telegram, WhatsApp, Twitter, Facebook)
- Reliable remote satellite update via systemd-run transient unit
- Update script: timestamps, retries, error trapping, PATH fix for detached execution
- Comprehensive release protocol documentation
v0.10 — Internationalization (i18n)
- English and French translations (500+ keys, every page)
- Language switcher, locale-aware formatting, translated map popups and heatmap labels
- Singular/plural support via Intl.PluralRules
- Alert messages in tenant's language (species names, labels, rarity reasons)
- First-of-day detection alerts with badge on detection cards
- Start-of-week day preference for heatmaps
- Species images not-found investigation panel with per-species retry
- Public share URLs in alert notifications with species image
- Notification images via Wikipedia direct URLs
- Shared detection page: translated species names, stats, lightbox, user language preferences
- Open Graph link previews (Discord, Slack, Telegram, WhatsApp, Twitter, Facebook)
- SpectrogramPlayer audio preloading with buffering indicator
- French translation quality pass (gender-neutral phrasing, idiomatic terms)
- Timeline session auto-splitting at 600 chunks
- Abbreviated relative times on detection pills
- Species search across all 38 languages, sort by primary language
v0.9 — Analytics & Visualization
- Biodiversity indices (Shannon, Simpson, Evenness)
- Migration pattern heatmaps, weather correlation (Open-Meteo)
- Enhanced detection map (clusters, heatmap, time filter)
- Enhanced dashboard (trend chart, activity bars, biodiversity snapshot)
- Location comparison (Jaccard similarity, shared/unique species)
v0.8 — Smart Alerts & Communication
- Custom alert rules engine (detection, absence, trend triggers)
- 6 notification channels (Email, Slack, Telegram, Google Chat, Discord, Webhook)
- Platform health banner
- Scheduled automatic exports (cron-based CSV/JSON/eBird/iNaturalist)
v0.7 — Species & Location Context
- Per-satellite config overrides with admin lock
- Species profile pages with trend, activity, seasonal data
- eBird expected species integration
- Activity heatmaps (hour x day-of-week)
- Shareable detection links (HMAC-signed)
- Detection comments
v0.6 — Detection Intelligence
- Detection timeline with session-based browsing
- Species filter pills, expand/collapse sessions
- First-of-season detection with badges
- Species accuracy stats from community verification
- Page layout system, server-side sorting/filtering/pagination on all pages
v0.5 — Scalable Architecture
- Hub split into stateless API + single-instance dispatcher
- Redis event bridge, service registry with auto-discovery
- System monitoring page for platform admins
- Comprehensive audit logging (30+ action types)
- Node.js 24, MQTT over WSS
v0.4 — Audio Intelligence
- SpectrogramPlayer (seek, loop, boost, speed, volume)
- Adaptive noise floor + spectral peak SNR filtering
- GPS per detection, satellite config push
- Satellite management with side panel
v0.3 — User Management & Security
- Account management, self-deletion, ownership transfer
- Login rate limiting, account lockout, last login tracking
- Audit log page
- Unified design system (buttons, badges, states)
v0.2 — Satellite Ecosystem
- Recording profiles (dawn chorus, night migration, low power)
- Community verification with keyboard shortcuts
- Android phone satellite app
- Species images from Wikipedia
- Data export (CSV, JSON, eBird, iNaturalist, xeno-canto)
- Multi-language bird names (38 languages)
v0.1 — Core Platform
- Distributed audio capture (Raspberry Pi satellites)
- BirdNET TFLite inference with geo-aware filtering
- Multi-tenant web UI with JWT auth
- Real-time WebSocket alerts for rare species
- Docker Compose deployment with Traefik
Planned
v0.14 — Model & Data Management (continued)
- Multiple BirdNET model versions with A/B testing
- Audio re-analysis when models improve
- Cold storage archival for purged audio
- Research export (structured datasets)
v0.16 — Mobile & On-Device (continued)
- Field notes UI (standalone field journal page)
- On-device inference (TFLite on phone)
- Native push notifications
- Mobile always-on background mode with persistent notification icon
v1.0 — Production Ready
- Unsaved changes confirmation dialog
- Security audit & hardening (GDPR erasure path)
- Two-factor authentication (TOTP)
- Session management (view and revoke active sessions)
- Email notifications (registration, password reset, rare species)
- Rolling updates with zero downtime
- Custom UI components (replace native HTML elements)
- Prometheus metrics, backup strategy, disaster recovery
- Documentation search, API auto-documentation