monitor-im-flur
Hallway / common-area wall monitor dashboard. A single-page React + Vite app that surfaces useful household + transit + weather + fun data on a passive display.
Key Features
- Realtime-ish auto‑refresh via git commit hash file (
/git-hash.html) – hot-reloads the deployed page when a new build is published. - Dynamic theming (day / evening / night) based on current time.
- Public transport departures (KVV) for two nearby stops (IDs 7000044 & 7000045).
- Weather (current, hourly, daily min/max) via Open‑Meteo.
- Flatastic chores integration (tasks + flatmates) with API key.
- Home Assistant readings (tent temperature + humidity) displayed in a faux terminal with rotating shitposts.
- 4:20 easter egg card + Amogus sprite + other playful flourishes.
- Docker / Nginx static deployment image (
git.rivercry.com/wg/monitor-im-flur:latest). - Strict linting + formatting (ESLint AirBnB + Prettier + Biome optional).
- Zustand + RTK (toolkit present) state management (currently Zustand in active use).
Tech Stack
- React 19 + TypeScript + Vite
- Zustand (with devtools) for app stores (weather, kvv, flatastic, home assistant)
- Nginx (static file serving) inside minimal Docker image
- Open‑Meteo, Flatastic, KVV, Home Assistant external APIs
- Git hash pipeline script to trigger client self‑reloads
Project Structure (abridged)
src/
api/ # External data fetchers
components/ # UI building blocks (Cards, Timetable, Weather, Terminal, etc.)
store/ # Zustand stores encapsulating fetch + state
types/ # Type definitions for external data
pipeline/
create-git-hash-html.sh # Injects current commit hash into dist
Dockerfile # Nginx static hosting
docker-compose.yml # Example runtime service definition
Environment Configuration
Create a .env (or .env.local) for Vite with the following (only what you need):
VITE_FLATTASTIC_API_KEY=your_flatastic_api_key
# (Planned) VITE_HOME_ASSISTANT_TOKEN=your_long_lived_token # NOTE: currently hardcoded – see Security section
Vite automatically exposes variables prefixed with VITE_ to the client bundle. Do NOT place secrets without that prefix – but remember: anything in the client bundle is public. For sensitive data consider a tiny proxy backend instead of calling APIs directly from the browser.
Security Notice
src/api/homeAssistant.ts currently contains a hard‑coded long‑lived Home Assistant token. This should be refactored before any public deployment:
- Remove the literal token from the repository.
- Load it via environment variable during build (
import.meta.env.VITE_HOME_ASSISTANT_TOKEN) OR - Prefer a minimal server proxy so the token never ships to the browser.
Development
Install dependencies (Bun is inferred from bun.lock, but npm/pnpm/yarn also work).
bun install
Run the dev server (HTTPS support possible with vite-plugin-mkcert if certificates are trusted):
bun run dev
Open: http://localhost:5173
Lint & Format
bun run lint
Optionally run Biome (if desired):
npx biome check --apply .
Build
bun run build
Outputs production bundle to dist/.
Docker Image
Build locally:
docker build -t monitor-im-flur:local .
Run:
docker run --rm -p 9123:80 monitor-im-flur:local
Or use compose (uses published image):
docker compose up -d
Visit: http://localhost:9123
Git Hash Auto‑Reload Mechanism
pipeline/create-git-hash-html.sh writes the current commit ($GITHUB_SHA) to dist/git-hash.html during CI. The dashboard polls /git-hash.html every 10s; when the value changes it performs window.location.reload(). Ensure your CI runs the script after vite build and before creating the Docker image.
Pseudo CI step example:
vite build
GITHUB_SHA=$(git rev-parse HEAD) ./pipeline/create-git-hash-html.sh
docker build -t git.rivercry.com/wg/monitor-im-flur:$(git rev-parse --short HEAD) .
Data Sources
- KVV Departures: Public endpoint (JSON) for stop IDs 7000044 / 7000045.
- Weather: Open‑Meteo forecast API (lat 49.0094, lon 8.4044, Europe/Berlin TZ).
- Flatastic: Auth via
x-api-key(user provided). - Home Assistant: Long‑lived bearer token (refactor recommended).
Adding a New Card
- Create a directory under
src/components/<NewCard>/withNewCard.tsx& optionalstyle.module.css. - Wrap content with existing
Cardcomponent (icon+nameprops). - Register inside
Dashboard.tsxwhere layout lives (usingCardColumn/CardRow).
State Management Notes
All data fetching is encapsulated inside zustand store fetch methods invoked on an interval within the respective components. Consider centralizing polling or using React Query if complexity grows.
Potential Improvements / TODO
- Remove hard‑coded Home Assistant token.
- Error + loading states (currently optimistic, failures would be silent / console only).
- Retry & backoff strategy for network calls.
- Dark mode override / manual theme toggle.
- Accessibility pass (ARIA, focus management) – current dashboard is mostly passive.
- Tests (none yet). Could add Vitest + React Testing Library.
- Switch transit API code to gracefully handle outages (KVV sometimes rate limits).
License
Add a license file if you plan to share externally (currently unspecified).
Support / Contact
Internal project (wg). For issues open a ticket on Gitea: https://git.rivercry.com/wg/monitor-im-flur
Generated README draft – adjust repository paths / badge branch name if different (e.g., replace master with your default branch).