4.2 KiB
4.2 KiB
QR-Tabellen (table.lehrstun.de)
Status
Phase: MVP live auf https://table.lehrstun.de (Admin: /admin/, Basic Auth) Stand: 2026-07-05
Zweck
Kleines selbst gehostetes Tool für den Schuleinsatz: CSV-Tabellen (Stationenlernen, Materiallisten, Linksammlungen) werden hochgeladen und als hübsche statische HTML-Seite veröffentlicht; Link-Spalten bekommen automatisch lokal erzeugte QR-Codes (kein externer API-Call, DSGVO). Dateneingabe bleibt bewusst in Excel/LibreOffice — Austausch ausschließlich über CSV.
Quickstart
cd D:\Claude-Projekte\qr-tabellen
venv\Scripts\python -m flask --app app.main run # Admin: http://localhost:5000/admin/
venv\Scripts\python tests\test_engine.py # Engine-Selbsttest
Architektur
- Python 3.13 + Flask + segno — einzige Abhängigkeiten (Jinja2 kommt mit Flask)
- Kein JS-Framework, keine DB — Ablage im Dateisystem
app/
engine.py — Kern: CSV parsen/validieren, QR-SVGs (segno), HTML rendern (framework-frei)
storage.py — Dateiablage: Schemas, CSV-Versionen, Veröffentlichung
main.py — Flask-Admin: Schema-Designer, Dropzone, Linkliste, Versionen
templates/ — table.html (öffentliche Seite) + admin/*
static/ — table.css (Design-Tokens, wird in Seiten eingebettet) + admin.css
data/tables/<slug>/schema.json + versions/<zeitstempel>.csv (gitignored)
public/<slug>/index.html (gitignored)
tests/test_engine.py — Selbsttest ohne pytest
Datenfluss
- Schema online anlegen (Spalten: text, text_long, number, date, url, rating_5)
- CSV-Vorlage herunterladen (Semikolon + UTF-8-BOM → Excel-tauglich)
- Befüllte CSV in die Dropzone → Zuordnung per Dateiname, sonst Header-Signatur
- Validierung (URLs, Bewertung 1-5, Zahlen); bei Fehlern wird nichts gespeichert
- Version abgelegt + in sich geschlossene HTML-Seite nach
public/<slug>/gerendert
Produktion (live seit 2026-07-05)
- Server: Hetzner,
~/qr-tabellen(Klon von Giteaadmin/qr-tabellen, öffentliches Repo) - Öffentliche Seiten: Nginx statisch aus
/var/www/table(verifiziert: bleiben bei App-Stopp online) - Admin: gunicorn (Port 8010) via systemd
qr-tabellen.service, Nginx Basic Auth unter/admin - Zugangsdaten: lokal in
~/.config/claude-secrets/qr-tabellen.env; Hash in/etc/nginx/htpasswd-table - TLS: certbot (Let's Encrypt), DNS via hetznerdns.py angelegt
- Deploy-Update:
ssh herb@46.225.114.15,cd ~/qr-tabellen && git pull && sudo systemctl restart qr-tabellen
Design
Tokens in table.css (:root-Variablen: Farben, Fonts, QR-Größe, Breite).
Systemfont-Stack mit Source Serif 4 / Fira Sans als Wunschfonts — bei Bedarf
lokal hosten (kein Google-CDN, Schulkontext). Print-Media-Query vorhanden.
Entscheidungen
| Datum | Entscheidung | Begründung |
|---|---|---|
| 2026-07-05 | Python/Flask + segno statt Node | Passt zum Hetzner-Deploy-Muster; csv ist Stdlib, segno erzeugt SVG-QR ohne weitere Deps |
| 2026-07-05 | Nur CSV im MVP, kein XLSX | Excel/LO speichern CSV; spart exceljs/openpyxl komplett |
| 2026-07-05 | Öffentliche Seiten statisch, App nur fürs Admin | Schüler-Traffic trifft nie den Python-Prozess; robust bei App-Ausfall |
| 2026-07-05 | QR-Codes als Inline-SVG in der Seite | Eine Datei pro Tabelle, keine Bild-Assets, skaliert per CSS |
| 2026-07-05 | Versions-Erkennung: Dateiname → Header-Signatur → manuell | Kein Ratespiel; Vorlage heißt schon <slug>.csv |
| 2026-07-05 | Kein Login in der App; Basic Auth via Nginx | Single-Admin, unveröffentlichte Slugs reichen für Schüler |
| 2026-07-05 | CSV-Vorlage mit Semikolon + UTF-8-BOM | Deutsches Excel öffnet sie direkt korrekt |
| 2026-07-05 | Fehlerhafte CSVs werden komplett abgelehnt | Klare Fehlermeldung statt halb veröffentlichter Tabelle |
Blocker
- Keine
Nächste Schritte
- Deployment: DNS
table.lehrstun.de, Gitea-Repo, gunicorn + systemd, Nginx (statisch + /admin Basic Auth), TLS - Demo-Tabelle (
demo-stationenlernen) nach dem Ausprobieren im Admin löschen - Design-Feintuning (Tokens in table.css), ggf. Fonts lokal hosten
- Später: XLSX-Direkt-Upload, QR-Label-Styling, XLSX-Re-Export mit QR-Bildern