10 KiB
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
- 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).
- ADHS-freundlich: Niedrigschwellig, wenig Klicks, schnelles Erfassen ("Brain dump"), sofortiges visuelles Feedback (Fälligkeits-Badges: überfällig/bald/ok), keine überladenen Screens.
- 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.
- 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.txtpflegen.
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/<modulname>/) - bringt eigene Models, Routes, Templates mit (Templates unter
templates/<modulname>/) - wird in
app/__init__.pyperapp.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)
- Nutzer gibt E-Mail-Adresse auf
/loginein. - 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).
- Backend generiert 6-stelligen Code, speichert Hash +
expires_at = now + 10min, sendet Code per E-Mail (Betreff klar, kurzer Text, kein HTML-Tracking). - Nutzer landet auf
/verify, gibt Code ein. - Backend prüft: Code korrekt, nicht abgelaufen, nicht bereits benutzt → Login via
Flask-Login (
login_user), Code alsusedmarkieren. - Alte/abgelaufene Codes regelmäßig aufräumen (z.B. bei jedem neuen Code-Request für denselben User).
- 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)
- Projektgerüst (App-Factory, Config,
.env.example,requirements.txt) - Models + DB-Migration (User, LoginCode, Project, Task)
- Auth-Modul (E-Mail-Code-Login, Templates für
login.html/verify.html) - Basis-Layout
base.htmlmit Navigation + Dark-Theme-CSS (aus Prototyp übernehmen) - Modul "Projekte": Routes + Templates, 1:1-Funktionsumfang aus dem HTML-Prototyp
- PDF-Export (projektbasierte To-Do-Liste zum Ausdrucken, fpdf2)
- 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_NAMEbzw. 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)