Files
Flaro/web
ScarriffleandClaude Opus 5 579a49b73b Der Server wusste, was du zuletzt gesehen hast — und sonst nichts
Für „wie viel habe ich letzte Woche geschaut" gab es keine Daten.
`UserItemState` ist eine Zeile je Titel: der letzte Stand. Wer einen Film
zweimal sieht, überschreibt den ersten Durchgang; wann etwas lief, wusste
der Server nur fürs jeweils letzte Mal. Nachträglich erfinden lässt sich
das nicht.

Jetzt gibt es ein Sehprotokoll: **eine Zeile je Nutzer, Tag und Titel.**
Keine Sitzungen — die brauchen ein Ende, und das kommt oft nie an, wenn
der Browser zugemacht oder das Telefon zugeklappt wird. Tagesbündel haben
diesen Lebenslauf nicht, es wird nur addiert.

**Gezählt wird, was wirklich lief.** Der Zuwachs zwischen zwei Meldungen,
gedeckelt auf die Zeit, die dazwischen verstrichen ist (mal zwei als
Toleranz für doppelte Geschwindigkeit und ausgefallene Meldungen). Sonst
ergäbe ein Sprung von Minute 5 auf Minute 90 anderthalb Stunden Sehzeit in
zehn Sekunden. Gemessen an fünf Meldungen im Abstand von elf Sekunden:
88 Sekunden statt 190.

Dabei fiel ein zweiter Fall auf: war **gar keine** Zeit verstrichen, griff
kein Deckel statt eines engen — eine frisch angelegte Zeile hätte ihre
Anfangsstelle voll mitgezählt. Wer einen Film öffnet und sofort auf Minute
fünf springt, hat keine fünf Minuten gesehen.

Im Profil stehen drei Zahlen, und jede sagt, woher sie kommt: die
aufgezeichnete Zeit fängt heute an, die Zahl gesehener Titel steht seit
jeher fest. Dazu eine Wochenkurve, die häufigsten Genres und was zuletzt
lief. **Jeder sieht nur sich selbst, auch ein Administrator** — es gibt
keinen Weg, ein fremdes Konto zu meinen.

Zwei Dinge auf dem Weg dorthin:

**Eine stellbare Uhr für die Tests.** Zwei Minuten Film lassen sich nicht
in fünf Millisekunden sehen, und das ist richtig so — prüfen liess es sich
nur, indem die Zeit vergeht, ohne sie zu verbringen.

**Ein Namenskonflikt im CSS.** Die leeren Wochenbalken trugen die Klasse
`leer`, und die gehört längst der Fläche „hier ist nichts" — mitsamt
24 Pixeln Polster. Jeder leere Balken war dadurch 48 Pixel hoch, egal
welche Höhe dastand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-06 17:20:01 +02:00
..

Flaro Web

Die Weboberfläche für Rechner, auf denen es keine App gibt — Windows vor allem.

Aufbau

Ordner Was
app/ Das Frontend (Vite, TypeScript)
server/ Ein Server ohne Abhängigkeiten, der die Anfragen weiterreicht und die gebauten Dateien ausliefert
frontend/ Die erste Fassung als einzelne Datei. Läuft, wird abgelöst.
jellyfin-theme/ Ein Kleid für Jellyfins eigene Oberfläche — die kleine Lösung von vorher

Warum ein eigener Server?

Er löst zwei Dinge, an denen die einzelne Datei scheitert, und zwar unabhängig davon, wie gut das Frontend geschrieben ist:

  • Herkunft. Anfragen laufen über /api und damit über dieselbe Adresse wie die Seite. Kein CORS, auch nicht beim Streamen.
  • Klartext und Verschlüsselung. Läuft der Medienserver über http und die Seite über https, blockiert der Browser den Stream. Dagegen kann keine Zeile im Frontend etwas tun — ein Server davor schon.

Nebenbei bleibt der Zugangsschlüssel beim Server, statt im Browser zu liegen.

Betreiben

cd app && npm install && npm run build
cd ../server && FLARO_SERVER=http://jellyfin:8096 node index.js

Dann auf http://localhost:8080. Der Port lässt sich über PORT ändern.

Entwickeln

cd app && FLARO_SERVER=http://jellyfin:8096 npm run dev

Vite übernimmt dabei das Weiterreichen, der eigene Server wird nicht gebraucht.