Sprint 5 abgeschlossen · v0.5.0 Full-Stack SaaS

STUDYNEXUS

Eine Plattform, die kein HsH-Student hatte.
Gebaut von einem, der sie selbst brauchte.

Deep Dive

Chapter I: The Origin

Aus echter Frustration wird echtes Produkt.

Sprint 5 vollständig abgeschlossen — 9 Sprints, 17 Migrationen, 122/122 Tests bestanden, 0 TypeScript-Fehler. Die Case Study spiegelt den aktuellen Stand wider.

Studium organisieren ist ein Chaos

Jeder HS Hannover Student kennt das: QIS, Moodle, Excel, Notizbuch – und trotzdem verliert man den Überblick.

Das ist kein Komfortproblem – es ist ein Systemfehler.

  • Keine zentrale Anlaufstelle für Studienfortschritt
  • ECTS manuell in Excel nachpflegen
  • Prüfungstermine über mehrere Systeme verteilt
  • GPA mit dem Taschenrechner ausrechnen
  • Stundenplan-Kollisionen erst im Hörsaal bemerken
student_tools.sh

# Aktuelle Realität an der HsH

$ open QIS.exe && open moodle.hs-hannover.de
$ open "ECTS_Tracking_v3_FINAL.xlsx"
$ grep -r "Prüfungstermin" ~/Desktop/notizen/

# Die StudyNexus Lösung

yusef@studynexus:~$ docker compose up --build
[✓] frontend started on :3000
[✓] backend started on :8000
[✓] postgres ready — migrations applied
[READY] StudyNexus is running.

Platform Scope

📋
Studienplan & GPA
Prüfungsordnung eingebaut · ECTS-gewichtet
📅
Schedule Board
15-Min CSS Grid · Kollisionserkennung
📌
Kanban Board
Drag & Drop · Persistent in DB
🔐
HsH-Only Zugang
@stud.hs-hannover.de · Email-verifiziert

Ein Betriebssystem fürs Studium.

StudyNexus ist keine weitere Todo-App. Es ist ein vollständiges Studien-Betriebssystem.

Der Zugang ist absichtlich exklusiv.

Full-Stack MVP läuft bereits vollständig.

200+

Source Files
(Frontend + Backend)

17

Alembic
Migrations

22+

Architecture Decision
Records (ADRs)

122

Backend Tests
alle grün

37

BIN-Module
vollständig seeded

5

Docker Services
(Compose Stack)

Chapter II: System Architecture

Fünf Container. Eine kohärente Plattform.

Frontend & Backend. Ein Repository.

Frontend (Next.js) und Backend (FastAPI) leben im selben Repository.

Jede Änderung am API-Contract ist sofort im Frontend sichtbar.

📁 studynexus/ ├── 📁 frontend/ // Next.js 14 │ ├── 📁 src/app/[locale]/ │ ├── 📁 src/components/ │ └── 📄 package.json ├── 📁 backend/ // FastAPI │ ├── 📁 app/routers/ │ ├── 📁 app/models/ │ └── 📄 requirements.txt ├── 📄 docker-compose.yml └── 📄 .env

Der Weg einer Anfrage

Jede Mutation durchläuft eine sichere Pipeline.

Browser
React UI
TanStack Query
Next.js
API Route
Proxy + CSRF
FastAPI
Backend
JWT + Pydantic
PostgreSQL
Database
SQLAlchemy ORM
Redis
Cache
Sessions

Docker Compose: Fünf Services

Die gesamte Infrastruktur startet mit einem einzigen Befehl.

PostgreSQL und Redis haben eigene Health-Checks.

bash
$ docker compose up --build
✓ db healthy (postgres:16)
✓ redis healthy (redis:7-alpine)
✓ backend started → :8000
✓ frontend started → :3000
✓ adminer started → :8080
frontend :3000 Next.js 14 · App Router Node
backend :8000 FastAPI · Uvicorn · ASGI Python
db :5432 PostgreSQL 16-alpine Health ✓
redis :6379 Redis 7-alpine · Sessions Health ✓
adminer :8080 DB Admin UI · Dev only Tool

Chapter III: Engineering Decisions

22+ Architecture Decision Records. Hier sind die prägendsten.

Architektur-Entscheidungen sollten dokumentiert sein — nicht nur was, sondern warum. Und welche Alternativen abgelehnt wurden.

ADR-01

FastAPI statt Django

Django ist das 'sichere' Python-Framework. FastAPI ist das richtige.

async-nativePydantic v2OpenAPI /docsKI-ready
ADR-03

httpOnly Cookies statt localStorage

JWT in localStorage speichern ist eine klassische XSS-Schwachstelle.

XSS-sicherhttpOnlySameSite=LaxSecure
ADR-02

bcrypt direkt – kein passlib

passlib ist de facto unmaintained. Letzte Version 2022.

bcrypt 4.1.3kein passlibPython 3.13+ safe
ADR-12

CSRF via Custom Header

Klassisches CSRF-Token-Management benötigt Server-State. Stattdessen x-studynexus-client: true.

statelessCORS-PreflightOrigin-Check
ADR-07

HsH-Only Strategie

Die Beschränkung auf @stud.hs-hannover.de ist kein Kompromiss – sie ist ein Design-Entscheid.

@stud.hs-hannover.deechte Prüfungsordnungverifizierte Communitykeine Fake-Daten
ADR-019

Redis für Admin-Session-Tokens

JWT ist nicht server-seitig invalidierbar. Für Admin-Aktionen (Delete, Archive, Reset) brauchen wir einen Token, den wir sofort sperren können. Redis mit 15-Minuten-TTL – das Sudo-Konzept für das Web.

server-side invalidierbar15min TTLRedis.get/setex/delete
ADR-021

is_admin im JWT-Payload

Next.js Middleware läuft in der Edge Runtime – kein Datenbankzugriff möglich. is_admin: true direkt im JWT ermöglicht Admin-Route-Guards ohne DB-Abfrage und ohne latency.

Edge Runtimezero DB-latencyatob() + Base64url

Chapter IV: Feature Deep-Dive

Was die Plattform heute kann.

Mission Control

Das Herzstück: Mission Control Dashboard

Der erste Blick nach dem Login. Echtzeit aus der Datenbank – kein Caching.

Jedes Widget ist funktional und reaktiv.

  • GPA-Tracker mit ECTS-gewichteter Echtzeit-Berechnung
  • Exam Countdown mit Pulsier-Animation (< 14 Tage=rot)
  • Daily Focus: heute's Events, automatischer Wechsel nach 20 Uhr
  • Smart Timeline: aufgaben-intelligente Sortierung nach Fälligkeit
Task Management

Kanban Board mit echtem Drag & Drop

@dnd-kit v6 als Fundament. Vier Spalten, Prioritäten, Modul-Verknüpfung.

Vollständig persistent – DB-write bei jedem Drop.

To DoIn ProgressExam ReadyDone LOW · MED · HIGHAbgabe-Flag 📄@dnd-kit v6
Schedule Board

15-Minuten CSS-Grid Engine

Kein Table-Layout. Ein echtes CSS Grid mit 15-Min-Auflösung, Echtzeit-Linie und HTTP 409 Kollisionserkennung.

Semester-Binding. Ghosting-Modus. Mobile Agenda View.

LECTUREEXERCISETUTORIALSEMINAR EXAMFOCUSWORKLIFE +2 mehr
Studienplan

Visueller Studienplan

Module in Semester-Spalten, Drag & Drop, ECTS-Berechnung, echte HsH-Prüfungsordnung.

  • PFLICHT-Module automatisch geladen
  • WAHLPFLICHT & ERGÄNZEND manuell hinzufügbar
  • Drag & Drop zwischen Semestern via @dnd-kit
  • ECTS-Summe pro Spalte live berechnet
Milestone Tracker (Sprint 4)

MilestoneWidget — §6 PO live überwacht

Das Dashboard hat ein neues Sidebar-Widget, das die BIN-Prüfungsordnung §6 in Echtzeit auswertet: Welche Semester sind abgeschlossen? Ist die Vorprüfung bestanden?

  • Sem 1 complete: alle 6 Module BIN-100..116
  • Vorprüfung: alle 17 Module Sem 1–3 bestanden
  • BA-Zulassung: Vorprüfung + ≥ 134 ECTS
  • Live-Fortschrittsbalken per Milestone
Admin Panel (Sprint 5)

Enterprise Admin — 14 Seiten, 35+ Endpunkte

Ein vollständiges Admin-Control-Center: User-Management, Prüfungsordnungs-Verwaltung, Analytics-Dashboard, Audit-Log und JSON-Import – komplett in 2 Tagen geliefert.

Two-Layer AuthAudit-LogRecharts AdminDataTable<T>Soft DeleteJSON-Import
PO-Übersicht (Sprint 4)

Studienordnung auf einen Blick

Eine eigene Dashboard-Seite, die alle relevanten PO-Regeln darstellt: Zulassungsregeln §6, Notenscala §10, Wiederholungsregeln §11 – mit Live-Status-Badges direkt aus der Datenbank.

  • Programm-aware: erkennt BIN via API-Response
  • Prüfungsarten PX / EA / R / BAA+Ko farbcodiert
  • BA-Zulassung: Live-ECTS-Fortschrittsbalken
  • Kein Hardcode – Sprint 7 fügt weitere POs hinzu

Chapter V: BIN Prüfungsordnung

3 PDFs. 37 Module. Alle §6-Regeln automatisch abgebildet.

Aus echten Dokumenten gebaut

Keine Placeholder-Daten. Alle 37 BIN-Module wurden direkt aus drei offiziellen HsH-Dokumenten extrahiert und in die Datenbank überführt.

PO BIN 2019
9 Seiten
  • §5 — Modulstruktur Abschnitt 1 + 2
  • §6 — Zulassungs- & Voraussetzungsregeln
  • Anlage B1/B2 — vollständige Modullisten
ATPO-FIV 2025
20 Seiten
  • §7 — Prüfungsarten (PX, EA, R, BAA+Ko)
  • §10 — 11 offizielle HsH-Noten
  • §11 — Wiederholungsregeln (max. 3 Versuche)
Modulhandbuch BIN 19WS
76 Seiten
  • SWS pro Modul (Semesterwochenstunden)
  • Prüfungsarten je Modul
  • 37 vollständige Modulbeschreibungen

Vier Typen. Direkt aus ATPO-FIV §7.

Jedes der 37 BIN-Module trägt die offizielle Prüfungsart aus dem Modulhandbuch – persistent in der Datenbank, farbcodiert in der UI.

Eine Pydantic-Validierung stellt sicher, dass nur die 11 offiziellen HsH-Noten eingetragen werden können. HTTP 422 bei ungültiger Note.

PX · 26 Module
EA · 3 Module
R · 1 Modul
BAA+Ko · 1 Modul

§6 ZULASSUNGSREGELN — VOLLSTÄNDIG IMPLEMENTIERT

Module Voraussetzung Typ
BIN-200..204 Semester 1 abgeschlossen SEM_COMPLETE
BIN-206, BIN-208 Vorprüfung bestanden (Sem 1–3) SEM_COMPLETE
BIN-211..219 (WP) Semester 1+2 abgeschlossen SEM_COMPLETE
BIN-210 Vorprüfung + ≥ 134 ECTS ECTS_THRESHOLD

Studienfortschritt nach §6 — live

GET /me/stats liefert 8 neue Felder. Das Dashboard-Widget wertet sie in Echtzeit aus. Kein Polling – der Status wird beim Page-Load berechnet.

Semester 1 complete
sem1_complete: true
Semester 2 complete
sem2_complete: true
Vorprüfung bestanden
vorpruefung_bestanden: true
BA-Zulassung
ba_zulassung_eligible: false

Chapter VI: Security by Design

Security ist kein Nachgedanke. Security ist Architektur.

CSRF Protection

Stateless CSRF via Custom Header

Jede mutierende Anfrage trägt x-studynexus-client: true. Cross-Origin-Requests dürfen ohne CORS-Preflight keine Custom Headers setzen.

Request
Check Header
Check Origin
✓ Allow
Authentication

JWT in httpOnly Cookies

Der JWT-Token lebt ausschließlich in einem httpOnly Cookie. JavaScript kann diesen Cookie nicht auslesen.

Set-Cookie: token=eyJ...
HttpOnly; Secure; SameSite=Lax
Path=/; Max-Age=604800 (7d)
Verification

6-Digit Email Verification

6-stelliger Code via Resend API, 15-Minuten-Ablauf, nur @stud.hs-hannover.de.

Register
6-digit Email
Verify (15min)
Active
Data Isolation

Row-Level User Isolation

Jede Datenbank-Query filtert by user_id. Kein separates Permissions-System – das ORM erzwingt die Isolation strukturell.

tasks.py
db.query(Task)
  .filter(Task.user_id == current_user.id)
  .all()
Admin Two-Layer Auth (ADR-019)

Sudo-Konzept: Lesen vs. Zerstören

Ein gestohlener Admin-JWT allein kann keinen Schaden anrichten. Destruktive Operationen erfordern einen zweiten Faktor – einen kurzlebigen Redis-Token, der durch Passwort-Re-Verifikation ausgestellt wird.

Layer 1 — get_admin_user

JWT-basierter Admin-Check

is_admin: true im JWT-Payload (ADR-021). Edge-Runtime kompatibel – kein DB-Lookup, zero latency. Reicht für alle lesenden Admin-Operationen.

GET /admin/users GET /admin/analytics GET /admin/audit-log
Layer 2 — get_verified_admin

Redis Session Token (Sudo)

Admin gibt Passwort erneut ein → Redis-Token mit 15-Min-TTL. Nur dieser Token schaltet destruktive Ops frei. Sofort invalidierbar – kein JWT-Expiry abwarten.

DELETE user ARCHIVE module RESET password

Chapter VII: Admin Panel

Enterprise Control Center. Geplant für eine Woche. Geliefert in zwei Tagen.

Sprint 5 — Delivery Metrics (2026-05-09 bis 2026-05-10)
2 Tage
14 Admin-Seiten
35+ Endpunkte
122 Tests grün
0 TS-Fehler

Was das Admin Panel kann

01 — Analytics

Dashboard & KPI

13-Felder-KPI-Response, Wachstums-Chart (Recharts LineChart, 7d/30d/90d/1y), User-Segmentierung, DB-Größe via pg_database_size().

RechartsResponsiveContainerPostgreSQL
02 — User Management

Vollständiger User-Zugriff

Paginated Liste (25/Seite), 5 Filter-Tabs, Suche über Email+Name, PATCH aller Felder, Password-Reset, Hard Delete mit Begründungspflicht.

AdminDataTable<T>debounced Search350ms
03 — PO-Verwaltung

Hochschule → Modul → Voraussetzung

6 Router-Dateien, ~30 Endpunkte. Soft Delete auf POs/Modulen (Bestandsschutz), Hard Delete auf Hochschulen/Fakultäten.

Soft DeleteJSON-Import (500 Module)Duplikat-Skip
04 — Audit-Log

Lückenlos seit Phase 2

Jede Admin-Mutation seit dem ersten Tag protokolliert. Timeline-Layout, ActionBadge mit 8 Farb-Varianten, DiffBlock (old→new Diff, Strikethrough für entfernte Werte).

DiffBlockActionBadgefilter: entity/action/date
05 — Import-System

JSON-Bulk-Import bis 500 Module

Validate → Preview (erste 10) → POST → Ergebnis. Idempotent via kuerzel-Lookup in derselben PO. PDF-Placeholder für Sprint 7 (ML/NLP).

idempotentPreview-StepAdmin-Session-Guard
06 — System & Health

Echtzeit-Systemstatus

Overall-Badge (ok/degraded/down), ServiceBadge pro Service (DB-Ping + Redis.ping), DB-Version + Größe, Auto-Refresh alle 60 Sekunden.

health checkRedis.pingauto-refresh 60s

AdminDataTable<T> — eine Komponente für alle Listen

Statt 6 separate Tabellen-Implementierungen: eine generische TypeScript-Komponente. Column-Sort, debounced Search (350ms), server-side Pagination, hideOnMobile per Spalte — alles konfigurierbar über Props.

22 neue TypeScript-Interfaces, 11 neue TanStack Query Hooks, adminFetch.ts als dünner Wrapper: kein direktes fetch(), zentrale Header-Logik, 204-Handling.

strict: true0 TS-Fehler22 Interfaces11 Hooks~400 i18n-Keys
pytest tests/ -q
test_admin_auth.py·······7 ✓ test_admin_users.py··········10 ✓ test_admin_po.py················16 ✓ test_admin_analytics.py············12 ✓ test_admin_audit_log.py···········11 ✓ test_auth.py········8 ✓ test_gpa.py··············14 ✓ test_grades.py············12 ✓ test_health.py··2 ✓ test_stats.py·····5 ✓ test_study_plan.py···············15 ✓ test_universities.py··········10 ✓
122 passed in 2.34s

Chapter VIII: Database Architecture

12+ Tabellen. 17 Alembic-Migrationen. Vollständige Hochschul-Hierarchie.

Von der Hochschule zum einzelnen Modul

Das Datenmodell bildet die echte Hochschulhierarchie ab.

9 SQLAlchemy-Modelle mit UUID Primary Keys und PostgreSQL-native ENUMs.

University name, kuerzel, stadt
└── FK ──
Faculty name, kuerzel
└── FK ──
Program abschluss, gesamt_ects
└── FK ──
ExamRegulation version, gueltig_ab
└── FK ──
Module ects, modul_typ, gewichtung
└── FK (user) ──
StudentModule status, note, semester

Gewichtete Note – wie an echten Hochschulen

Der GPA wird nicht einfach gemittelt – ECTS-basierte Gewichtung.

GPA_ALGORITHM · gpa_service.py
GPA  = 
Σ ( Note × ECTS × Gewichtung )
Σ ( ECTS × Gewichtung )
Nur bestandene (status=PASSED), benotete (ist_benotet=true) Module fließen ein.

17 Alembic Migrations – Jeder Schritt versioniert

Keine manuellen SQL-Änderungen – jede Schemaänderung ist versioniert, reversibel und auf jedem Environment reproduzierbar.

Sprints 1–3 legten das Fundament (0001–0011). Sprint 4 ergänzte die BIN-PO-Daten (0012–0014). Sprint 5 lieferte die Admin-Infrastruktur (0015–0017).

001 · Create users table
UUID PK, email, hashed_password, is_verified
002 · Study plan tables
University → Faculty → Program → ExamReg → Module
003–005 · Module data, email verification, Tasks+Events
Kanban & Schedule Board foundation
006–009 · Profil-Felder, Semester-Binding
matrikelnummer, FOCUS-Typ, birth_date, hochschule
010–011 · Studienplan + BIN-Full-Seed
parent_student_module, 37 BIN-Module komplett
012 · pruefungsart + sws
Sprint 4 — alle BIN-Module mit Prüfungsart aus ATPO-FIV §7
013 · module_prerequisites
Sprint 4 — §6-Voraussetzungen: SEM_COMPLETE, ECTS_THRESHOLD
014 · BIN-209 gewichtung fix
Sprint 4 — Datenfehler: 1.0 → 1.5 (Anlage B2 PO BIN)
015 · Admin-Felder auf users
Sprint 5 — is_admin, last_login_at, admin_notes
016 · admin_audit_logs Tabelle
Sprint 5 — entity_type, action, admin_id, diff_snapshot (3 Indizes)
017 · Soft-Delete-Felder
Sprint 5 — is_archived, archive_reason auf Module/Programs/ExamRegs

Chapter IX: Sprint-Roadmap

Wo das Projekt steht. Wohin es geht.

Sprint 1-2 ✓ Abgeschlossen

Foundation: Auth, DB & Docker

JWT Authentication, PostgreSQL-Schema, Docker Compose, Email-Verifikation, Studienplan-CRUD.

Sprint 3.x ✓ Abgeschlossen

Mission Control & Mobile

Kanban Board, Schedule Board (15-Min Grid), Dashboard Widgets, Mobile FAB, Agenda View, TanStack Query, i18n DE/EN.

Sprint 4 ✓ Abgeschlossen

BIN Prüfungsordnung Integration

37 BIN-Module aus 3 PDFs, Prüfungsart-System, §6-Voraussetzungen, MilestoneWidget, PO-Übersicht-Seite, GPA-Fix BIN-209.

Sprint 5 ✓ Abgeschlossen

Admin Panel — Enterprise Control Center

14 Admin-Seiten, 35+ Endpunkte, Two-Layer Auth, Audit-Log, Analytics (Recharts), JSON-Import, 122/122 Tests.

Sprint 6 — In Planung

Security Audit & Email-Templates

Admin-API-Rate-Limiting, Toast-Notifications bei API-Errors, E-Mail-Templates für Passwort-Reset, UI-Polishing.

v1.0 — Ziel

Production Launch für die HsH

Öffentlicher Launch für alle HS Hannover Studierenden. Onboarding-Flow mit vorausgefüllten POs. Gamification: XP, Badges, Streaks.

Ein Projekt
in Bewegung.

StudyNexus ist nicht fertig – und das ist genau der Punkt.