PRIME FC Mini League
PRIME FC Mini 4-a-side League 2026 — fixtures, results and live table.
Translation pending
Lift Heavy Shit. Trainingsplaner fuer 5x5, Zwift und Jams — statische Web-App ohne Build, ohne Abhaengigkeiten, ohne Server.
Translation pending
Sports & fitnessGitHub @cyphomatOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Zur Sprache. Die App gibt es auf Deutsch und Englisch — umschaltbar unter Tour → ⚙ Backstage → App. Zweisprachig sind die ganze Oberfläche, die Ansage samt Tageswort, Meilensteine, Minierfolge, Aufnäher und Fehlermeldungen. Deutsch bleiben nur die Übungsinhalte — Erklärungen, Cues, typische Fehler, Bewegungsstandards (im Kettlebell-Kurs stehen Übungsnamen und Cues englisch, die Erklärungen deutsch) — sowie die mitgelieferten Sprüche, die Jam-Bewegungen und die Rad-Begründungen. Das ist Fachtext, der inhaltlich übersetzt werden muss statt Wort für Wort. In deinen Daten steht das Tageswort immer deutsch, damit „Ansage gegen Gefühl“ in beiden Sprachen gleich zählt.
Auf dem Mac wird daraus eine Übersicht — Kalender, Wochenlast, Bestwerte und Verlaufskurven nebeneinander statt untereinander:
Und so richtest du es ein — die App fragt, statt dich eine JSON-Datei schreiben zu lassen:
Und das sagt sie dir über deine Kraft — nicht nur wie viel, sondern wo sie schief steht:
Und ein bisschen Bühne — Rang, Monats-Tour mit Endgegner, Aufnäher, Schallplatten, Gitarrenrack und Tourshirts, alles aus deinen Einheiten:
Und die Kugel — Kettlebell-Kurs und Mosh Pit, mit der Kugel in kg, Checks und einem eigenen Endgegner:
Echte Bildschirme mit Beispieldaten, aufgenommen über tools/shot.html und tools/shots.mjs. Keine Mockups.
Der Unterschied zu einem Logbuch: sie hat eine Meinung zum heutigen Tag — aus Daten, nicht aus dem Bauch.
Die Ansage liest Trainingspause, offene Fehlversuche, laufende Serie und Form vom Rad und entscheidet zwischen TECHNIK, SOLIDE, HART und SCHWER — und fragt nach der Einheit, wie sich das wirklich angefühlt hat. Die Ansage bleibt damit überprüfbar statt behauptet.
HRV, Ruhepuls, Befinden und Schlaf gehen vor. Fällt die HRV deutlich unter den eigenen Schnitt der letzten Tage, liegt der Ruhepuls 7 Schläge darüber, hast du starken Muskelkater oder große Müdigkeit eingetragen oder war die Nacht zu kurz, sagt die App TECHNIK an — auch wenn Trainingsplan oder offene Fehlversuche eigentlich etwas anderes verlangen würden. Beides sieht etwas, das reine Trainingslast nicht erfasst.
Interferenz-Warnung, wenn eine harte Fahrt weniger als vier Stunden her ist — die letzten Sätze werden zäh, das Maximalkraftniveau bleibt unberührt.
Meilensteine kennen die alten Bestleistungen samt Datum:
Aus deiner Geschichte — Gestern vor 5 Jahren: 140 kg Back Squat. Heute stehst du bei 65 kg — nicht weil du weniger kannst, sondern weil du wieder anfängst.
Minierfolge stehen nach jeder Einheit ganz oben. Nicht der Bericht, sondern das Geschaffte.
Die Stimme mischt eigene Zeilen mit 52 mitgelieferten, etwa halbe halbe. Eintragbar unter Tour → ⚙ Backstage → Persönlich — dort steht auch dein Grund, der nur an den harten Tagen erscheint.
Zwift ──▶ Strava ──▶ intervals.icu ◀──▶ Setlist ◀──▶ setlist-data (privat)
│ │
Fahrten, Form Kraft-Progression
Setlist besitzt die Kraft-Progression — zwei Systeme, die dasselbe Arbeitsgewicht berechnen, laufen unweigerlich auseinander. Das Rad läuft andersherum: es kommt automatisch über Zwift → Strava → intervals.icu, Setlist zeigt es nur als Hinweis und schreibt im Gegenzug jede Krafteinheit zurück, damit Fitness und Ermüdung in einer Kurve liegen statt in zwei getrennten Welten.
Der Rückweg wartet bewusst bis zum nächsten App-Start: die Apple Watch erkennt Krafttraining oft selbst über die Herzfrequenz und reicht es mit Verzögerung über Strava nach. Ein sofortiger Push käme dem meist zuvor und dieselbe Einheit stünde doppelt in Fitness und Ermüdung.
5×5 ist ursprünglich für drei Einheiten pro Woche gebaut. Bei höchstens zwei gilt dieselbe Mechanik, nur langsamer — die 60-%-Regel für den Wiedereinstieg hätte bei dieser Frequenz sechs bis neun Wochen unter Reizschwelle bedeutet, deshalb sind es 80 %.
| Übung 1 | Übung 2 | Übung 3 | |
|---|---|---|---|
| Workout A | Back Squat 5×5 | Bench Press 5×5 | Barbell Row 5×5 |
| Workout B | Back Squat 5×5 | Strict Press 5×5 | Deadlift 1×5 |
Back Squat ist in beiden Workouts dabei und steigt darum doppelt so schnell.
| 5×5-Automat | Steigerung, Fehlerzähler, Deload auf 90 % nach drei Fehlversuchen. |
| Deload nach einer Pause | Ab 14 Tagen ohne Krafteinheit schlägt die App beim Start einen Rückschritt vor: −10 %, ab 21 Tagen −20 %, ab 42 Tagen −30 %. Ein Tipp übernimmt, einer behält die alten Gewichte — nichts ändert sich ohne dich. Danach steigt jede erfolgreiche Einheit doppelt, bis das Gewicht vor der Pause wieder erreicht ist; ein Fehlversuch beendet die Abkürzung. Faustregeln, keine Messwerte. |
| Plattenrechner | Scheiben pro Seite. Nicht exakt ladbare Gewichte werden benannt statt gerundet. Darunter eine zweite Zeile mit derselben Last nur aus 20/10/5/2,5/1,25 — die Reihe, die in jedem Studio komplett liegt. Wo keine 25er und 15er sind, lädt man eben 2×20 statt 25 + 15. Sie erscheint nur, wenn sie etwas anderes sagt. |
| Soundcheck | Aufwärmsätze aus dem Arbeitsgewicht: leere Stange, dann 55 / 70 / 85 %. Jede Zeile abhakbar — angetippt durchgestrichen. Die Cardio-Zeile am Anfang lässt sich unter Backstage → Persönlich durch einen eigenen Einstieg ersetzen, etwa 15 Min Rudern. Über der Liste läuft ein Timer für diese Zeile, mit Pause; am Ende hakt er sie ab. Seitstütz und Curl-up bekommen einen „Halten“-Knopf mit Countdown. |
| Gewicht im Satz | Anpassbar während der Einheit — das Log bildet ab, was wirklich passiert ist. |
| Pausenuhr | 90 s, nach Fehlversuch 180 s, im Lauf um ±30 s verstellbar. Endet mit Vibration und Ton, stoppt sich nach dem letzten Satz der Einheit selbst. |
| Aftershow | Hilfsübungen nach dem Hauptprogramm: Klimmzüge, Chin-ups, Dips, Liegestütze, Face Pulls, Curls, hängendes Beinheben. Je Satz die Wiederholungen, daneben, was beim letzten Mal ging. Ohne Steigerung, ohne Einfluss auf Gewichte und Tonnage. In der Tour steht je Übung der beste Satz. |
| Bestwerte | Maximum (nur aus Max-Out) gegen Mindestens (aus Arbeitssätzen, systematisch zu niedrig). |
| Max-Out | Krafttest mit e1RM. Dreht den A/B-Wechsel nicht. |
| Wissen an der Stange | Aufklappbar: Begründung, Cue, typischer Fehler, Brücke zum olympischen Heben. |
| Mobility | Fünf Übungen, einmal pro Kalenderwoche fällig — bei der ersten Einheit (Kraft oder Jam), ganz gleich welcher. Eigener Button, jederzeit unabhängig davon nutzbar. In der Einheit lässt sich „Mobility gemacht“ abhaken, in der Bibliothek trägt einen eigenen kleinen Eintrag ein. Mobility zählt als Mobility, nicht als Training: keine Serie, keine Tonnage, keine Übertragung zu intervals.icu. Dreimal in einer Woche bringt den Aufnäher . |
| Radfahrten | Fahrten, Stunden, Kilometer, Last, Energie, Ø Leistung mit Anteil an der FTP und die Wochenlast über zwölf Wochen — aus intervals.icu. Dazu die Trittfrequenz je Fahrt gegen dein Ziel (unter Backstage → Persönlich, ohne Eintrag 80 rpm; 2 rpm darunter zählen noch), Ø Watt gegen NP als Balkenpaare (wie gleichmäßig du fährst) und je Fahrt Ø Watt, NP, IF, Last, Puls, Kadenz, RPE, Gefühl und die Zone mit der meisten Zeit. Neue Leistungs-Bestwerte, die intervals.icu meldet, stehen gesammelt darüber; bei Plan gegen Ist steht, wie hart sich die Fahrten im Ziel und daneben angefühlt haben (Ø RPE). |
| Trainingskalender | 26 Wochen als Raster: Kraft bernstein, Jam grün, Rad stahlblau. |
| Wochenlast gestapelt | Kraft und Rad in einem Balken — die eine Kurve, wegen der beides zusammengehört. |
| Fitness gegen Ermüdung | Zwei Linien aus intervals.icu — die Fläche dazwischen ist die Form. |
| Erholung (HRV/Ruhepuls/Befinden/Schlaf) | Aus intervals.icu, meist via HealthFit aus Apple Health. HRV und Ruhepuls nur relativ zur eigenen Basis der letzten Tage bewertet, nicht absolut. Muskelkater und Müdigkeit, wie du sie in intervals.icu einträgst (1–4), dazu der Schlafwert. Fließt in die Ansage ein. |
| Wattziele | Aus der eFTP statt Prozentangaben. |
| Unplugged | Fünfzehn Minuten, nur Körpergewicht, im Zweifel leise. Feste Intervalle mit geführter Uhr statt Wiederholungszahlen — für den Morgen, an dem noch jemand schläft. Der Leise-Modus lässt alles Springende weg und gibt keinen Ton, nur Vibration. |
| Kettlebell Mosh Pit | Das Folgeprogramm nach dem Kurs: Swing, Goblet Squat und einarmiges Drücken, je drei Sätze. Erst mehr Wiederholungen (10 · 12 · 15 · 17 · 20), dann eine um 4 kg schwerere Kugel und wieder von unten — wie beim 5x5, nur mit Kugel. Zweimal nicht geschafft: eine Stufe zurück. Das nächste Ziel folgt aus den Logs. |
| Kettlebell-Kurs | Zwölf Wochen, drei Einheiten pro Woche: erst Hüfte, Swing und Get-up sauber, dann einarmig und nach der Uhr, am Ende Dichte und ein Test in Woche 12. Jede vierte Woche ist Entlastung. Die Einheit führt durch, Sätze hakst du ab, Takt und Pausen laufen allein. Wiederholungen und Seite (links, rechts) stehen groß auf der Bühne, vor Kugelwechsel, nach dem Rad und vor dem Tragen steht eine Umbaupause, und unter der Bühne steht, wie die Übung geht und was oft schiefläuft, bei Hinge, Swing, Einarm-Swing, Goblet Squat, Press und Get-up mit Pixelbildern der Haltungen. Vor der Einheit trägst du ein, mit welcher Kugel du arbeitest (in kg, die letzte ist vorbelegt); Gesamtuhr, Stoppuhr und Countdowns laufen mit. Auf Wunsch sagt eine Stimme Umbau, Pause, Handwechsel und die nächste Übung an, praktisch, wenn das Handy an der Anlage hängt. In Woche 4 und 8 stehen Checks, in Woche 12 der Abschlusstest. Danach bewertest du jede Kugel einzeln (zu leicht, passend, zäh) — zweimal zu leicht oder zu zäh bei derselben Übung, und die App schlägt die andere Kugel vor. Auf Home zeigt eine Leiste, wie weit du bist, und nach jeder Einheit steht ein Erfolg da. Zeichnest du mit der Apple Watch auf, stellst du das ein, und Setlist schickt nichts doppelt nach intervals.icu; ohne Watch geht die Einheit mit geschätzter Last dorthin. Verlauf und Checks stehen in der Tour unter „Kugel“. Wo du stehst, folgt aus den Logs. Steht am gewählten Ort ein und bist du in den letzten Stunden nicht gefahren, schlägt die Einheit sechs Minuten Rad zum Aufwärmen vor (locker, drei kurze Antritte); ein Schalter lässt dich es jederzeit an- oder abwählen. |
| Offline | Einheiten werden gepuffert. Tour und Radansicht zeigen den letzten Stand. |
| Bildschirm bleibt an | Während Einheit, Jam, Unplugged und Max-Out geht das Display nicht aus. Zum Abhaken muss nicht entsperrt werden. Danach gibt die App den Bildschirm wieder frei. |
| Export als CSV | Backstage → App: alle Einheiten als Tabelle für Excel, Numbers oder Sheets. Entsteht im Browser, geht an keinen Dienst; Text aus deinen Daten kommt nie als Formel an. |
| Selbstaktualisierend | Prüft die Version beim Start und lädt sich genau einmal neu. |
| Sound und Vibration | Ton bei Pausenende und Einheitsabschluss, zusätzlich zur Vibration — Ton respektiert den Stumm-Schalter, Vibration nicht. |
| Saisonales | Zu Weihnachten (1.–26.12.), Ostern (Gründonnerstag bis Ostermontag) und Halloween (24.–31.10.) hängt unter dem Tageswort ein kleiner Banner mit bewegtem Pixelmotiv und einem Satz; zum Gedenken an Lemmy (28.12.) und Ozzy (22.7.) steht eine stille Kerze da. Unter Backstage → App abschaltbar, per ✕ für heute ausgeblendet; nur auf dem Gerät. Eine Einheit im Zeitfenster bringt dazu einen Aufnäher (Weihnachts-Gig, Eiersuche, Geisterstunde, Eine Kerze), der erst an der Wand steht, wenn er verdient ist. |
| Hell und dunkel | Umschalter System / Hell / Dunkel. Zwei echte Fassungen, keine Invertierung. |
| Schriftgröße | Normal / Groß / Sehr groß unter Backstage → App. Skaliert die ganze Oberfläche gleichmäßig, gilt nur auf diesem Gerät. |
| Startseite als Plakat | Oben ein Tageswort (TECHNIK, SOLIDE, HART, SCHWER), darunter nur, was heute etwas ändert — Pause, Verletzung, müde Form, Rad zu nah. Form, Schlaf, Gewicht und Rad stehen als kleine Instrumente darunter und klappen auf Antippen auf. Rechts eine Wochenkarte mit Regler und Serie und eine Gewichtsliste, über der die Reunion-Tour steht, bis sie geschafft ist. |
| Tour mit Reitern | Überblick, Kraft, Körper, Rad, Einheiten. Die Einstellungen liegen getrennt davon im Backstage (⚙ in der Tour): Persönlich, Orte, Verbindungen, App. |
| Handy und Mac | Ab 900 px zwei Spalten, in der Tour breitere Raster — dieselbe Reihenfolge, kein Umbau. |
| Deutsch und Englisch |
| Alle Übungen an einem Ort | Grundlifts, Technik, Mobility, Finisher und alle Jam-Bewegungen, durchsuchbar und nach Kategorie filterbar. |
| Wann die Wiederholung zählt | Zu 60 Übungen steht ein Bewegungsstandard als Prüfkriterium: nicht „tief in die Hocke", sondern „Hüftfalte unter der Kniescheibe, oben Hüfte und Knie ganz gestreckt". Auch im Jam, im Unplugged und in der laufenden Einheit. Dehnungen und Geräte auf Zeit bleiben bewusst ohne — dort gibt es keine gültige Wiederholung. |
| Nach Kategorien gegliedert | Jede Kategorie mit eigener Farbe und Anzahl; je Übung Name, Dosis und Cue, aufgeklappt Erklärung, Standard, Fehler und „Wenn es klemmt“. |
| Übung des Tages | Den ganzen Tag dieselbe, kompakt oben; „Ansehen“ klappt sie in der Liste auf, ↻ würfelt neu. Tritt beim Suchen und Filtern zurück. |
| YouTube-Suchlink statt geratenem Video | Ein einzelnes fest verdrahtetes Video könnte offline oder falsch sein. Per eigenem Link überschreibbar. |
| Eigene Notizen | Auf Wunsch über „Notiz hinzufügen“; gespeichert stehen sie als Text bei der Übung. Landen in bibliothek.json in setlist-data und wachsen mit — dieselbe Wissensschicht wie config.json, nur für das, was du selbst gelernt hast. |
| Ersteinrichtung | Kein Programm im Repo? Dann fragt die App: Stange, die fünf Übungen mit Startgewicht, Krafttage, optional Radtage — und schreibt daraus eine gültige config.json. Kein JSON von Hand. |
| Deine Stimme | Dein Grund, eigene Sprüche und alte Bestleistungen direkt in der App. Der Grund erscheint an harten Tagen, die Bestleistungen an ihren Jahrestagen. |
| Orte und Geräte | Mehrere Gyms (Homegym, Box, Studio …) mit eigener Ausstattung. Der Jam würfelt nur aus dem, was dort steht. Ohne eingerichtete Orte bleibt alles erlaubt. Trägst du Kugel, Stange und Scheiben ein, rechnet der Lastrechner (Backstage → Orte) und der Kurs zeigt unter der Kugel, was aufgesteckt wird — auch wenn ein Gewicht nicht exakt ladbar ist. Feste Hanteln (Stück × kg) und Widerstandsbänder (nur Farben, die Stärke hängt von der Marke ab) lassen sich ebenfalls eintragen. |
| Ortswahl in der Kopfzeile | Ein Knopf zeigt, wo du gerade bist, und stellt um — auf dem Startbildschirm wie im Jam. In der Auswahl steht je Ort, wie viele Jam-Bewegungen dort möglich sind. |
| Update-Hinweis für Forks | Ein Fork bleibt stehen, wo er abgezweigt ist. Die App vergleicht ihre Version mit der des Originals und sagt einmalig Bescheid, samt Weg zum Aktualisieren. |
| Sprache | Oberfläche auf Deutsch oder Englisch, umschaltbar im Backstage. |
state.json ist abgeleitet, nicht gepflegt. Eine Projektion aus config.json und allen Dateien in einheiten/. Ein vertippter Eintrag wird nie zum Problem: Datei korrigieren, „state.json neu berechnen", fertig. Arbeitsgewichte werden nie direkt gesetzt — dafür gibt es den Log-Typ anpassung.
„Mindestens" ist nicht „Maximum". e1RM-Formeln setzen Nähe zum Versagen voraus; ein 5×5-Arbeitssatz ist submaximal, die Formel unterschätzt dort systematisch. Deshalb mischt die Verlaufskurve die Quellen nicht: gestrichelte Linie für Untergrenzen, Max-Outs als eigene Punkte.
Nur ausprobieren oder einfach benutzen? Dann brauchst du nichts davon: App öffnen, Lokal starten (siehe Loslegen oben und Daten). Ein eigenes Datenrepo (Schritte 2, 4 und 5 mit der gehosteten App unter cyphomat.github.io/setlist) lohnt sich, wenn du denselben Stand auf mehreren Geräten willst. Fork und Pages (Schritte 1, 3 und 6) brauchst du nur für eine eigene, unabhängige Fassung, deren Code du selbst in der Hand hast.
Setlist ist für genau eine Person gebaut — dich. Es gibt keinen Login mit mehreren Konten; wer die App benutzt, ist der oder die, dessen setlist-data-Repo hinterlegt ist. Um eine eigene, unabhängige Instanz zu bekommen, brauchst du ein GitHub-Konto und etwa zehn Minuten.
1 · App-Code forken
Fork dieses Repo (cyphomat/setlist) in dein eigenes GitHub-Konto. Das ist der öffentliche Teil — Code, kein Personenbezug.
2 · Eigenes Datenrepo anlegen
Leg ein privates Repo namens setlist-data an. Mehr braucht es nicht — keine Datei
von Hand. Beim ersten Öffnen merkt die App, dass noch kein Programm da ist, und fragt
dich durch: Stangengewicht, die fünf Übungen mit Startgewicht (oder ein Klick auf „mit der
leeren Stange anfangen"), Krafttage, optional Radtage. Daraus schreibt sie eine gültige
config.json in dein Repo.
Wer lieber selbst schreibt, kann das weiterhin — die Datei sieht dann so aus:
{
"bar": 20,
"rounding": 2.5,
"deload": { "afterFails": 3, "factor": 0.9 },
"lifts": {
"squat": { "name": "Back Squat", "increment": 2.5, "start": 40 },
"bench": { "name": "Bench Press", "increment": 2.5, "start": 30 },
"row": { "name": "Barbell Row", "increment": 2.5, "start": 30 },
"ohp": { "name": "Strict Press", "increment": 2.5, "start": 20 },
"deadlift": { "name": "Deadlift", "increment": 5.0, "start": 50 }
},
"workouts": {
"A": [{ "lift": "squat", "sets": 5, "reps": 5 }, { "lift": "bench", "sets": 5, "reps": 5 }, { "lift": "row", "sets": 5, "reps": 5 }],
"B": [{ "lift": "squat", "sets": 5, "reps": 5 }, { "lift": "ohp", "sets": 5, "reps": 5 }, { "lift": "deadlift", "sets": 1, "reps": 5 }]
},
"firstWorkout": "A",
"rest": { "normal": 90, "afterFail": 180 },
"plates": [25, 20, 15, 10, 5, 2.5, 1.25],
"week": { "slots": [{ "day": 1, "type": "strength" }, { "day": 4, "type": "strength" }] }
}
start ist dein Einstiegsgewicht je Übung, increment die Steigerung pro erfolgreicher
Einheit. week.slots legt fest, an welchen Wochentagen etwas ansteht (day: 1 = Montag …
7 = Sonntag); Radslots ("type": "ride") brauchen zusätzlich ein rides-Array. Fehlt
etwas davon, bleibt die Wochenübersicht einfach leer — der Rest der App läuft weiter.
state.json nicht anlegen — die App leitet den Startzustand beim ersten Mal selbst aus
config.json ab und schreibt ihn erst nach der ersten abgeschlossenen Einheit zurück.
einheiten/ als Ordner reicht leer. Optional sind stimme.json (eigene Sprüche, siehe
js/content.js für die Struktur) sowie records und ziele in config.json, wenn du
Meilensteine oder alte Bestleistungen willst. Die Ordner soundcheck/ und zusammen/
legt die App selbst an, der erste Wochen-Soundcheck bzw. der erste Check-in.
3 · Veröffentlichen
Im Fork unter Settings → Pages: Source auf den main-Branch stellen. Nach ein bis zwei Minuten läuft die App unter https://<du>.github.io/setlist/.
4 · GitHub-Token erzeugen
Klick oben rechts auf dein Profilbild → Settings — deine persönlichen Kontoeinstellungen, nicht die Settings des Repos — dann Developer settings → Personal access tokens → Fine-grained tokens → Generate new token. Zugriff nur auf dein Datenrepo, Permission Contents → Read and write, sonst nichts. Setz eine Laufzeit (etwa ein Jahr) und erzeug vor Ablauf einen neuen Token — eintragen unter Tour → ⚙ Backstage → Verbindungen. Meldet die App „Token ungültig, abgelaufen …“, ist es meist genau das.
Beim ersten Öffnen landest du automatisch auf dem Setup-Screen. Dort trägst du deinen GitHub-Nutzernamen, den Namen deines Datenrepos (steht schon auf setlist-data vor) und den Token ein — kein Code-Editieren nötig, das Repo-Ziel ist direkt in der App einstellbar. Alle drei bleiben ausschließlich im localStorage deines Browsers.
5 · intervals.icu — optional
Nur nötig, wenn du auch Radeinheiten/Form/HRV/Schlaf willst. Key liegt unter Settings → Developer in deinem intervals.icu-Konto.
6 · Updates holen
Dein Fork bleibt stehen, wo du ihn abgezweigt hast — am Original wird weitergearbeitet, aber davon bekommt er von sich aus nichts mit. Die App sagt dir deshalb Bescheid: läuft dein Fork auf einem älteren Stand, erscheint beim Start einmalig ein Hinweis, und unter Backstage → App steht, welche Version oben liegt und welche bei dir.
Aktualisieren geht dann in zwei Klicks auf GitHub:
GitHub Pages baut danach neu, und beim nächsten Öffnen lädt sich die App einmal selbst
neu. Deine Daten sind davon nicht berührt — die liegen in deinem eigenen setlist-data,
das mit dem App-Code nichts zu tun hat.
Falls du eigene Änderungen am Code gemacht hast, geht es über die Kommandozeile:
git remote add upstream https://github.com/cyphomat/setlist.git # einmalig
git fetch upstream && git merge upstream/main
git push
Fertig. Die erste Einheit legt state.json automatisch an; alles danach ist Ableitung, kein manuelles Pflegen.
Ohne Konto liegt alles auf dem Gerät. Wer mit Lokal starten beginnt, hat Programm, Einheiten, Soundchecks, Verabredungen und Notizen in diesem Browser (IndexedDB). Es gibt kein Konto und keinen Server, und nichts verlässt das Gerät, außer du verbindest intervals.icu. Die App bittet den Browser, den Speicher dauerhaft zu halten. Auf dem iPhone gilt das aber nur für die installierte App: Safari räumt den Speicher normaler Webseiten nach sieben Tagen ohne Besuch auf. Also Zum Home-Bildschirm.
Sichern und Einlesen. Unter Backstage → App → Daten lädst du eine Sicherung als
JSON-Datei herunter (setlist-sicherung-JJJJ-MM-TT.json) und liest sie auf einem anderen
Gerät oder nach dem Löschen wieder ein. Einlesen legt dazu, statt zu ersetzen:
Einheiten sind unveränderlich, also ist die Vereinigung beider Seiten richtig. Dieselbe
Einheit kommt nicht doppelt, und vorher zeigt die App, wie viel neu ist. Ein anderes
Programm in der Datei wird nur nach Rückfrage übernommen. Der Zustand (Arbeitsgewichte,
A/B) wird danach aus allen Einheiten neu berechnet. Haben sich seit der letzten Sicherung
Einheiten angesammelt und liegt sie zwei Wochen zurück, erinnert der Wochenkopf daran.
Oder mit eigenem GitHub-Datenrepo. Wer Setlist auf mehreren Geräten mit demselben Stand nutzen will, verbindet im Setup ein privates Repo (siehe Selbst einrichten). Dann liegt jede Einheit als Datei im Repo. Wer so angefangen hat und lieber ohne Konto weitermacht: Daten → Aufs Gerät umziehen holt alles aus dem Repo auf dieses Gerät und trennt GitHub. Im Repo bleibt alles liegen. Ein Abgleich in beide Richtungen wie bei Riffforge folgt.
Löschen heißt löschen. Im lokalen Modus heißt der Knopf Alles löschen. Er nennt die Zahl der Einheiten, und ohne Sicherung ist danach nichts mehr da.
Die App ist für eine Person gebaut und soll auch nur für diese Person sichtbar sein. Was das konkret heißt:
Deine Daten liegen auf deinem Gerät oder in deinem privaten Repo. Lokal bleibt alles in
der IndexedDB dieses Browsers. Sie ist an die Adresse gebunden; unter cyphomat.github.io
teilen sich allerdings alle Seiten dieses Kontos denselben Speicherbereich. Mit Datenrepo
liest und schreibt die App ausschließlich in setlist-data — Einheiten, Körpergewicht, Notizen, der Injury Report (also Gesundheitsangaben) und die Namen deiner Studios. Der App-Code selbst (dieses Repo)
ist öffentlich, enthält aber keine Daten. Beim Start prüft die App die Sichtbarkeit deines
Datenrepos und warnt unübersehbar, wenn es öffentlich steht — sonst würde man es nie
merken, weil die App genauso funktioniert.
Zugangsdaten verlassen den Browser nur zu ihrem eigenen Dienst. GitHub-Token und
intervals.icu-Key liegen im localStorage und werden ausschließlich als
Authorization-Header mitgeschickt — nie in einer Adresse, nie in einem Commit, nie in
einer Fehlermeldung.
Drei externe Ziele, sonst keine. api.github.com für deine Daten (nur mit Datenrepo), intervals.icu für
Rad und Form, ein YouTube-Suchlink in der Bibliothek (ohne Referrer). Keine Analytics,
kein CDN, keine Schriften von fremden Servern.
Abmelden räumt das Gerät leer. Lokal heißt der Knopf Alles löschen (siehe Daten). Mit Datenrepo löscht Backstage → App → Zugänge entfernen löscht Token, Key und alle zwischengespeicherten Daten aus dem Browser — Einheiten, Injury Report, Gewicht, Schlaf, Fahrten. Es bleiben nur Einstellungen wie Thema und Schriftgröße. Liegen noch ungesendete Einheiten in der Warteschlange, sagt die Rückfrage das vorher.
Nicht in fremden Seiten. Lädt eine andere Adresse die App in einem Rahmen, zeigt sie nur einen Hinweis und startet nicht — so lassen sich keine Klicks unterschieben. Auf GitHub Pages geht das nicht per Header, deshalb erledigt es js/boot.js vor dem ersten Bild.
Fremdtext wird maskiert. Aktivitätsnamen aus intervals.icu setzt nicht du, sondern
Strava, Zwift oder eine Gruppenfahrt. Solcher Text — genauso die Namen aus Einladungslinks und alles aus deiner config.json — wird vor der Anzeige maskiert
(js/sicher.js), und eine strikte Content-Security-Policy (script-src 'self') fängt ab,
was durchrutschen sollte. Selbst eingetragene Videolinks werden auf http/https
begrenzt.
Einladungen bleiben unter dir. Eine Einladung zum gemeinsamen Training ist ein Link, den du selbst verschickst. Hinter dem # stehen nur Kennung, Schritt und Name; dieser Teil geht nie an einen Server, und die App nimmt nichts ungefragt an.
Was bewusst nach draußen geht: Ist die Übertragung nach intervals.icu aktiv, landen dort Datum, Dauer, geschätzte Trainingslast und eine Zeile pro Übung mit Gewicht und Wiederholungen. Abschaltbar unter Backstage → Verbindungen.
| Datei | Rolle |
|---|---|
js/program.js | 5×5-Automat, Plattenrechner, e1RM. Reine Funktionen. |
js/coach.js | Ansage, Ton, Meilensteine, Minierfolge. Ebenfalls rein. |
js/wod.js | Jam-Generator, deterministisch über einen Seed. |
js/stats.js | Tonnage, Bestwerte, Sparklines, Radstatistik. |
js/content.js | Wissensschicht: Cues, Soundcheck, Technik, Encore, Stimme. |
js/bibliothek.js | Bündelt alle Übungen zu einer durchsuchbaren Liste. |
js/i18n.js | Oberflächentexte auf Deutsch und Englisch. |
js/geraete.js | Orte, Ausstattung, Machbarkeit einer Bewegung, Scheibenrechner für Kugel und Kurzhantel. |
js/sicher.js | Maskiert Fremdtext, prüft Adressen. |
js/aktualisierung.js | Vergleicht die eigene Version mit der des Originals; Autor, Issues und Quelltext-Link (im Fork der Fork). |
js/einrichten.js | Baut aus ein paar Antworten eine gültige config.json. |
js/persoenlich.js | Grund, eigene Zeilen und alte Bestleistungen. |
js/unplugged.js | Körpergewichts-Intervalle, Vorrat und Ablauf. |
js/moshpit.js | Mosh Pit: Leiter, Ziel aus den Logs, Statistik. |
js/kurs.js | Kettlebell-Kurs: Plan, Wochenlogik, Ablauf, Kugelvorschlag. |
js/verletzung.js | Injury Report: Sperren, Verlauf, Pausenfenster für die Serie. |
js/merch.js | Merch-Stand: Aufnäher, Schallplatten, Rang, Tourshirts, Wochenregler — alles aus den Logs. |
js/gitarren.js | Gitarrenrack: welche Gitarre an welchem Rang oder welcher Schallplatte hängt, was neu dazukam, was als Nächstes fehlt. |
js/hilfs.js | Aftershow: Hilfsübungen bereinigen, letztes Mal, Bilanz. |
js/wach.js | Hält den Bildschirm während des Trainings an. |
node tools/tests.mjs
Mit Node 22 oder neuer (empfohlen: die aktuelle LTS), ohne Installation. Dasselbe läuft
als GitHub Action bei jedem Push und Pull Request (.github/workflows/tests.yml); die
Actions sind an Commits gepinnt, neue Versionen meldet Dependabot als Pull Request. Ohne Node geht es auch mit der
JS-Engine, die in macOS ohnehin steckt:
JSC=/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Helpers/jsc
for t in tests/*.test.js; do $JSC --module-file=$t; done
2911 Tests in 33 Dateien. Kein Build, keine Abhängigkeiten.
Die Tests prüfen die Rechnung, die Proben das, was man sieht. Sie öffnen die echte App in Chromium, mit gestellter GitHub-API, gestelltem intervals.icu und einem festen Datum:
node tools/proben.mjs # alle: start, einheit, tour, merch, buehne, bibliothek, rueckschau, lokal, sicherheit, englisch, ueber
node tools/proben.mjs start merch # einzelne
node tools/proben.mjs -v # auch jede bestandene Prüfung
Geprüft wird in beiden Themen, mit „Sehr groß“, bei 360 bis 1280 px und auf Deutsch und Englisch: Was zu sehen sein muss, ist da, nichts ragt über den Rand, und es gibt keine Seitenfehler. Dazu kommen Sicherheitsfälle: Eigener Text läuft nie als Code, Abmelden räumt auf, und die App lässt sich nicht in fremde Seiten einbetten.
Einen Server bringen die Proben selbst mit. Sie brauchen nur Playwright samt Chromium
(npx playwright install chromium; ein eigener Browser geht über CHROMIUM=/pfad). Die
Bilder landen im Temp-Ordner (PROBEN_BILDER ändert das). In der GitHub Action laufen
sie bewusst nicht, damit Setlist ohne Abhängigkeiten bleibt.
sh tools/release.sh 2026-09-14.1
git add -A && git commit -m "…" && git push
Setzt version.json und den Cache-Namen in sw.js gemeinsam — beides muss sich ändern, sonst merkt die App nichts Neues.
Screenshots neu aufnehmen — zwei Werkzeuge, weil zwei Sorten Bildschirm:
python3 -m http.server 8765 &
sh tools/screens.sh # Training: Start, Einheit, Tour, Jam, Max-Out
node tools/shots.mjs # Einrichten, Stimme, Orte, Fork-Hinweis
screens.sh treibt tools/shot.html mit Chrome — die App läuft dort aus dem
Zwischenspeicher. Das reicht nicht für Bildschirme, die davon abhängen, was die API
antwortet: der Einrichte-Bildschirm erscheint nur bei einer fehlenden config.json, der
Fork-Hinweis nur bei einer neueren Version im Original. shots.mjs antwortet deshalb
selbst (Playwright, plattformunabhängig, npx playwright install chromium).
Web-App, die URL genügt. Für ein eigenes Fenster: Safari → Ablage → Zum Dock hinzufügen, oder Chrome → Adressleiste → Installieren.
Token und Key liegen im localStorage, also pro Gerät — auf dem Mac einmal neu eintragen. Die Trainingsdaten kommen aus dem Repo und sind überall dieselben. Zwei Geräte gleichzeitig eine Einheit abschließen lassen sollte man nicht; nacheinander ist problemlos.
Nirgends im Code, nirgends im Repo, in keinem Commit. GitHub-Token und intervals.icu-Key werden in der App eingegeben und liegen ausschließlich im localStorage des jeweiligen Browsers.
Setlist ist von @cyphomat.
| Gefühl nach der Einheit | Vier Stufen (Leicht/Normal/Hart/Extrem) auf dem Geschafft-Screen — macht die Ansage im Nachhinein überprüfbar. |
| Injury Report | Was gerade zwickt, mit deiner eigenen Behandlung. Zwei Arten: wiederkehrend (kommt und geht, wird nach der Einheit kurz abgefragt, kann ausheilen) und strukturell (bleibt, wird nicht abgefragt, sperrt dauerhaft). Übungen, die du sperrst, würfelt der Jam nicht, das Unplugged nimmt sie nicht, Technik und Mobility lassen sie weg. Grundübungen werden nur angemerkt, nie weggelassen — daran hängt die 5×5-Mechanik. Die App stellt keine Diagnose und schlägt keine Behandlung vor. |
| Merch-Stand | Ein bisschen Spiel, passend zur Bühne: eine Kutte mit Aufnähern (Plattenclub, 1000-lb-Club, Körpergewicht-Marken, Comeback, Serien, Roadcrew und Hangar 18 für die Aftershow, Duett, Faustgruß, Tourpartner und feste Verabredung fürs Training zu zweit, Kurs-Debüt, Phasen, Checks, schwerere Kugel, Pit-Serien, Kugel-Rang und Kurs zu zweit für die Kettlebell … und fürs Rad: Tourbus-Kilometer, Stairway to Heaven, Highway Star, Doom für disziplinierte Grundlage, Open Air, Crossover-Wochen mit Kraft und Rad), Gold und Platin fürs bewegte Gewicht als gerahmte Auszeichnungen an der Studiowand (bis Adamant bei 1000 t, dazu eine eigene Reihe Kugel-Platten aus Kurs und Mosh Pit), ein Kurs-Endgegner für die drei Checks, ein Gitarrenrack mit zehn Pixel-Gitarren, die sich über Rang und Schallplatten freischalten (kaufen kann man nichts), ein Rang von der Garagenband bis zur Hall of Fame und jedes Quartal ein Tourshirt als Pixel-Bandshirt: Stofffarbe und Emblem kommen aus dem Tournamen, vorne Siebdruck, hinten deine Trainingstage — zum Umdrehen. Nach der Einheit kommt die Setlist als Zettel mit Gaffa-Tape, auf Home steht ein Wochenregler, der nur bei erfülltem Plan und sauberen Sätzen auf elf geht. Belohnt wird Regelmäßigkeit, nie Menge: der Rang zählt Wochen statt Einheiten (Radwochen eingeschlossen), und eine eingetragene Verletzung friert die Serie ein statt sie reißen zu lassen. Alles aus den Logs berechnet, nichts gespeichert. |
| Pixel-Bühne | Jeder Aufnäher hat ein eigenes Pixelbild, auch jede Stufe einer Leiter: die Gigs wachsen vom Setlist-Zettel über Ticket, Plakat und Amp bis zum hochgehaltenen Feuerzeug, die Kilometer vom Fahrrad bis zur Weltkugel, und im Plattenclub steht jeder Lift als eigene Figur mit 1–4 Scheiben an der Stange. Die Form zeigt die Kategorie: Bühne rund, Kraft achteckig, Rad eckig, Comeback Wappen, Serie Stern. Jeder Rang hat seine Szene, von der Garage bis zur Hall of Fame, darunter die Tour mit allen Stationen; freigespielte lassen sich antippen und wieder groß ansehen, mit dem Tag, an dem sie dazukamen. An Tagen mit SCHWER brennt hinter dem Wort ein kleines Pixelfeuer. Nach der Einheit sagt ein Ansager die großen Momente an: neuer Rang, neuer Aufnäher, wieder auf dem Stand vor der Pause, eine runde Marke wie „100 KG“, der Wochenregler auf elf, „FLAWLESS“. Es gibt höchstens eine Ansage je Einheit, und unter Backstage → App lässt sie sich abschalten. Mit „Bewegung reduzieren“ im System gibt es kein Feuer und keinen Sprung. Eigene Pixel-Art, keine fremden Grafiken. |
| Monats-Tour | Jeden Monat drei Ziele aus deinem eigenen Wochenplan: die geplanten Krafteinheiten, die geplanten Fahrten (ohne Rad: vier Tage Jam, Unplugged oder Mobility) und halb so viele saubere Einheiten. Am Ende wartet der Endgegner des Monats, vom Frostriesen im Januar bis zum Krampus im Dezember, mit einer Lebensleiste, die mit jedem erfüllten Ziel ein Drittel verliert. Tage vor der ersten Einheit und in einer Verletzungspause zählen nicht zum Soll. Fällt der Gegner, sagt der Ansager TOUR KOMPLETT; dazu Aufnäher für 1, 3, 6 und 12 besiegte Monate. Die Karte steht im Merch, die Zeile im Wochenkopf. |
| Wochen-Soundcheck | Sonntags für die laufende Woche, montags und dienstags noch für die vergangene: die Zahlen der Woche (Einheiten, Jams, Mobility, Fahrten, Tonnen, saubere Sätze), als Mischpult mit einem Fader je Zahl (gemessen an der eigenen Bestmarke der acht Wochen davor), dazu „Lief gut“, „Hakt“ und drei Vorsätze auf einer Setlist aus Papier. Er liegt als eigene Datei im Datenrepo (soundcheck/JJJJ-Www.json), ohne Netz in der Warteschlange. Die Vorsätze stehen danach im Wochenkopf, frühere Soundchecks in der Tour. Aufnäher für 4 und 12 Wochen in Folge. |
| Abend-Check-in | Eine Ja/Nein-Frage, die du dir selbst stellst (Backstage → Persönlich, etwa „Eiweiß getroffen?“); ohne Frage gibt es keine Karte. Auf Heute zwei Knöpfe, am selben Tag zählt die letzte Antwort. Die Wochenzeile („3 von 4 Tagen“) steht ab dem ersten Ja, die Serie ab zwei Tagen. Die App gibt nichts vor und verknüpft die Antwort nicht mit der Waage; Training ist es auch nicht. |
| Zu zweit trainieren | In der Einheit eincheckt man, mit wem man heute trainiert; in der Pause steht dann „Max ist dran“, und der Knopf heißt „Fertig“ (I go, you go). Den Handschlag machen beide über zwei Links, die sie sich selbst schicken, oder per Einfügen in der App — es gibt keinen Server dazwischen, und im Link stehen nur Kennung, Schritt und Name. Jede Seite führt nur ihre eigene Datei unter zusammen/ im Datenrepo. „Bestätigt“ heißt: beide Telefone waren beteiligt, mehr nicht. Dazu acht Aufnäher (Duett, Faustgruß, Tourpartner 5/15/30, feste Verabredung 2/4/8 Wochen), die erst auftauchen, wenn es eine Verabredung gibt. Gezählt werden Tage und Wochen, kein Vergleich zwischen Personen. |
| Flightcase-Look | Karten mit Kantenschutz an den Ecken wie am Case, Überschriften als Gaffa-Streifen mit Edding-Schrift, das Tageswort in Anton. Beide Schriften liegen im Repo (assets/fonts/, Lizenzen daneben), es wird nichts von außen geladen. |
| Ansage gegen Gefühl | In der Tour: jede Einheit mit beiden Werten, dazu die Trefferquote — Ansage und gefühlte Schwere nebeneinander statt nur behauptet. |
| Wo du schief stehst | Zwölf Kraftverhältnisse gegen Richtwerte und gegen deinen eigenen Stand vor der Pause. Fällt derselbe Lift in mehreren Paaren auf, nennt die App ihn als Ursache und schlägt Zusatzarbeit vor — ein einzelnes schiefes Paar sagt nicht, an welcher Seite es liegt. Verglichen werden nur Werte gleicher Güte. |
| Prüfwerte | Klimmzug, Dip, Front Squat, einarmiges Drücken, Step-Up, einbeiniges Kreuzheben und Farmer's Carry — was das 5×5 nicht selbst erzeugt. Im Backstage eintragen oder im Max-Out messen; ein gemessener Test schlägt die Handeingabe und steht mit Datum im Verlauf. Damit kommen acht weitere Verhältnisse dazu, darunter ob dein Ziehen zu deinem Drücken passt. |
| Wann du wieder da bist | Hochrechnung je Übung aus deiner tatsächlichen Steigerungsrate bis zum Gewicht vor der Pause. „Erreicht" heißt gehoben, nicht zugeteilt. |
| Kraft je Kilo | Arbeitsgewicht geteilt durch Körpergewicht, mit Verlauf. Im Defizit die ehrlichere Zahl — dort ist Halten schon Fortschritt. |
| Wo es klemmt | Plateaus, bevor der Deload-Zähler sie meldet: wie lange ein Gewicht steht, Fehlversuche, und wie viele einzelne Sätze auf dem Ziel lagen. |
| Nach 5×5 | Muss ein Lift zweimal ohne neues Hoch in den Deload, steckt er fest. Beim Start schlägt die App dann den klassischen nächsten Schritt vor: 5×5 → 3×5 → 3×3 (Kreuzheben 1×5 → 1×3), gleiches Gewicht, weiter steigern. Nur mit deiner Zustimmung, als Anpassung im Log und unter Tour → Kraft jederzeit zurückzunehmen. |
| Jam | Fünf Formate, 31 Übungen, Lasten aus dem aktuellen Stand. Nie zwei Langhantelteile. Auf Wunsch zu zweit im Wechsel (I go, you go) an einem Gerät, ohne Check-in: die Anzeige sagt, wer dran ist, mit „Wechsel“ in der Uhrleiste tauscht ihr, und am Ende steht die Bilanz im Log. |
| Skalierung | Jede Übung nennt Alternativen. „Kann ich nicht" nimmt sie dauerhaft raus. |
| Unter Backstage umschaltbar: Oberfläche, Ansage, Meilensteine, Minierfolge und Meldungen. Übungsinhalte und Sprüche bleiben deutsch. |
js/export.js | Einheiten als CSV, sicher gegen Formeln. |
js/feuer.js | Pixelfeuer (Doom-Algorithmus, eigene Umsetzung). |
js/ansager.js | Entscheidet, was nach der Einheit angesagt wird. |
js/sprache.js | Sprachansagen im Kurs: Umbau, Pause, Handwechsel, nächste Übung. |
js/anlaesse.js | Welcher saisonale Banner an welchem Tag gilt (Datumsregeln, Ostern, Rang), dazu der Schalter auf dem Gerät. |
js/soundcheck.js | Wochen-Soundcheck: Kalenderwochen, Fälligkeit, Serie, Faderstand, Bereinigen der Eingaben. |
js/zusammen.js | Zusammen trainieren: Verabredungen, Einladungslinks lesen und bauen, Handschlag, gemeinsame Tage für die Aufnäher. |
js/boot.js | Thema, Speicherumzug und Einbett-Sperre vor dem ersten Bild. |
js/store.js | Datenspeicher: lokal im Browser oder im GitHub-Repo, dieselben Pfade; Offline-Puffer. |
js/lokal.js | Die lokale Ablage: Dateien in IndexedDB. |
js/sicherung.js | Sichern und Einlesen als JSON-Datei, Vereinigung statt Ersetzen. |
js/intervals.js | Liest Fahrten und Form; schreibt Einheiten zurück. |
js/app.js | Oberfläche und Ablauf. |
sw.js | Cacht die App-Hülle. Trainingsdaten bewusst nicht. |
tools/tests.mjs | Führt alle Tests mit Node aus; dasselbe tut die GitHub Action bei jedem Push. |
tools/proben.mjs | Browserproben: die echte App im Chromium, mit gestellter GitHub-API (optional, Playwright). |
tools/pixel.mjs | Baut alle Pixel-Grafiken: die Bögen in assets/pixel/ (aus den Quellbildern in tools/pixel/), Schriftzug und App-Icons (icons/) und die README-Bilder (assets/readme/); --pruefe läuft in der Action. |
tools/pixel-anlaesse.mjs | Zeichnet die Motive der Banner (je zwei Bilder zum Wechseln); pixel.mjs setzt sie zum Bogen zusammen. |
tools/pixel-gitarren.mjs | Zeichnet die zehn Gitarren fürs Rack (Körpermasken, Kopfplatten, Farben); pixel.mjs setzt sie zum Bogen zusammen. |