Layout-Fix Satz-Zeile (mobil), README knapp/oeffentlich, Roadmap aktualisiert
Image bauen und in die Registry schieben / build (push) Successful in 6s

- ex-grid: minmax(min(460px,100%),1fr) -> keine 460px-Mindestspalte auf dem
  Handy mehr; Block und X-Button nicht mehr abgeschnitten
- Satz-Zeile: Aktionen (Reset/X) rechtsbuendig per flexiblem Spacer; auf
  sehr schmalen Handys kompaktere Felder (72px)
- README: gekuerzt, bodenstaendiger Ton, interne CI/CD-/Infra-Notizen raus
- ROADMAP: Umgesetztes markiert, veraltete Punkte entfernt, gestrafft
- Tests: 169 Checks gruen (39+18+52+32+28)
This commit is contained in:
AI-Agent committed 2026-10-05 11:24:51 +00:00
1 parent 1759da8437
commit 7c5045cec8
4 files changed
+92 -136

No files matched your search

+37 -87
View File
@@ -1,135 +1,85 @@
# REKORD
**Rekord & Record: dein Training, festgehalten.**
Selbstgehosteter Trainings-Tracker für Gym, Laufen und Radfahren. Läuft im
Browser, speichert auf deinem Server, gehört dir.
Ein leichtgewichtiger, selbst gehosteter Trainings-Tracker fürs Gym, Laufen
und Radfahren. Läuft in jedem modernen Browser, speichert auf deiner Platte
und wertet deine Fitnessdaten nicht aus. Kein Abo, kein Konto bei einem
Anbieter, keine Datenkraken.
Eine SQLite-Datei als Zustand, ein Python-Backend aus der Standardbibliothek,
ein HTML/CSS/JS-Frontend ohne Framework. Kein Cloud-Konto, keine Telemetrie.
## Warum REKORD?
- **Kein Vendor Lock-in.** Alles läuft bei dir: Backend auf deinem Server,
Zustand in einer portablen SQLite-Datei. Export jederzeit als JSON oder
CSV, Import genauso. Zieh um oder hör auf - deine Daten gehören dir.
- **Leichtgewichtig.** Python-Standardbibliothek + SQLite im Backend, ein
HTML-, ein CSS-, ein JS-File im Frontend. Kein Framework, kein
Build-Schritt, keine Node-Installation. Läuft auf einem Mini-PC, einem
alten Laptop oder in einem Container.
- **Browserbasiert.** Keine App, kein Store, keine Installation. Aufschlagen,
loslegen - auf jedem Gerät mit Browser.
- **Cross-Device Sync.** Der Zustand liegt serverseitig. Öffne die App am
Handy, am Laptop oder am Desktop-Rechner - es ist derselbe Stand. Mehrere
Benutzer mit eigenen Konten und getrennten Daten sind eingebaut.
- **UX zuerst.** Sätze eintragen mit einer Box (Zahl + Einheit in einem
Feld), Set-Kette durch Abhaken, "Alles zurücksetzen", Verlauf inline
bearbeiten, Wochenübersicht, Statistik mit Differenz zur ersten Messung.
Der Tracker reibt sich nicht in den Weg zwischen dich und die Übung.
- **Dein Take aufs Aufzeichnen.** Die App zeichnet auf - Gewichte, Reps,
Cardio-Felder - und zeigt die Entwicklung über die Zeit. Sie verkauft
nichts, personalisiert nichts und schickt nichts nach Hause.
- **Open Source.** AGPL-3.0. Nachvollziehbar, erweiterbar, auditierbar.
## Features im Überblick
## Was es kann
**Training erfassen**
- Gym mit Push/Pull/Legs (frei konfigurierbar) plus Laufen und Radfahren
- Gym mit Push/Pull/Legs (frei konfigurierbar), dazu Laufen und Radfahren
- Eingabe als eine Box: Zahl links, Einheit fest rechts (kg, reps, km, min,
min/km, bpm, m)
- Set-Abhaken als "Set n [ ]": der ganze Button ist klickbar, das Set hakt
eine Kette ab - ohne Lücken
- Reset-Satz und "Alles zurücksetzen" laden das letzte abgeschlossene
Training
- Vorbefüllung beim Start (optional): "Letztes Training vorbefüllen" oder
"Plan-Gewichte vorbefüllen" (startKg aus der Config, auch ohne Verlauf)
- Sätze abhaken als "Set n [ ]"; der ganze Button ist klickbar, die Kette
hakt ohne Lücken ab
- "Reset-Satz" und "Alles zurücksetzen" holen das letzte abgeschlossene
Training; optional startet eine Session direkt mit dem letzten Workout
oder mit den Plan-Gewichten
- Übungen per Drag & Drop sortieren, Übungen aus anderen Tagen spontan
hinzufügen
- Fragezeichen pro Übung: Erklärung plus die passende Maschine
- Fragezeichen pro Übung: kurze Erklärung (herstellerunabhängig)
**Sessions & Verlauf**
**Verlauf & Statistik**
- "Session starten" / "Session abschließen", mehrere Sessions am Tag
- Keine Geister: erst abgeschlossene Sessions erscheinen im Verlauf
- Verlauf als Liste oder Wochenübersicht, inline bearbeitbar (Datum, Zeiten,
Abhak-Status, Werte) und löschbar
- Statistik: bestes Gewicht je Trainingstag mit Balken, Differenz zur ersten
Messung
- Verlauf als Liste oder Wochenübersicht; inline bearbeitbar und löschbar
- Statistik: bestes Gewicht je Trainingstag, Differenz zur ersten Messung
**Ansicht & Einstellungen**
- Deutsch und Englisch (Server-Standard und pro Benutzer)
- Farbthema: Dunkel, System (folgt dem Gerät), Hell - plus OLED-Dark-Schalter
- Akzentfarbe aus zehn Farben (inklusive Weiß)
- Gewichtseinheit kg oder lb, Start-Ansicht wählbar
- Einstellungen serverseitig, gelten auf allen Geräten
- Deutsch und Englisch
- Themes: Dunkel, System, Hell - plus OLED-Dark-Schalter
- Akzentfarbe aus zehn Farben, Gewichtseinheit kg/lb, Start-Ansicht wählbar
- Einstellungen liegen serverseitig, gelten auf allen Geräten
**Mehrbenutzer**
- Eigene Konten mit Kennwort (gehasht), Daten strikt getrennt
- Konten mit Kennwort (gehasht), Daten getrennt pro Benutzer
- Der erste Benutzer ist Administrator und verwaltet Konten und Kennwörter
- Einmaliger Einrichtungs-Wizard beim ersten Start (Sprache, Modus,
Darstellung)
**Daten**
- Export/Import als JSON und CSV (Backup, Umzug, Tabellen-Auswertung)
- Workouts über eine kleine API abrufbar (`/api/workouts`)
- Demo-Daten (`demo-data.json`) zum direkten Ausprobieren
- Workouts über eine kleine API (`/api/workouts`)
- Demo-Verlauf (`demo-data.json`) zum Ausprobieren
## Schnellstart
## Starten
Python (nur Standardbibliothek, kein `pip install`):
Python (nur Standardbibliothek):
```bash
python3 server.py 8080
```
Oder mit Docker:
Oder Docker:
```bash
docker compose up -d
```
Danach im Browser: `http://<host>:8080/`
Danach im Browser: `http://<host>:8080/`. Beim ersten Start führt ein kurzer
Wizard durch Sprache, Einzel- oder Mehrbenutzermodus und Darstellung.
Beim ersten Start führt dich ein kurzer Wizard durch Sprache, Einzel- oder
Mehrbenutzermodus und Darstellung - danach ist die App einsatzbereit.
## Plan anpassen
## Den Übungsplan anpassen
Übungen, Sätze, Gewichte und Erklärungen stehen in `config.json` - ohne
Code-Eingriff. Schema: [TECH.md](TECH.md).
Alle Übungen, Sätze, Gewichte, Maschinen und Erklärungen stehen in
`config.json` - ohne Code-Eingriff. Das komplette Schema steht in der
[technischen Dokumentation](TECH.md).
## Automatischer Build (CI/CD)
Ein Push auf `main` baut automatisch ein Docker-Image und legt es in der
Gitea-Registry ab (`git.somantis.net/j4stmarkus/trainingsplan`). Dafür läuft
ein Gitea-Actions-Runner auf dem Server; die Workflow-Datei liegt unter
`.gitea/workflows/build-image.yml`. Die CasaOS-Installation
(`docker-compose.casaos.yml`) bezieht die App aus diesem Registry-Image.
Fürs lokale Entwickeln bleibt `docker-compose.yml` mit `build: .` bestehen.
## Daten & Privatsphäre
## Daten
- Alles liegt in `data/state.db` (SQLite) - backupbar, überlebt Neustart und
Container-Rebuild
- Datenverzeichnis frei wählbar (`TRAINING_STATE_DIR`)
- Keine externen Dienste, keine Telemetrie, keine Analyse deiner Daten
- Datenverzeichnis per `TRAINING_STATE_DIR` frei wählbar
- Keine externen Dienste, keine Telemetrie
## Roadmap
## Mehr
Die geplante Weiterentwicklung (Übungskatalog in der App bearbeiten,
herstellerunabhängige Info-Texte mit Bildern/Schritten, Plugin-System mit
Ollama/Cloud-Coach, Wearable-Import, CLI-Harness) steht in
[ROADMAP.md](ROADMAP.md).
## Design
Die verbindliche Design-Sprache (Tokens, Komponenten, Zustaende, Anti-
Patterns) steht in [DESIGN.md](DESIGN.md) - wiederverwendbar für weitere
Projekte.
- [TECH.md](TECH.md) - Architektur, API, Datenmodell
- [DESIGN.md](DESIGN.md) - Design-Sprache (Tokens, Komponenten, Anti-Patterns)
- [ROADMAP.md](ROADMAP.md) - geplante Erweiterungen
## Lizenz
+46 -47
View File
@@ -1,63 +1,62 @@
# REKORD - Roadmap
Interne Roadmap. Prioritaeten: P1 = naechste Iterationen, P2 = bald, P3 =
spaeter. Status: Idee / Geplant / In Arbeit / Fertig.
Was geplant ist, und was schon steht. Priorität: P1 = als Nächstes, P2 = bald,
P3 = später. Status: Fertig / Teilweise / Geplant.
Zielrichtung: breiteres Feature-Set, einfachere Erweiterung des
Uebungs-/Maschinen-Katalogs, herstellerunabhaengige Inhalte, sanfte
Integration (Plugins, lokale Modelle) statt Monolithen. Architektur-Leitplanken
bleiben: Config-getrieben, leichtgewichtig, Daten lokal, keine Telemetrie.
Leitplanken bleiben: config-getrieben, leichtgewichtig, Daten lokal, keine
Telemetrie.
---
## Umgesetzt
## Phase 1 - Inhalte & Bedienbarkeit
- Config-getriebener Plan (`config.json`), SQLite-Zustand serverseitig
- Gym (Push/Pull/Legs), Laufen, Radfahren; Cardio-Felder aus der Config
- Set-Kette, Reset-Satz, "Alles zurücksetzen", Vorbefüllung (letztes Workout
oder Plan-Gewichte)
- Übungen per Drag & Drop sortieren, Übungen aus anderen Tagen hinzufügen
- Verlauf als Liste und Wochenübersicht, Inline-Bearbeitung, Löschen
- Statistik: bestes Gewicht je Tag, Differenz zur ersten Messung
- Mehrbenutzer mit Admin, Kennwort ändern/zurücksetzen, Server-Reset
- Einrichtungs-Wizard (Sprache, Darstellung, Modus)
- i18n de/en, Themes dunkel/system/hell + OLED, zehn Akzentfarben
- Export/Import JSON/CSV, Workouts-API, Demo-Daten
- Übungs-Infos herstellerunabhängig; mobile-taugliche Satz-Zeile
| Prioritaet | Thema | Status | Notiz |
## Offen
### Inhalte & Bedienbarkeit
| Prio | Thema | Status | Notiz |
|---|---|---|---|
| P1 | **Uebungen/Maschinen in der App bearbeiten** | Idee | Heute aendert man `config.json` von Hand. Ziel: Uebungen, Tage, Maschinen und Info-Texte direkt in der App anlegen/bearbeiten (persistiert neben der Config), damit ein Nicht-Programmierer den Plan ohne Dateieditor pflegt. |
| P1 | **Info-Texte erweitern** | Idee | Neben dem Freitext: optionale Bilder (URL oder Upload), Schritte als Checkliste, ein "wertvoller Link" (z.B. zu einer neutralen Anatomie-/Form-Quelle). Wichtig: **nicht hersteller-spezifisch** - die Technogym-Referenzen aus der Config sind nur Platzhalter; der Katalog soll generisch sein. |
| P1 | **Uebungsvarianten & Maschinen-Tags** | Idee | Eine Uebung mit mehreren Varianten (KH, Maschine, Kabel) und deren Verfuegbarkeit; beim Training schnell zwischen den Geräten wechseln, die im Studio stehen. |
| P1 | **Set-Vorlagen pro Uebung** | Idee | Im Plan definierte Satz-Vorlagen (Anzahl, Ziel-Reps, Pause) als Startpunkt - schon teilweise da ("Plan-Gewichte vorbefuellen"), aber noch nicht pro Satz steuerbar. |
| P2 | **Gewichtseinheiten pro Uebung** | Idee | z.B. Bodyweight (kein kg), Bandwiderstand, Maschinen-Gewicht inkl. Hebel - neben dem globalen kg/lb. |
| P1 | Übungen/Maschinen in der App bearbeiten | Geplant | Statt `config.json` von Hand: Übungen, Tage und Info-Texte direkt in der App pflegen. |
| P1 | Info-Texte erweitern | Geplant | Optional Bilder, Schritte als Checkliste, ein Link (neutral, nicht herstellerspezifisch). |
| P1 | Übungsvarianten & Maschinen-Tags | Geplant | Eine Übung mit Varianten (KH, Maschine, Kabel) und schnellem Wechsel im Training. |
| P2 | Set-Vorlagen pro Übung | Teilweise | Plan-Gewichte vorbefüllen gibt es; noch nicht pro Satz steuerbar (Ziel-Reps, Pause). |
| P2 | Einheiten pro Übung | Geplant | Bodyweight, Band, Maschinen-Gewicht - neben dem globalen kg/lb. |
## Phase 2 - Integration & Automation
### Integration
| Prioritaet | Thema | Status | Notiz |
| Prio | Thema | Status | Notiz |
|---|---|---|---|
| P1 | **Plugin-System** | Idee | Kleine Plugins (JS im Browser und/oder Server-Skripte) mit klaren Hooks: nach Session-Speichern, beim Export, beim Anzeigen einer Uebung, beim Abschluss. Registrierung in der Config. So bleiben Erweiterungen ausserhalb des Kerns. |
| P1 | **Ollama/Cloud-Coach** | Idee | Plugin, das Form-Tipps/Zusammenfassungen per API generiert - **local-first** (Ollama), Cloud nur mit expliziter Zustimmung und eigener Wahl des Anbieters/Keys. Keine Daten gehen ohne Erlaubnis nach aussen. |
| P2 | **Webhooks bei Events** | Idee | Nach "Session abgeschlossen", "Benutzer angelegt" etc. - fuer eigene Automation (Backup, Benachrichtigungen, Hausautomation). |
| P2 | **API-Keys pro Benutzer** | Idee | Neben den Login-Tokens: eigene read/write Keys pro Benutzer fuer Scripts, ohne das Konto freizugeben. |
| P2 | **Effizienter Harness (CLI)** | Idee | Kleines Kommandozeilen-/Script-Interface (`rekord`-CLI oder Python-Client) gegen die API: Workouts eintragen/abrufen, Statistiken ziehen - fuer Cron-Jobs, TUI, Automation. |
| P3 | **Wearable-Import** | Idee | Garmin/Apple/Fitbit/Samsung-Health-Exporte (CSV/JSON) als Plugin importieren; Puls etc. an Cardio-Sessions anhaengen. Kein Live-Sync in Phase 1. |
| P1 | Plugin-System | Geplant | Kleine Plugins mit Hooks (nach Session-Speichern, beim Export, beim Anzeigen). |
| P1 | Ollama/Cloud-Coach | Geplant | Form-Tipps/Zusammenfassungen per API - local-first (Ollama), Cloud nur auf Wunsch. |
| P2 | Webhooks bei Events | Geplant | Nach "Session abgeschlossen" o.ä. für eigene Automation. |
| P2 | API-Keys pro Benutzer | Geplant | Read/write Keys für Scripts, ohne das Konto freizugeben. |
| P2 | CLI-Harness | Geplant | Kleines Kommandozeilen-Interface gegen die API (Cron, TUI). |
| P3 | Wearable-Import | Geplant | Garmin/Apple/Fitbit/Samsung-Exporte (CSV/JSON) als Plugin. |
## Phase 3 - Analyse & UX
### Analyse & UX
| Prioritaet | Thema | Status | Notiz |
| Prio | Thema | Status | Notiz |
|---|---|---|---|
| P1 | **Volumen & 1RM-Schaetzung** | Idee | Trainingsvolumen (kg × Reps) je Uebung/Tag, 1RM-Schaetzung (z.B. Epley) als zusaetzliche Statistik-Kennzahl. |
| P2 | **Wochenvergleich & Trends** | Idee | Statistik ueber Wochen hinweg (nicht nur "Differenz zur ersten Messung"): gleitende Durchschnitte, PR-Markierungen, Verlaufs-Graph (ohne externe Chart-Lib, wenn moeglich). |
| P2 | **PWA / Offline** | Idee | Als installierbare App (Service Worker, App-Icon) - nicht kritisch, da serverseitig, aber schoener auf dem Handy. |
| P2 | **Sessions am selben Tag bessern** | Idee | Mehrere Sessions pro Tag sind drin; UX fuer "morgens laufen, abends Gym" vereinfachen (schneller Aktivitaets-/Tag-Wechsel). |
| P1 | Volumen & 1RM-Schätzung | Geplant | kg × Reps je Übung/Tag, 1RM-Schätzung als zusätzliche Kennzahl. |
| P2 | Wochenvergleich & Trends | Geplant | Gleitende Durchschnitte, PR-Markierungen, Verlauf ohne Chart-Lib. |
| P2 | PWA / Offline | Geplant | Installierbar auf dem Handy (Service Worker, Icon). |
| P2 | Mehrere Sessions am Tag | Teilweise | Funktioniert; Aktivitäts-/Tag-Wechsel im UI vereinfachen. |
## Phase 4 - Qualitaet & Betrieb
### Qualität
| Prioritaet | Thema | Status | Notiz |
| Prio | Thema | Status | Notiz |
|---|---|---|---|
| P2 | **Barrierefreiheit (a11y)** | Idee | Tastatur-Navigation, Kontraste, Screenreader-Labels systematisch pruefen. |
| P2 | **Backup/Retention** | Idee | Automatische Export-Erinnerung oder in-App-Backup-Timer; Dokumentation fuer Rotation. |
| P3 | **Mehrsprachigkeit ausbauen** | Idee | i18n-Architektur ist da (de/en); weitere Sprachen als Community-Beitrag. |
| P3 | **Mehr-Server / Replikation** | Idee | Datenhaltung bleibt SQLite; falls noetig: Import/Export als Synchronisationsweg dokumentieren statt Live-Replikation. |
---
## Konzepte in einem Satz
- **Content in der App statt in der Datei** - der Uebungskatalog wird Teil des
Produkts, nicht des Repos.
- **Herstellerunabhaengig** - Maschinen-Referenzen sind Hinweise, keine
Abhaengigkeit; Links/Medien sind optional und austauschbar.
- **Plugins statt Kern-Zerfaserung** - alles, was nicht jeder braucht
(Coach, Sync, Import), wird Plugin.
- **Local-first** - lokale Modelle (Ollama) sind der Default, Cloud nur auf
ausdruecklichen Wunsch.
| P2 | Barrierefreiheit | Teilweise | Fokus, Kontraste, Labels gepflegt; systematischer Test offen. |
| P2 | Backup/Erinnerung | Geplant | Export gibt es; automatische Backup-Erinnerung offen. |
| P3 | Weitere Sprachen | Geplant | i18n-Architektur (de/en) steht; weitere Sprachen als Beitrag. |
+1
View File
@@ -931,6 +931,7 @@ function buildSetRow(a, model, ex, entry, i) {
row.appendChild(rBox);
entry.wInput = wBox.querySelector("input");
entry.rInput = rBox.querySelector("input");
row.appendChild(el("span", "set-gap"));
const reset = el("button", "icon-btn", "");
reset.type = "button";
+8 -2
View File
@@ -405,7 +405,7 @@ h3 { font-size: 15px; font-weight: 700; }
.ex-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(460px, 1fr));
grid-template-columns: repeat(auto-fill, minmax(min(460px, 100%), 1fr));
gap: 14px;
align-items: start;
}
@@ -438,12 +438,18 @@ h3 { font-size: 15px; font-weight: 700; }
.set-row {
display: grid;
grid-template-columns: auto auto auto auto auto;
grid-template-columns: auto auto auto 1fr auto auto;
gap: 6px;
align-items: center;
padding: 6px 8px;
}
.set-gap { min-width: 0; }
@media (max-width: 480px) {
.field-box { width: 72px; }
}
.set-rows { overflow: hidden; }
.set-row.is-done { background: var(--bg-subtle); }