Das Feld „Name (optional)" stand nur im Dynamisch-Block. Bei einem statischen Code gab es damit keine Moeglichkeit, ihm einen Namen zum Wiederfinden zu geben. Jetzt gilt es in beiden Betriebsarten und tut zweierlei: Es bestimmt den Dateinamen beim Herunterladen — aus „Plakat Eingang" wird qr-plakat-eingang.png statt qr-example-com-plakat.png — und es laesst sich damit ein statischer Code in „Meine Codes" ablegen. Ein abgelegter statischer Code ist ein Schnappschuss, kein steuerbares Ziel. Aenderbar ist nur der Name; Inhalt und Gestaltung bleiben, wie sie beim Ablegen waren, denn genau das steckt im gedruckten Bild. Er bekommt keinen Kurz-Link, ist unter /r nicht erreichbar und zaehlt keine Scans — in der Liste steht dort „statisch" und ein Strich. Wer nach dem Ablegen den Inhalt aendert, bekommt das Ablegen erneut angeboten; der vorherige Eintrag bleibt als eigener Schnappschuss. Dafuer traegt QrCode jetzt `mode`, und `slug` darf leer sein. In PostgreSQL schliessen sich mehrere NULL in einem eindeutigen Index nicht aus, die Bedingung „je Domain eindeutig" gilt fuer dynamische Codes also unveraendert. Refs #2
243 lines
9.8 KiB
Markdown
243 lines
9.8 KiB
Markdown
# Roadmap
|
|
|
|
Was gebaut ist, was als Nächstes kommt und was danach denkbar wäre. Die
|
|
Aufwände sind grobe Einschätzungen, keine Zusagen.
|
|
|
|
---
|
|
|
|
## Gebaut
|
|
|
|
### Version 1 — Grundgerüst (13.08.2026)
|
|
|
|
- Next.js-Anwendung und PostgreSQL als Docker-Compose-Stack, ohne Reverse
|
|
Proxy, Migrationen beim Start
|
|
- QR-Typ-Registry als Dispatch-Tabelle — ein neuer Typ ist ein Modul plus ein
|
|
Formular, ohne Eingriff in den übrigen Code
|
|
- Typ **Website**, statisch und dynamisch, mit Kurz-URL, 302-Weiterleitung und
|
|
Scan-Zähler
|
|
- Gestaltung: Farben mit Kontrastwarnung, Größe, Fehlerkorrektur, Rand
|
|
- Download als PNG und SVG, serverseitig gerendert
|
|
- „Meine Codes“ mit Ziel ändern und Löschen
|
|
- Deutsche Oberfläche, deutsche Fehlermeldungen, Validierung mit Zod
|
|
- Update-Skript für Linux/macOS und Windows
|
|
|
|
### Typen einzeln freigeben (14.08.2026)
|
|
|
|
Ausblenden nicht gebrauchter Typen in der Verwaltung. Bereits erstellte Codes
|
|
eines abgeschalteten Typs funktionieren weiter.
|
|
|
|
### Phase A — acht weitere Typen (14.08.2026)
|
|
|
|
vCard, App-Link, WhatsApp, E-Mail, SMS, Standort, Zahlung (GiroCode und
|
|
Zahlungslink), WLAN.
|
|
|
|
### Phase B1 — Anmeldung, Gruppen, Rollen (14.08.2026)
|
|
|
|
Abschaltbare Anmeldung, Benutzerverwaltung, Gruppen mit den Rollen
|
|
Administrator, Bearbeiter und Betrachter, Sitzungen in der Datenbank,
|
|
scrypt-Passwörter, Sperre nach Fehlversuchen.
|
|
|
|
### Phase B2 — mehrere Domains (14.08.2026)
|
|
|
|
Domains für Kurz-URLs, den Gruppen zugeteilt. Slug je Domain eindeutig,
|
|
Host-Header gegen die registrierten Domains geprüft.
|
|
|
|
### Listenansicht (14.08.2026)
|
|
|
|
„Meine Codes“ als Liste mit Suche, Sortierung und Gruppenfilter — gedacht für
|
|
viele Projekte nebeneinander. Karten bleiben als zweite Ansicht.
|
|
|
|
### Phase C — die letzten sechs Typen (14.08.2026)
|
|
|
|
Mehrere Links, Social Media, Video, PDF, Bild, Feedback. Dazu:
|
|
|
|
- Landingpages als eigene Gattung (`/s/{slug}`), ohne App-Navigation
|
|
- Datei-Upload mit Inhaltsprüfung, Größengrenze und Aufräumen
|
|
- Feedback mit anonymer Erhebung und Auswertung
|
|
|
|
Damit sind **alle 15 vorgesehenen Typen** gebaut.
|
|
|
|
### Single Sign-on (15.08.2026)
|
|
|
|
Anmeldung über Authentik und andere OIDC-Anbieter, mit PKCE und geprüftem
|
|
ID-Token.
|
|
|
|
### Erscheinungsbild (16.08.2026)
|
|
|
|
Name, Logo, Favicon und Akzentfarbe im Admin-Bereich einstellbar. Die Farbe
|
|
wirkt über die Farbvariablen, die Tailwind ohnehin benutzt — deshalb ohne
|
|
Umbau der rund 60 eingefärbten Stellen.
|
|
|
|
### Dark Mode (16.08.2026)
|
|
|
|
Folgt dem Betriebssystem, mit Umschalter für Hell, Dunkel und System.
|
|
Umgesetzt über `light-dark()` statt über `dark:`-Klassen — deshalb ohne
|
|
Änderung an den rund 440 Farbklassen und ohne JavaScript für die Systemwahl.
|
|
|
|
### Sprechende Kurz-Links (17.08.2026)
|
|
|
|
Kurz-Links selbst vergeben und nachträglich ändern, mit `/` als Trenner. Die
|
|
vorherige Adresse bleibt gültig und lässt sich einzeln freigeben — sonst würde
|
|
jedes Umbenennen gedruckte Codes entwerten. Standardmäßig Administratoren
|
|
vorbehalten, per Einstellung für Bearbeiter freigebbar.
|
|
|
|
Schließt [Issue #1](https://git.wilde-server.de/florian.wilde/qrcode-generator/issues/1).
|
|
|
|
### Statische Codes benennen und ablegen (20.08.2026)
|
|
|
|
Das Namensfeld gilt in beiden Betriebsarten. Es bestimmt den Dateinamen beim
|
|
Herunterladen und erlaubt, einen statischen Code in „Meine Codes" abzulegen —
|
|
als Schnappschuss, dessen Inhalt sich nicht mehr ändert.
|
|
|
|
Schließt [Issue #2](https://git.wilde-server.de/florian.wilde/qrcode-generator/issues/2).
|
|
|
|
### Dokumentation (15.08.2026)
|
|
|
|
Bedienungsanleitung mit Bildern, Authentik-Anleitung, Funktionsübersicht.
|
|
Die Bilder erzeugt ein Skript, damit sie nicht veralten.
|
|
|
|
---
|
|
|
|
## Als Nächstes
|
|
|
|
In dieser Reihenfolge. Die Einschätzungen sind grobe Hausnummern für eine
|
|
Person, die den Code kennt.
|
|
|
|
### 1. QR-Typen je Gruppe freigeben · mittel
|
|
|
|
Heute gilt die Freigabe eines Typs für die ganze Installation: Was
|
|
abgeschaltet ist, ist für alle weg. Bei mehreren Gruppen ist das zu grob — die
|
|
Marketingabteilung braucht Social Media, die Werkstatt nur Website und PDF.
|
|
|
|
Geplant: Die Freigabe bekommt eine zweite Dimension. Es bleibt eine globale
|
|
Einstellung als Grundlage, und je Gruppe lässt sich davon abweichen. Wer in
|
|
mehreren Gruppen ist, sieht auf der Startseite die Vereinigung; beim Anlegen
|
|
entscheidet die gewählte Gruppe.
|
|
|
|
Zu klären ist der Fall, in dem ein Typ global aus, in einer Gruppe aber an
|
|
ist — entweder die Gruppe darf das überstimmen, oder die globale Abschaltung
|
|
gewinnt immer. Die zweite Lesart ist die weniger überraschende und
|
|
wahrscheinlich die richtige.
|
|
|
|
Berührt: `QrTypeSetting` (zusammengesetzter Schlüssel aus Typ und Gruppe),
|
|
`src/lib/qr/availability.ts`, die Startseite und die Typ-Verwaltung, die dann
|
|
eine Gruppenauswahl bekommt.
|
|
|
|
### 2. Statistik über die Zeit · mittel
|
|
|
|
Der Zähler weiß heute nur, wie oft und wann zuletzt. Gebraucht wird der
|
|
Verlauf: Wie lief die Kampagne in den ersten Tagen, wann ist Ruhe
|
|
eingekehrt?
|
|
|
|
Geplant: eine Tabelle mit einer Zeile je Code und Tag, dazu ein Diagramm in
|
|
der Codeansicht und die Zahlen der letzten 7, 30 und 365 Tage.
|
|
|
|
Bewusst **ohne** Herkunft, Gerät oder Verweisseite. Ein reiner Tageszähler
|
|
sagt nichts über einzelne Menschen aus und braucht deshalb weder Einwilligung
|
|
noch Löschfristen. Wer mehr will, muss sich mit beidem befassen — das ist eine
|
|
andere Entscheidung als „ein Diagramm wäre schön“.
|
|
|
|
### 3. Papierkorb statt Löschen · klein
|
|
|
|
Heute ist ein gedruckter Code nach einem Fehlklick unwiederbringlich tot,
|
|
samt seiner Dateien und Rückmeldungen.
|
|
|
|
Geplant: Gelöschte Codes 30 Tage aufheben und dann endgültig entfernen. In
|
|
„Meine Codes“ ein Reiter „Papierkorb“ mit Wiederherstellen. Solange ein Code
|
|
im Papierkorb liegt, bleibt sein Slug belegt — sonst könnte ihn ein neuer Code
|
|
bekommen und die gedruckten Codes zeigten plötzlich woandershin.
|
|
|
|
### 4. Logo im QR-Code · mittel
|
|
|
|
Ein kleines Bild in die Mitte setzen, wie man es von Firmen-Codes kennt.
|
|
|
|
Geplant: Upload eines Logos je Code, mittig eingesetzt, mit erzwungener
|
|
Fehlerkorrektur **H** und einer Warnung, sobald zu viel Fläche verdeckt wird.
|
|
|
|
Das ist der Punkt mit dem größten Risiko, etwas Kaputtes auszuliefern: Ein
|
|
Code, der auf dem eigenen Handy noch funktioniert, kann bei anderen
|
|
Scanner-Apps durchfallen. Gehört deshalb nicht ohne eine ehrliche Prüfung mit
|
|
mehreren Geräten und Apps ausgeliefert — und mit einer klaren Obergrenze für
|
|
die verdeckte Fläche.
|
|
|
|
### 5. Ablaufdatum und Zeitsteuerung · mittel
|
|
|
|
Ein Code, der ab einem Datum woandershin führt oder abläuft — für
|
|
Veranstaltungen, Aktionen und Aushänge mit Verfallsdatum.
|
|
|
|
Geplant, in zwei Stufen:
|
|
|
|
- **Ablauf:** ab einem Zeitpunkt zeigt der Code eine erklärende Seite statt
|
|
des Ziels. Wichtig ist der Text — wer davorsteht, soll erfahren, dass die
|
|
Aktion vorbei ist, nicht dass „etwas nicht gefunden“ wurde.
|
|
- **Zeitplan:** mehrere Ziele mit Gültigkeitsfenstern, damit derselbe
|
|
Aufsteller montags auf die Mittagskarte und samstags auf die Veranstaltung
|
|
zeigt.
|
|
|
|
Zu bedenken: Zeitzonen und die Frage, was beim Bearbeiten mit vergangenen
|
|
Fenstern geschieht.
|
|
|
|
---
|
|
|
|
## Später denkbar
|
|
|
|
**Das Fenster der Ersteinrichtung schließen** · klein
|
|
Heute wird das erste Konto ohne jede Legitimation angelegt und ist gleich
|
|
Administrator. Wer die Anwendung öffentlich stellt, bevor er sein Konto
|
|
angelegt hat, kann sie an einen Fremden verlieren. Vorschlag: ein einmaliges
|
|
Token, das beim ersten Start ins Protokoll geschrieben wird und für die
|
|
Ersteinrichtung nötig ist. Klein im Aufwand — und das Erste, was zu tun ist,
|
|
falls die Anwendung je aus dem eigenen Netz herausgeht. Siehe
|
|
[sicherheit.md](sicherheit.md).
|
|
|
|
**Codes exportieren** · klein
|
|
Eine CSV aller Codes einer Gruppe mit Name, Kurz-URL, Ziel und Scans — für
|
|
die Übergabe an eine Druckerei oder die Ablage.
|
|
|
|
**Codes duplizieren** · klein
|
|
„Wie dieser, aber mit anderem Ziel“ — bei vielen ähnlichen Projekten spart
|
|
das jedes Mal ein paar Minuten.
|
|
|
|
**Stapelverarbeitung** · mittel
|
|
Eine CSV hochladen und daraus 200 Codes erzeugen, als ZIP zurück. Sinnvoll,
|
|
sobald jedes Produkt oder jeder Tisch einen eigenen Code bekommt.
|
|
|
|
**Gruppen aus dem Verzeichnis übernehmen** · mittel
|
|
Die OIDC-Anbindung übernimmt heute bewusst nur die Identität. Eine Zuordnung
|
|
von Verzeichnisgruppen zu Gruppen dieser Anwendung ist möglich, braucht aber
|
|
eine klare Regel dafür, was mit von Hand vergebenen Rollen geschieht — sonst
|
|
verliert jemand beim nächsten Anmelden stillschweigend seine Rechte.
|
|
|
|
**Passwortgeschützte Landingpages** · mittel
|
|
Für Unterlagen, die nicht jeder sehen soll, der den Aushang fotografiert.
|
|
Heute ist die Empfehlung klar: Vertrauliches gehört nicht hinter einen
|
|
offenen QR-Code.
|
|
|
|
**Dateien außerhalb der Datenbank** · mittel
|
|
Heute liegen Uploads in PostgreSQL, damit es bei einem Volumen bleibt. Wer
|
|
sehr viele oder sehr große Dateien ablegt, will sie irgendwann auf einem
|
|
Objektspeicher (S3) haben. Der Wechsel betrifft nur `src/lib/uploads.ts` und
|
|
die Auslieferungsroute — aber auch die Sicherungsstrategie.
|
|
|
|
**Erscheinungsbild je Gruppe** · groß
|
|
Seit dem 16.08. lassen sich Name, Logo, Favicon und Farbe für die ganze
|
|
Installation einstellen. Der nächste Schritt wäre, das je Gruppe zu erlauben
|
|
und die Landingpages mit dem Logo der jeweiligen Gruppe zu versehen — damit
|
|
eine gescannte Seite nach der Firma aussieht, der sie gehört. Technisch
|
|
überschaubar, gestalterisch eine eigene Aufgabe; es braucht Grenzen, damit
|
|
nichts Unlesbares entsteht.
|
|
|
|
**Mehrsprachige Oberfläche** · groß
|
|
Die Anwendung ist durchgehend deutsch, auch in den Fehlermeldungen und den
|
|
Landingpages. Eine zweite Sprache berührt jede Datei.
|
|
|
|
---
|
|
|
|
## Wie ein neuer Typ dazukommt
|
|
|
|
Falls doch noch einer fehlt: Er besteht aus einem Modul in
|
|
`src/lib/qr/types/`, einer Formular-Komponente, je einem Registry-Eintrag und
|
|
— wenn er eine eigene Seite braucht — einer Landingpage. Am übrigen Code
|
|
ändert sich nichts. Näheres im [README](../README.md), Abschnitt „Einen
|
|
weiteren Typ ergänzen“.
|