PageMark

Anforderungen – Frontend

Projekt: Online Novel Lib Komponente: Frontend (Kotlin Multiplatform) Stand: 23.09.2026

1. Zielsetzung und Kontext

Das Frontend ist die Anwendung, mit der Leser Novels entdecken und kapitelweise lesen, Autoren eigene Novels und Kapitel verfassen und verwalten, und Admins Nutzer sowie Inhalte moderieren. Es wird mit Kotlin Multiplatform (Compose Multiplatform als UI-Framework) gebaut, sodass möglichst viel Logik und UI-Code zwischen den Plattformen geteilt wird. Es spricht ausschließlich über die REST-API mit dem in einem separaten Dokument beschriebenen Spring-Boot-Backend.

2. Zielplattformen

Für die erste Ausbaustufe werden Android, iOS und Web (Compose Multiplatform for Web, Kotlin/Wasm) unterstützt. Ein natives Desktop-Target (Windows/Mac/Linux) ist bewusst nicht im Scope: Das Web-Target deckt denselben Zweck – ein schneller, emulatorloser Blick auf den aktuellen Stand im Browser – ab, ohne einen separaten nativen Build-/Verteilungsweg zu benötigen. Die Architektur (siehe Abschnitt 4) wird so gewählt, dass ein Desktop-Target später ohne größere Umbauten ergänzt werden könnte, indem lediglich ein neues Plattform-Modul (jvmMain/desktopApp) mit den entsprechenden plattformspezifischen Implementierungen hinzukommt.

Android ist die primäre Zielplattform. Da für die Entwicklung aktuell kein Mac zur Verfügung steht, ist Android die einzige Plattform, auf der neue Funktionen laufend real (Emulator/Testgerät) verifiziert werden; das Web-Target dient als sekundäre, ebenfalls sofort lauffähige Möglichkeit für einen schnellen Blick im Browser. iOS-Code wird von Anfang an im gemeinsamen commonMain mitgepflegt und muss kompilieren (compileIosMainKotlinMetadata), bleibt aber bis zur Verfügbarkeit eines Mac mit Xcode zur Laufzeit unverifiziert – geplante Funktionsumfänge dürfen nicht implizit von einer bereits erfolgten iOS-Laufzeitprüfung ausgehen. Sobald ein Mac verfügbar ist, sollten die bis dahin aufgelaufenen Iterationen einmal gebündelt auf dem iOS-Simulator nachverifiziert werden.

3. Technologiestack

Bereich Wahl Anmerkung
UI-Framework Compose Multiplatform Gemeinsamer UI-Code für Android, iOS, Web
Sprache Kotlin  
Netzwerk Ktor Client Multiplatform-HTTP-Client für die REST-Kommunikation mit dem Backend
Serialisierung kotlinx.serialization JSON (de)serialisieren
API-Client openapi-generator (kotlin, library=multiplatform) Erzeugt den Ktor-Client samt Modellen aus dem OpenAPI-Vertrag des Backends – siehe Abschnitt 10.1
Datum/Zeit kotlinx-datetime Von den generierten Modellen für date-time-Felder verwendet
Dependency Injection Koin Gut etabliert im KMP-Umfeld, einfache Einbindung
Navigation Compose Multiplatform Navigation (oder alternativ Voyager) Plattformübergreifendes Screen-Routing
Lokale Datenhaltung/Cache SQLDelight Multiplatform-SQL für lokales Zwischenspeichern gelesener Kapitel und ausstehender Fortschritts-Updates
Sicherer Token-Speicher multiplatform-settings (mit verschlüsseltem Backend je Plattform, wo verfügbar) Android: EncryptedSharedPreferences/DataStore; iOS: Keychain; Web: localStorage (kein OS-Schlüsselbund im Browser verfügbar – siehe Sicherheitshinweis in Abschnitt 10)
Nebenläufigkeit Kotlin Coroutines & Flow  

4. Projektstruktur / Module

Das Projekt folgt dem üblichen KMP-Modulaufbau: commonMain enthält die gesamte gemeinsame Logik – Datenmodelle, Netzwerk-Client, ViewModels/State-Holder, UI-Screens und -Komponenten in Compose Multiplatform. Plattformspezifische Module (androidMain, iosMain, wasmJsMain) enthalten ausschließlich das, was sich nicht teilen lässt: z. B. die konkrete Implementierung des sicheren Token-Speichers, Plattform-Einstiegspunkte (Activity unter Android, Browser-Entry-Point unter Web, entsprechendes iOS-Setup) sowie ggf. plattformspezifischen Dateizugriff für Cover-Bilder. Ziel ist ein möglichst hoher Anteil an commonMain-Code, damit neue Features nur einmal implementiert werden müssen.

5. Rechte im Frontend (Permission-basiert)

Analog zum Backend (siehe Backend-Anforderungen, Abschnitt 3) prüft das Frontend nicht auf feste Rollennamen, sondern auf einzelne Permissions, die nach dem Login aus dem JWT bzw. per GET /user/me geladen werden. Das hat den Vorteil, dass eine später hinzukommende Rolle mit nur einer Teilmenge der Admin-Rechte (z. B. „Moderator”, der nur die Meldungs-Warteschlange sehen darf) automatisch die passenden UI-Teile freischaltet, ohne dass die App-Logik geändert werden muss:

6. Funktionale Anforderungen / Screens

Authentifizierung: Registrierung (E-Mail, Benutzername, Passwort), Login, Logout, automatisches Halten der Session über gespeicherte Tokens, automatisches Erneuern des Access Tokens über den Refresh Token im Hintergrund. Ein „Passwort vergessen”-Flow sowie Social Login sind bewusst nicht Teil der ersten Ausbaustufe.

Katalog/Entdecken: Liste aller veröffentlichten Novels mit Cover, Titel, Kurzbeschreibung, Autor(en), Status, Genre-Tags und Altersfreigabe-Badge (ALL_AGES/TEEN/MATURE); Suche nach Titel; Filterung nach Genre/Status/Altersfreigabe; Paginierung bzw. „mehr laden” beim Scrollen.

Novel-Detailansicht: Vollständige Beschreibung, Anzeige aller zugeordneten Autoren, Altersfreigabe und optionale Inhaltshinweise (Content Warnings), Liste der veröffentlichten Kapitel (mit Nummer und Titel), Button „Zur Bibliothek hinzufügen” bzw. Statusanzeige, falls das Novel bereits in der eigenen Bibliothek ist, ein „Weiterlesen”-Button, der direkt zur zuletzt gelesenen Position springt, sowie ein „Melden”-Button für unangemessene Inhalte oder Urheberrechtsverletzungen (siehe Reporting weiter unten).

Eigene Bibliothek: Liste aller Novels, die der Nutzer seiner Bibliothek hinzugefügt hat, gruppiert oder filterbar nach Lesestatus (liest gerade, abgeschlossen, geplant, abgebrochen), mit Fortschrittsanzeige (z. B. „Kapitel 12 von 30” oder Prozentanzeige) pro Eintrag. Ein DRAFT-Novel kann hier nie erscheinen, auch nicht das eigene (siehe Backend-Anforderungen, Abschnitt 4.5) – ein Autor, der seine unveröffentlichten Novels sehen will, nutzt dafür das Autoren-Dashboard, nicht die Bibliothek.

Leseansicht (Reader): Kapiteltext in gut lesbarer Darstellung, Navigation zum vorherigen/nächsten Kapitel, Einstellungen für Schriftgröße und Farbschema (hell/dunkel/sepia), automatische Fortschrittsspeicherung (siehe Abschnitt 7), sowie eine Melden-Option für das aktuelle Kapitel. Kapitel tragen serverseitig bereits ein accessLevel-Feld (FREE/PREMIUM); die App zeigt aktuell noch keine Kauf-/Bezahllogik an, sollte aber ein PREMIUM-Kapitel bereits optisch kennzeichnen können (z. B. Schloss-Icon), damit eine spätere Einführung kostenpflichtiger Kapitel ohne UI-Konzeptänderung möglich ist.

Autoren-Dashboard: Übersicht der eigenen Novels (inkl. Novels, bei denen man als Co-Autor hinzugefügt wurde), geladen über GET /user/me/novels – dies ist zugleich die einzige Ansicht, in der ein Autor seine eigenen DRAFT-Novels sieht, da die Bibliothek sie kategorisch ausschließt (siehe oben). Mit Möglichkeit, ein neues Novel anzulegen (Titel, Beschreibung, Cover, Genre, Status, Altersfreigabe, optionale Inhaltshinweise) sowie bestehende zu bearbeiten oder zu löschen; pro Novel eine Kapitelliste, die sich wie eine frei sortierbare Liste verhält – ein Kapitel wird per Drag & Drop an eine beliebige Position gezogen, das Frontend meldet dabei nur, hinter welchem Nachbar-Kapitel es jetzt stehen soll (siehe Backend-Anforderungen, PUT /novels/{novelId}/chapters/{chapterId}/position), die angezeigte Kapitelnummer kommt danach automatisch neu vom Server und muss clientseitig nicht selbst berechnet werden; außerdem können Kapitel angelegt, als Entwurf gespeichert oder veröffentlicht werden; zusätzlich eine Verwaltung der zugeordneten Autoren (Liste, weiteren Autor per Benutzername/E-Mail hinzufügen, Autor entfernen).

Kapitel-Editor: Eingebauter Text-Editor (Markdown oder einfacher Rich-Text, der intern als Markdown gespeichert wird) zum Schreiben und Bearbeiten von Kapiteln, mit Titel-Feld, Speichern-als-Entwurf- und Veröffentlichen-Aktion sowie einer Live- oder Vorschau-Ansicht, wie das Kapitel später für Leser aussieht.

Admin-Bereich: In einzelne, permission-gesteuerte Teilbereiche gegliedert (siehe Abschnitt 5): Nutzerliste mit Möglichkeit, Accounts zu sperren (USER_MANAGE) bzw. Rollen zuzuweisen/zu entziehen (ROLE_MANAGE); Übersicht/Suche über alle Novels mit Möglichkeit, einzelne Novels oder Kapitel zu entfernen (NOVEL_EDIT_ANY/CHAPTER_EDIT_ANY); eine Moderationswarteschlange (REPORT_REVIEW), die offene Meldungen (Reports) aus Abschnitt „Melden” auflistet und pro Meldung erlaubt, sie abzulehnen oder eine Aktion (Inhalt/Nutzer sperren) zu vermerken.

Melden (Reporting): Ein einfaches Formular (Grund aus einer festen Auswahl wie Urheberrecht, unangemessener Inhalt, Spam, Sonstiges, plus optionaler Freitext), erreichbar über den „Melden”-Button auf Novel-Detailseite, in der Leseansicht (bezogen auf das aktuelle Kapitel) und auf Autoren-/Nutzerprofilen. Nach dem Absenden erhält der Nutzer eine Bestätigung; der weitere Bearbeitungsstatus wird nicht an den meldenden Nutzer zurückgemeldet, sondern landet in der Admin-Moderationswarteschlange.

Einstellungen/Profil: Anzeigename ändern, Passwort ändern, Logout, App-weites Farbschema.

7. Lesefortschritt und geräteübergreifende Synchronisation

Damit ein Nutzer auf einem anderen Gerät oder Browser genau dort weiterlesen kann, wo er aufgehört hat, speichert das Frontend den Fortschritt nicht nur lokal, sondern sendet ihn an das Backend (PUT /user/me/library/{novelId}/progress, siehe Backend-Anforderungen). Ein Update wird ausgelöst, wenn der Nutzer ein Kapitel verlässt, die App/den Screen verlässt oder in regelmäßigen Abständen während des Lesens (z. B. alle 30 Sekunden bei aktivem Scrollen). Beim Öffnen eines Novels wird zunächst der serverseitig gespeicherte Fortschritt geladen, um die Leseansicht an der richtigen Stelle zu öffnen. Ist das Gerät offline, wird das Update lokal (SQLDelight) zwischengespeichert und beim nächsten Verbindungsaufbau nachgereicht.

8. Offline-Verhalten und lokales Caching

Bereits geladene Kapitel werden lokal zwischengespeichert (SQLDelight), damit ein erneutes Öffnen ohne Netzwerkzugriff funktioniert und die App insgesamt reaktionsschneller wirkt. Ausstehende, noch nicht an das Backend übermittelte Fortschritts-Updates werden ebenfalls lokal vorgehalten und bei Konnektivität synchronisiert. Ein vollständiger Offline-Download ganzer Novels ist für die erste Ausbaustufe nicht vorgesehen (siehe Abschnitt 14).

9. State Management

Jeder Screen besitzt einen State-Holder/ViewModel in commonMain, der über Kotlin StateFlow einen unidirektionalen Datenfluss (State nach außen, Events/Intents nach innen) umsetzt. Dadurch bleibt die UI-Schicht (Compose) weitgehend zustandslos und dieselbe Logik kann auf allen Plattformen wiederverwendet werden.

10. Netzwerk- und Auth-Handling

Der Ktor-Client wird pro Umgebung (lokal/später Produktion) mit einer konfigurierbaren Basis-URL initialisiert; für die lokale Entwicklung ergeben sich je nach Plattform unterschiedliche Adressen für das lokal laufende Backend (z. B. http://localhost:8080 für Web/iOS-Simulator, http://10.0.2.2:8080 für den Android-Emulator). Da Web-Dev-Server und Backend auf unterschiedlichen Ports (= unterschiedlichen Origins) laufen, muss das Backend für lokale Entwicklung CORS-Header für die Origin des Web-Dev-Servers senden, sonst blockt die Same-Origin-Policy des Browsers alle Requests clientseitig, bevor der Auth-Interceptor überhaupt greift. Ein Auth-Interceptor fügt automatisch den Access Token an ausgehende Requests an und erneuert ihn bei Ablauf transparent über den Refresh Token; schlägt auch das fehl, wird der Nutzer zum Login zurückgeführt. Netzwerkfehler werden einheitlich behandelt und dem Nutzer verständlich angezeigt (z. B. „Keine Verbindung zum Server”). Da das Backend produktiv hochverfügbar mit mehreren Instanzen hinter einem Load Balancer betrieben wird (siehe Backend-Anforderungen), können bei Deployments vereinzelt kurzzeitige Fehler auftreten; für Requests wird daher eine einfache automatische Wiederholung bei transienten Fehlern (z. B. HTTP 502/503 oder Verbindungsabbruch) mit ein bis zwei Versuchen vorgesehen, bevor dem Nutzer ein Fehler angezeigt wird.

10.1 Generierter API-Client (Contract-First)

Der API-Client wird nicht von Hand geschrieben, sondern aus dem OpenAPI-Vertrag des Backends generiert (api/openapi.yaml im Backend-Repository, siehe Backend-Anforderungen, Abschnitt 5.1). Das Backend generiert aus derselben Datei seine Server-Interfaces, sodass Client und Server nicht auseinanderlaufen können: Feldnamen, Pflichtfelder, Enum-Werte und Statuscodes stammen auf beiden Seiten aus einer einzigen Quelle.

Konkret bedeutet das für dieses Projekt:

11. UX/Design

Empfohlen wird ein Material-3-basiertes Design über Compose Multiplatform als konsistente Basis auf allen Plattformen, mit Anpassungen für größere Bildschirme im Web-Browser (z. B. mehrspaltige Katalogansicht, breitere Leseansicht mit begrenzter Textbreite für Lesbarkeit) gegenüber der kompakteren mobilen Darstellung. Eine detaillierte visuelle Gestaltung (Farbschema, Typografie) wird in einem separaten Design-Schritt festgelegt und ist nicht Gegenstand dieses Anforderungsdokuments.

12. Nicht-funktionale Anforderungen

Lange Kapiteltexte werden performant dargestellt (Lazy Loading langer Textabschnitte statt Rendern des gesamten Kapitels auf einmal, falls nötig); die Schriftgröße ist skalierbar, um unterschiedlichen Lesebedürfnissen gerecht zu werden; gemeinsame Logik in commonMain wird mit Unit-Tests abgedeckt, plattformspezifische Teile nach Bedarf ergänzend mit UI-Tests.

13. Lokales Setup

Die Entwicklung erfolgt in Android Studio mit installiertem Kotlin-Multiplatform-Plugin. Für Android wird ein Emulator oder ein Testgerät benötigt; da aktuell kein Mac zur Verfügung steht, ist Android die primäre Plattform für die tägliche Entwicklung und Verifikation. Das Web-Target lässt sich direkt über die Gradle-Aufgabe wasmJsBrowserDevelopmentRun im Browser starten (öffnet automatisch einen lokalen Dev-Server) und eignet sich als sekundäre Möglichkeit für schnelle Entwicklungszyklen ohne Emulator. Für das iOS-Target werden zusätzlich Xcode und ein Mac vorausgesetzt; bis ein Mac verfügbar ist, beschränkt sich die Verifikation auf das Kompilieren des gemeinsamen Codes (./gradlew :shared:compileIosMainKotlinMetadata), ohne Laufzeittest auf einem Simulator/Gerät. In allen Fällen zeigt die App im lokalen Entwicklungsmodus auf das lokal laufende Spring-Boot-Backend (siehe Backend-Anforderungen, Abschnitt „Lokales Setup”) – für das Web-Target muss dessen CORS-Konfiguration die Origin des Dev-Servers erlauben (siehe Abschnitt 10).

14. Offene Punkte / spätere Erweiterungen

Folgende Punkte sind bewusst nicht Teil der ersten Ausbaustufe: natives Desktop-Target (Windows/Mac/Linux) – ursprünglich vorgesehen, zugunsten des Web-Targets (schnellerer Blick ins UI ohne Emulator, kein separates natives Artefakt) aus dem Scope genommen, siehe Abschnitt 2; OAuth-/Social-Login-UI (sobald backendseitig verfügbar); vollständiger Offline-Download ganzer Novels statt nur einzelner bereits gelesener Kapitel; Kommentare und Bewertungen zu Novels/Kapiteln in der UI; Push-Benachrichtigungen bei neuen Kapiteln abonnierter Novels; „Passwort vergessen”-Flow.