# CLAUDE.md — Projekt-Hub Diese Datei beschreibt den Kontext, die Architektur und die Konventionen für dieses Projekt. Sie dient Claude (und anderen Entwicklern) als Einstiegspunkt, bevor Code geschrieben wird. ## Hintergrund / Idee Der Nutzer hat ADHS und führt ein analoges Bullet Journal (Logbuch, Weekly Bridge, Monthly Log). Projektbezogene Arbeitsaufgaben sollen davon getrennt digital verwaltet werden. Ein erster Prototyp war eine einzelne HTML-Datei mit LocalStorage (Projekte, Aufgaben, Fälligkeitsdaten, Export/Import als JSON). Diese Datei dient als **funktionale Referenz** für Feature-Set und UI/UX — siehe `reference/projekte.html` (wird vom Nutzer bereitgestellt). Das Ziel jetzt: aus dieser Idee eine **Flask-Webapp** machen, die auf einem eigenen VPS läuft (volle Datenhoheit, kein Drittanbieter-Cloud-Dienst). Diese App ist der erste Baustein eines **Hubs**, der später um weitere kleine Apps/Module erweitert wird — alle hinter einem gemeinsamen Login. ## Kernprinzipien 1. **Datenschutz / Selbsthosting**: Alle Daten bleiben auf dem eigenen VPS. Keine externen Tracker, kein CDN-Zwang für kritische Funktionen (Fallback ohne Internet sollte funktionieren oder zumindest nicht hart brechen). 2. **ADHS-freundlich**: Niedrigschwellig, wenig Klicks, schnelles Erfassen ("Brain dump"), sofortiges visuelles Feedback (Fälligkeits-Badges: überfällig/bald/ok), keine überladenen Screens. 3. **Erweiterbarkeit**: Architektur so anlegen, dass weitere "Mini-Apps" als eigene Module/Blueprints unter demselben Login + derselben Navigation ergänzt werden können, ohne den Kern umzubauen. 4. **Einfacher Login**: Kein Passwort. Login per E-Mail-Adresse + zeitlich begrenztem Code (10 Minuten gültig), der per Mail zugeschickt wird ("Magic Code" / OTP-Login). ## Tech-Stack - **Backend**: Python, Flask - **Datenbank**: SQLite (ausreichend für Einzelnutzer/kleine Gruppe; Pfad konfigurierbar, später ggf. auf Postgres migrierbar — daher SQLAlchemy als ORM verwenden) - **Auth**: Flask-Login für Session-Verwaltung + eigene Logik für E-Mail-Code-Versand (Flask-Mail oder smtplib, SMTP-Zugangsdaten über Umgebungsvariablen) - **Frontend**: Server-seitig gerenderte Templates (Jinja2) + minimal JavaScript für interaktive Elemente (Checkbox-Toggle, Filter, evtl. htmx für dynamische Updates ohne vollständigen Page-Reload). Kein schweres SPA-Framework — Ladezeit und Einfachheit haben Priorität. - **Styling**: Eigenes CSS im Stil des Prototyps (Dark Theme, siehe Referenzdatei) als Basis-Theme für den ganzen Hub, das von allen Modulen genutzt wird. - **Deployment**: VPS, lauffähig hinter einem Reverse Proxy (nginx) via gunicorn. `.env`-Datei für Secrets (SMTP, SECRET_KEY, Datenbankpfad). `requirements.txt` pflegen. ## Architektur-Überblick ``` projekt-hub/ ├── app/ │ ├── __init__.py # App-Factory, Extensions-Init, Blueprint-Registrierung │ ├── config.py # Config-Klassen (liest aus .env) │ ├── extensions.py # db, login_manager, mail etc. │ ├── models.py # User, LoginCode (gemeinsame Modelle) │ ├── auth/ # Auth-Modul (Blueprint) │ │ ├── __init__.py │ │ ├── routes.py # /login, /verify, /logout │ │ └── forms.py # E-Mail-Eingabe, Code-Eingabe │ ├── projects/ # Modul 1: Projekte & Aufgaben (aus dem Prototyp) │ │ ├── __init__.py │ │ ├── routes.py │ │ ├── models.py # Project, Task │ │ └── templates/projects/ │ ├── templates/ │ │ ├── base.html # gemeinsames Layout, Navigation, Theme │ │ └── auth/ │ │ ├── login.html │ │ └── verify.html │ └── static/ │ └── css/main.css # Dark-Theme-Basis aus dem Prototyp ├── migrations/ # Flask-Migrate / Alembic ├── instance/ # SQLite-Datei (nicht versionieren) ├── .env.example ├── requirements.txt ├── wsgi.py └── run.py # lokaler Dev-Server ``` ### Erweiterbarkeit für künftige Module Jedes neue Mini-App-Modul: - ist ein eigenes Python-Package mit eigenem Blueprint (`app//`) - bringt eigene Models, Routes, Templates mit (Templates unter `templates//`) - wird in `app/__init__.py` per `app.register_blueprint(...)` eingebunden - erscheint automatisch als Eintrag in der gemeinsamen Navigation (`base.html`), idealerweise über eine zentrale Liste/Registry, die Modulname + URL + Icon enthält - nutzt denselben `current_user` (Flask-Login) — kein eigenes Auth nötig Ziel: ein neues Modul hinzufügen = neuen Ordner anlegen, Blueprint registrieren, Navigationseintrag ergänzen. Kern-App, Auth und Theme bleiben unangetastet. ## Datenmodell (Modul "Projekte") **User** - id - email (unique) - created_at **LoginCode** - id - user_id (FK) - code (6-stellig, numerisch) - created_at - expires_at (created_at + 10 Minuten) - used (bool) **Project** - id - user_id (FK) - name - color (Hex-Wert, aus fester Palette wie im Prototyp) - created_at **Task** - id - user_id (FK) - project_id (FK, nullable — Aufgaben ohne Projekt erlaubt) - text - due_date (nullable) - done (bool, default False) - created_at ## Auth-Flow (E-Mail-Code-Login) 1. Nutzer gibt E-Mail-Adresse auf `/login` ein. 2. Backend prüft, ob User mit dieser E-Mail existiert — falls nicht, wird er angelegt (passwortlose Self-Registration; ggf. später auf Allowlist beschränkbar für Einzelnutzer-Setup). 3. Backend generiert 6-stelligen Code, speichert Hash + `expires_at = now + 10min`, sendet Code per E-Mail (Betreff klar, kurzer Text, kein HTML-Tracking). 4. Nutzer landet auf `/verify`, gibt Code ein. 5. Backend prüft: Code korrekt, nicht abgelaufen, nicht bereits benutzt → Login via Flask-Login (`login_user`), Code als `used` markieren. 6. Alte/abgelaufene Codes regelmäßig aufräumen (z.B. bei jedem neuen Code-Request für denselben User). 7. Rate-Limiting: max. X Code-Anfragen pro E-Mail pro Stunde, um Spam/Missbrauch zu verhindern (z.B. Flask-Limiter). Sicherheitsaspekte: - Code wird gehasht gespeichert (nicht im Klartext in der DB). - Session-Cookie: `Secure`, `HttpOnly`, `SameSite=Lax`. - HTTPS wird vom Reverse Proxy (nginx + Let's Encrypt) terminiert — App selbst geht von HTTPS aus (`PREFERRED_URL_SCHEME = 'https'`). ## Feature-Set Modul "Projekte" (aus dem Prototyp übernehmen) - Projekte anlegen/löschen, mit fester Farbpalette (zyklisch zugewiesen) - Aufgaben anlegen mit: Text, optionalem Projekt, optionalem Fälligkeitsdatum - Aufgaben abhaken (done/undone), löschen - Fälligkeits-Badges: überfällig (rot), diese Woche (orange), normal (grün), kein Datum - Ansicht "Nach Projekt" (gruppiert, mit Klapp-/Zähl-Funktion) + Ansicht "Alle Aufgaben" (gefiltert: alle / offen / überfällig / diese Woche / erledigt) - Statistik-Leiste (offen / erledigt / überfällig / Anzahl Projekte) - Da Daten jetzt serverseitig in SQLite liegen und auf dem VPS gesichert werden, entfällt der JSON-Export/Import als Sync-/Backup-Mechanismus. Stattdessen: **PDF-Export** — eine projektbasierte To-Do-Liste zum Ausdrucken (offene und erledigte Aufgaben, erledigte abgehakt/durchgestrichen, Aufgaben ohne Projekt in eigenem Abschnitt). Erzeugt mit fpdf2 (reines Python, keine System-Abhängigkeiten); DejaVu-Schrift im Repo mitgeliefert für identisches Rendering auf dem VPS. ## Nicht-Ziele (für jetzt) - Keine Multi-Tenant-Mandantentrennung über User hinaus (Familien-/Team-Sharing später, falls gewünscht) - Kein OAuth/Social Login - Kein Offline-First/PWA-Sync (kann später ergänzt werden) - Kein Rich-Text/Markdown in Aufgaben (bewusst simpel halten) ## Nächste Schritte (Vorschlag für Umsetzungsreihenfolge) 1. Projektgerüst (App-Factory, Config, `.env.example`, `requirements.txt`) 2. Models + DB-Migration (User, LoginCode, Project, Task) 3. Auth-Modul (E-Mail-Code-Login, Templates für `login.html` / `verify.html`) 4. Basis-Layout `base.html` mit Navigation + Dark-Theme-CSS (aus Prototyp übernehmen) 5. Modul "Projekte": Routes + Templates, 1:1-Funktionsumfang aus dem HTML-Prototyp 6. PDF-Export (projektbasierte To-Do-Liste zum Ausdrucken, fpdf2) 7. Deployment-Vorbereitung: `wsgi.py`, gunicorn-Konfiguration, Beispiel-nginx-Config, systemd-Service-Datei ## Entscheidungen (geklärt) - **SMTP-Anbieter**: Proton Mail (eigene Adresse). Da Proton Mail Bridge eine Desktop-Anwendung ist und nur mit zahlendem Plan läuft, wird sie testweise auf dem VPS via Docker betrieben (lokaler SMTP-Relay auf `127.0.0.1`). Falls das auf dem Server unzuverlässig läuft, ist ein **Fallback auf einen EU-SMTP-Relay-Dienst** (z.B. Infomaniak, Mailjet EU-Region) als austauschbare Alternative vorgesehen — die App liest SMTP-Host/Port/User/Passwort ausschließlich aus `.env`, sodass der Anbieter ohne Codeänderung wechselbar ist. - **Self-Registration**: Vorerst nur **eine** erlaubte E-Mail-Adresse (Allowlist mit einem Eintrag in `.env`, z.B. `ALLOWED_EMAILS=deine@adresse.com`). Spätere Erweiterung auf mehrere Adressen ist durch eine kommagetrennte Liste oder eigene DB-Tabelle vorbereitet, aber jetzt nicht nötig. - **Domain**: Noch nicht final. App wird so konfiguriert, dass Domain/Host über `.env` (`SERVER_NAME` bzw. Reverse-Proxy-Konfiguration) gesetzt wird. Bis zur Domain-Entscheidung ist die App über IP:Port oder eine Subdomain-Platzhalter erreichbar; Cookie-Settings (`SESSION_COOKIE_DOMAIN`) werden erst final gesetzt, wenn die Domain feststeht. ## Referenzdatei `reference/projekte.html` — der funktionsfähige HTML/JS-Prototyp (Dark Theme, LocalStorage, Export/Import). Dient als Vorlage für: - Farbpalette und CSS-Variablen (Basis für `static/css/main.css`) - UI-Struktur (Stats-Leiste, Formular, Projekt-Karten, Aufgabenliste, Filter-Buttons) - Fälligkeits-Badge-Logik (`dueBadge`-Funktion → als Jinja-Filter oder Python-Helper übernehmen) - Datenmodell-Felder (Project: id/name/color; Task: id/text/project/due/done)