OpenAthlete
AGPLv3 기반 지구력 훈련 플랫폼—EU 호스팅, 투명한 로직, 자체 호스팅·전체 내보내기 지원
스마트 트레이너 연결·전력 선택·트레이닝, 웹‑블루투스 PWA로 로컬에서 ERG 모드·프로그램·평가 제공, 계정 필요 없음
Smarttrainer verbinden, Watt wählen, treten. Web-Bluetooth-PWA: ERG-Modus, Programme, Auswertung — alles lokal, kein Konto.
스포츠·피트니스JavaScript · CSSGitHub @grenzenloseSchublade온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Wahoo KICKR als Ergometer im Browser — wattgesteuertes Training ohne Zwift, ohne Abo, ohne Konto. Web-Bluetooth-PWA (FTMS).
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Zwei Taps bis zum Treten. ergoMergo macht aus einem Wahoo KICKR (oder jedem FTMS-Smarttrainer) ein wattgesteuertes Ergometer — direkt im Browser, ohne Zwift, ohne Abo, ohne Konto, ohne virtuelle Welt. Trainer per Bluetooth verbinden, Programm oder Wattzahl wählen, fahren.README 전문 보기 ↗
Zwei Taps bis zum Treten. ergoMergo macht aus einem Wahoo KICKR (oder jedem FTMS-Smarttrainer) ein wattgesteuertes Ergometer — direkt im Browser, ohne Zwift, ohne Abo, ohne Konto, ohne virtuelle Welt. Trainer per Bluetooth verbinden, Programm oder Wattzahl wählen, fahren.
Live: https://grenzenloseschublade.github.io/ergoMergo/
Die App schickt deine Daten nirgendwohin — kein Server von uns, kein Konto, keine Analyse, keine Cookies, keine fremden Bibliotheken. Fahrten (inklusive Herzfrequenz), Einstellungen und Programme liegen nur im Browser auf deinem Gerät. Eine Content-Security-Policy lässt den Browser Verbindungen nur zur eigenen Adresse der App zu — selbst eingeschleuster Code könnte nichts an einen fremden Server senden.
Ohne Netz läuft alles. Ist das Gerät online, fragt die App nur sw.js ab, um
Updates zu erkennen (beim Öffnen, beim Zurückkehren, alle 10 min — nie während
der Fahrt); GitHub als Hoster sieht dabei wie bei jedem Seitenaufruf IP-Adresse
und Zeitpunkt. Sicherung und TCX-Export entstehen nur auf deinen Tipp als Datei
auf deinem Gerät.
| Datenschutz-Etikett | |
|---|---|
| Vom Entwickler erhoben | nichts |
| An Dritte weitergegeben | nichts |
| Tracker / Werbung | keine |
| Berechtigungen | Bluetooth, nur für die im Chrome-Dialog gewählten Geräte |
| Speicherort | nur dein Browser (IndexedDB) |
| Löschen | jederzeit in der App bzw. über die Browserdaten |
Belegt durch eine automatische Selbstprüfung vor jeder Veröffentlichung — Prüfkatalog, Speicher-Inventar, Grenzen und „So prüfst du es selbst": docs/sicherheit.md. Funde bitte über SECURITY.md melden.
Wer nur strukturiert Watt treten will, braucht keine 3D-Welt, kein Monatsabo und keinen Account. Was fehlte: eine App, die den Trainer ansteuert wie ein Studio-Ergometer — Ziel-Watt, Intervalle, ±-Tasten am Lenker, Auswertung. ergoMergo ist genau das: eine einzige statische Web-App (Vanilla JS, Web Bluetooth/FTMS, keine Buildkette, kein Backend), alle Daten bleiben lokal auf dem Gerät.
| Bereich | Was drin ist |
|---|---|
| ERG-Steuerung | Ziel-Watt mit sanften Rampen, ±-Tasten (Touch, Tastatur, Zwift Click/Ride), Not-Stopp mit geschütztem WEITER |
| Trainingsplan | Tage/Dauer/Ziel wählen, Wochen mit Aufbau und leichter Testwoche, heutige Einheit mit einem Tipp, verschieben/kürzer/leichter/auslassen mit Rückgängig |
| Programme | Zeitbasierte Generatoren (Sprint 30/30, HIIT 40/20, VO2max 4×4, Schwelle, Ausdauer, Recovery), klassische Programme, FTP-Rampentest, .zwo-Import (Einstellungen → Erweitert, standardmäßig aus) |
| Fahrbildschirm | Live-Graph mit Programmprofil und Positionscursor, Blocksteuerung (überspringen/zurück/+30 s), Kadenz-Zielbereiche, Fokus-Modus (Tap auf Werte oder Graph kippt die Gewichtung), LED-Statuszeile, Gerätezustand oben links, Bild-in-Bild (Experiment) |
| Ansagen & Töne | Countdown vor jedem Wechsel, unterscheidbare Signale für härter/leichter (Dur-Dreiklang rauf bzw. Töne abwärts), Sprachansagen aus vorgerenderten Audio-Bausteinen — funktionieren auch mit Bildschirm aus |
| Geräte | Trainer, Herzfrequenz-Gurt, Zwift Click/Ride; Tasten frei belegbar per Lern-Modus; Schnellverbindung ohne Geräteauswahl (mit Chrome-Flag) |
| Auswertung | Dauer, Ø/max/NP, IF/TSS, HF, Distanz (aus Trainer-Speed integriert, im ERG-Modus gangabhängig), Zeit in Zonen, Soll/Ist-Vergleich pro Block, Wochenbilanz, TCX-Export, Akkuverbrauch pro Fahrt |
| Plattform | Installierbare PWA, offlinefähig, alles lokal in IndexedDB — kein Server, keine Cloud; Demo-Modus ohne Trainer (Button auf dem Startbildschirm) |
css/tokens.css; lebendiger Style Guide
(docs/stil.html),
eine Prüfung verhindert feste Werte. Alle Tippflächen ≥ 44 px..zwo-Import ist jetzt eine Einstellung (Erweitert), standardmäßig aus.npm test prüft Stil, Plan-Regeln (alle
Wochentag-Kombinationen, Verpass-Muster, Verschiebungen), Abläufe und
Layout.| Gerät | Firmware/Version |
|---|---|
| Wahoo KICKR CORE 2 | FW 3.5.37 |
| Zwift Ride (Lenker) | FC82-Firmware (ab Jan 2025), Lern-Modus für Tastenbelegung |
| Samsung-Smartphone, Android-Chrome | Primärziel (Handy am Lenker) |
| Ubuntu-Laptop, Chrome | Sekundärziel |
Jeder FTMS-Trainer sollte funktionieren (Standard-Protokoll); getestet ist die Kombination oben. iOS wird nicht unterstützt (kein Web Bluetooth in Safari).
chrome://flags/#enable-web-bluetooth
aktivieren. Scheitert das Pairing, den Trainer einmalig per bluetoothctl
koppeln (pair + trust).chrome://flags/#enable-web-bluetooth-new-permissions-backend
erspart die Geräteauswahl bei jedem Start (Schnellverbindung).Dauer und Trainingstyp wählen — die App generiert ein vollständiges Programm mit Warmup-Rampe, skaliertem Hauptteil und Cooldown. Intensitäten sind fix (%FTP), die Zeit skaliert über Wiederholungen und Z2-Füller. Ohne FTP-Wert wird 170 W angenommen. Kein Tabata, keine 10-s-Sprints: ERG braucht 2–6 s pro Sollwertwechsel, kürzere Intervalle wären überwiegend Rampe. Strukturen, Formeln und Quellen: docs/programme.md
Alle Daten liegen lokal in einer IndexedDB (ergomergo) im Chrome-Profil —
kein Server, kein Konto, keine Cloud. Stores: sessions (Kennwerte je Fahrt),
sessionData (Rohsamples 1/s), settings, programme, logs (Diagnose).
navigator.storage.persist() schützt vor automatischem Aufräumen. Sicherung:
Komplett-Backup als JSON (Einstellungen → Sicherung) und TCX-Export je Fahrt.
Einmal verbundene Geräte (Trainer, HF-Gurt, Zwift Click/Ride) werden gemerkt; mit persistenten Web-Bluetooth-Berechtigungen verbindet die App beim Start ohne Geräteauswahl, HF-Gurt und Controller automatisch mit. Zwift-Ride-Tasten werden in Einstellungen → Geräte → „Tasten zuordnen" interaktiv belegt (+/−, Block vor/zurück, STOPP), je Aktion auch mehrere Tasten; ist von einem Paddle nur eine Richtung belegt, wirkt es in beide. Ab Werk: Watt hoch = beide Paddles nach außen, Watt runter = beide nach innen, Block vor/zurück = Pfeil rechts/links, STOPP = B. Die rpm-Anzeige kommt direkt vom Trainer (der KICKR schätzt die Trittfrequenz selbst, kein externer Sensor nötig).
Die App liest die Trainer-Firmware aus (Geräteliste, Diagnose-Log). Updates
macht sie nicht — es gibt kein öffentliches Protokoll: der KICKR CORE 2
aktualisiert über WLAN/Wahoo-App, Zwift Ride/Click über die Companion-App.
Ride-Firmware ab Jan 2025 wechselt die BLE-Service-UUID auf FC82 — die App
unterstützt beide Varianten. Fehlersuche: docs/debugging.md
python3 -m http.server 8000
# http://localhost:8000 — localhost ist Secure Context, HTTPS lokal nicht nötig.
Dev-Parameter: ?demo=<workoutId> (z. B. ?demo=vo2max — Demo-Fahrt ohne
Trainer), ?demo (freies Fahren); alle Parameter in
docs/debugging.md. Test vom Android-Gerät:
GitHub-Pages-Deployment oder USB-Debugging + chrome://inspect.
Farben, Schriftgrößen, Radien und Abstände kommen nur aus css/tokens.css
(Regeln: docs/stil.md, alle Bausteine live:
docs/stil.html).
node tools/stil-check.mjs # feste Werte außerhalb der Tokens (läuft auch in release.mjs)
node tools/datenschutz-check.mjs # jede Netzstelle freigegeben, CSP unverändert (läuft auch in release.mjs)
node test/sicherheit.mjs # präparierte Sicherung: kein Schadcode, bereinigt
node test/netz.mjs # Netz-Mitschnitt aller Abläufe inkl. Service Worker, CSP, Speicher
node test/layout.mjs # Fahrbildschirm in 5 Größen: Bedienleiste, Überlauf, Zentrierung, Sprünge, Panel
node test/ablauf.mjs # Navigation, Einstellungen, Fahrt, Programm, Demo-Wege mit Sollwerten
Die Browser-Tests brauchen Node ≥ 22 und ein Chrome (CHROME=/pfad/zu/chrome,
sonst Playwrights chrome-headless-shell oder google-chrome); sie starten
ihren eigenen Server.
Der Versionsstempel steht doppelt (VERSION in sw.js für die
Update-Erkennung, APP_VERSION in js/version.js für den
Install-Konsistenz-Check) — laufen sie auseinander, bricht jede
Service-Worker-Installation ab. Deshalb ausschließlich über das Skript bumpen:
node tools/release.mjs # nächste Version, setzt beide Stempel
node tools/release.mjs --check # prüft vor dem Push auf Drift
Danach committen (Konvention: „…; Release vXX") und pushen. Der Workflow
.github/workflows/pages.yml prüft (Stil, Datenschutz, Sicherheit, Netz) und
veröffentlicht nur die App-Dateien aus tools/auslieferung.mjs; installierte
Apps bieten das Update per Button an.
tools/log-pull.mjs holt das Diagnose-Log und die Fahrtdaten direkt aus der
IndexedDB der App auf dem Android-Gerät — ohne Export in der App. Es nutzt
adb forward auf den Chrome-DevTools-Socket und das DevTools-Protokoll.
Voraussetzungen: USB-Debugging, Chrome mit offenem ergoMergo-Tab, Node ≥ 22.
node tools/log-pull.mjs # Log anzeigen + Komplett-Dump als JSON
node tools/log-pull.mjs --logs-only # nur das Log
node tools/log-pull.mjs --seit 2026-09-21 # Log ab Datum
MIT