- Replace embedded Grafana iframes in ObservabilityPage with external
Grafana link cards. Grafana URL is configurable via VITE_GRAFANA_URL
(frontend) or GRAFANA_URL (backend env exposed to frontend build).
- Remove the grafana scrape job from monitoring/prometheus/prometheus.yml
so the main Prometheus stack no longer depends on Grafana.
- Pass GRAFANA_URL through docker-compose.yml and docker-compose.dev.yml.
The dark mode button was toggling React state but never applying it to the
DOM. Add a useDarkMode hook that:
- Persists the preference in localStorage
- Defaults to the OS prefers-color-scheme on first visit
- Adds/removes the 'dark' class on <html> to trigger CSS variable overrides
Also add dark-mode color overrides for all Tailwind v4 theme variables in
index.css.
Co-authored-by: openhands <openhands@all-hands.dev>
Refactor SSHKeyManager to match app layout pattern:
- List of SSH keys on the left (SelectionRailCard)
- Key details and form on the right (SectionCard)
- Add selectedSSHKeyId state to Settings component
- Click a key to select and populate the form
- New key button to create a new key
- Shows fingerprint and public key for selected key
- Delete button moved to the right panel
Backend:
- FastAPI app with 17 REST endpoints covering dashboard, monitoring,
media index, file browser, and jobs
- Reuses existing clients/domain/services unchanged
- pydantic-settings config, dependency injection, CORS setup
- Auto-generated OpenAPI docs at /docs
Frontend:
- Vite + React + TypeScript SPA
- @tanstack/react-query for data fetching with polling
- ag-grid-react for media table and file browser
- recharts for monitoring charts
- Tailwind CSS styling
- 4 pages: Dashboard, Monitoring, Media, File Browser
- Typed API client matching all backend endpoints
Also:
- docs/MIGRATION_PLAN.md with full architecture plan
- Updated .gitignore for both subprojects
- Streamlit app preserved for now (can coexist)