# Vermögen — Vermögens- und Budget-Tracker Implementation Plan

> **Für Hermes:** Nutze subagent-driven-development Skill um diesen Plan Task für Task umzusetzen.

**Ziel:** Eine selbst-gehostete Web-App (Docker auf ZimaOS), mit der Ahmed Zeyd Aytac und seine Frau Talla ihr Vermögen (Gold, Silber, Krypto, ETFs, Bargeld) und monatliches Budget tracken können. Gemeinsame Ansicht mit Basic Auth, Stripe Link-inspiriertes Design mit Lora-Schrift.

**Architektur:** FastAPI-Backend + SQLite-Datenbank + Single-File HTML/CSS/JS-Frontend. Docker-Container mit Volume-Mount auf HDD für Datenpersistenz. Kein Node.js, kein Build-Step.

**Tech Stack:** Python 3.11, FastAPI, uvicorn, SQLite (über sqlite3 stdlib), Lora (Google Fonts), Vanilla JS

**Stripe Link Design-Parameter (aus Analyse):**
- Hintergrund: `#fdf5ef` (warmes Off-White), Cards: `#fff`
- Text: `#13343B` (dark teal-black), `#171717` (near-black)
- Akzent-Blau: `#00579F`, Hover: etwas heller
- Rot (für negative Beträge): `#EF4562`
- Teal/Cyan-Akzent: `#1FB8CD`
- Kein Dark Mode bei Stripe Link
- Typografie: Lora (Serif) für Headlines, System-Font für UI (wie Stripe es macht)
- Cards mit dezentem Border-Radius, leichter Schatten
- Viel Weißraum, klare Hierarchie
- Große Zahlen, minimalistische Darstellung

---

### Task 1: Projektstruktur und Docker-Setup

**Objective:** Projektverzeichnis, Dockerfile und initiale FastAPI-App erstellen

**Files:**
- Create: `/DATA/AppData/hermes/projects/vermogen/Dockerfile`
- Create: `/DATA/AppData/hermes/projects/vermogen/main.py` (minimal skeleton)
- Create: `/DATA/AppData/hermes/projects/vermogen/frontend/` (leer)

**Step 1: Dockerfile**

```dockerfile
FROM python:3.11-slim
RUN pip install --no-cache-dir fastapi uvicorn
WORKDIR /app
COPY main.py .
COPY frontend/ frontend/
EXPOSE 3003
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "3003"]
```

**Step 2: main.py — Minimal Skeleton mit Basic Auth und CSP**

```python
"""
Vermögen — Vermögens- und Budget-Tracker
FastAPI Backend + SQLite + Static Frontend
"""
import secrets
from pathlib import Path
from fastapi import FastAPI, Request, HTTPException, Depends
from fastapi.responses import FileResponse, JSONResponse
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi.middleware.cors import CORSMiddleware

FRONTEND_DIR = Path(__file__).parent / "frontend"
AUTH_USER = "zeyd"
AUTH_PASS = "talla2024"

app = FastAPI(title="Vermögen")
security = HTTPBasic()

def check_auth(credentials: HTTPBasicCredentials = Depends(security)):
    if credentials.username != AUTH_USER or credentials.password != AUTH_PASS:
        raise HTTPException(401, "Unauthorized")
    return credentials

@app.middleware("http")
async def add_frame_options(request: Request, call_next):
    response = await call_next(request)
    response.headers["X-Frame-Options"] = "ALLOWALL"
    response.headers["Content-Security-Policy"] = "frame-ancestors 'self' http://*:* https://*:*;"
    return response

@app.get("/")
def serve_frontend(auth=Depends(check_auth)):
    return FileResponse(FRONTEND_DIR / "index.html")

@app.get("/api/health")
def health():
    return {"status": "ok"}

@app.get("/icon.svg")
def serve_icon():
    return FileResponse(FRONTEND_DIR / "icon.svg", media_type="image/svg+xml")

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=3003)
```

**Step 3: Docker Image bauen**

```bash
cd /DATA/AppData/hermes/projects/vermogen
sudo env HOME=/tmp docker build -t vermogen .
```

**Verification:** `curl -u zeyd:talla2024 http://localhost:3003/api/health` → `{"status":"ok"}`

---

### Task 2: SQLite-Datenbank und Datenmodell

**Objective:** Datenbank-Schema für Vermögen und Budget, Seeder mit den Notion-Daten

**Files:**
- Modify: `main.py` — DB-Initialisierung, Schema, Seed-Daten

**DB Schema:**

```sql
CREATE TABLE IF NOT EXISTS vermoegen (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    kategorie TEXT NOT NULL,  -- Gold, Silber, Krypto, ETF, Bargeld
    betrag REAL DEFAULT 0,
    ziel_prozent REAL,         -- Ziel-Allokation in %
    ist_prozent REAL,          -- Aktuelle Allokation in %
    notiz TEXT,
    sort_order INTEGER DEFAULT 0,
    updated_at TEXT DEFAULT (datetime('now'))
);

CREATE TABLE IF NOT EXISTS budget (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    art TEXT NOT NULL,         -- Fixkosten, Versicherung, Abo, Einnahme, Lebensmittel, Investment, Taschengeld
    betrag REAL DEFAULT 0,
    notiz TEXT,
    sort_order INTEGER DEFAULT 0,
    updated_at TEXT DEFAULT (datetime('now'))
);
```

**Seed-Daten aus Notion (in main.py beim ersten Start, wenn DB leer):**

Vermögen: Gold €7.510,40 (91%), Silber €194,22 (2,4%), Krypto €0 (2%), MSCI World Islamic €0 (25%), MSCI EM Islamic €0 (12%), Bargeld €800 + €500 verliehen

Budget: Miete -€436,47, Haushalt -€650, Strom -€72, Gas -€38, Netzkosten Strom -€18, Netzkosten Gas -€26,40, Internet -€49,30, Öffitickets -€67,45, Krankenversicherung Zeyd -€32,50, Krankenversicherung Fifo -€23,70, Haushaltsvers. -€5,63, Rechtsschutzvers. -€11,59, Rate Schrank -€75, Rate Küche -€62,50, Amazon Prime -€8,99, Disney+ -€10,99, Blink -€3, Fitness -€2, Taschengeld AZ -€400, Taschengeld T -€400, Sparrate -€150, Gehalt Zeyd +€1.031,90, Gehalt Talla +€1.093, Stipendium Zeyd +€484

**API-Endpoints:**
- `GET /api/vermoegen` — Alle Vermögenswerte
- `PUT /api/vermoegen/{id}` — Einzelnen Wert aktualisieren
- `POST /api/vermoegen` — Neuen Wert anlegen
- `DELETE /api/vermoegen/{id}` — Wert löschen
- `GET /api/budget` — Alle Budget-Posten
- `PUT /api/budget/{id}` — Einzelnen Posten aktualisieren
- `POST /api/budget` — Neuen Posten anlegen
- `DELETE /api/budget/{id}` — Posten löschen
- `GET /api/summary` — Zusammenfassung (Gesamtvermögen, Allokation, Monats-Cashflow)

---

### Task 3: Font-End — HTML-Grundgerüst mit Stripe Link Design

**Objective:** Einzelne `index.html` mit Stripe Link-inspiriertem Design, Lora-Schrift, responsiv

**Files:**
- Create: `frontend/index.html`
- Create: `frontend/icon.svg`

**Design-Parameter (Stripe Link):**
- `--bg: #fdf5ef` / `--card-bg: #ffffff`
- `--text: #13343B` / `--text-dim: #555`
- `--blue: #00579F` / `--blue-hover: #004785`
- `--red: #EF4562` / `--green: #0E6245` (Stripe-typisches Grün)
- `--teal: #1FB8CD`
- Font: Lora 400/600 (Google Fonts) für Headlines/Zahlen, -apple-system für UI-Text
- Cards: border-radius 12px, box-shadow: 0 1px 3px rgba(0,0,0,0.08), leichter Border
- Große Typografie-Zahlen, minimalistische Darstellung
- Navigation: Top-Tabs (Vermögen | Budget)

**Struktur index.html:**
- Google Fonts: Lora (Preconnect, dann `<style>`)
- CSS: Stripe Link Farbpalette, Cards, Responsive Grid
- JS: Fetch API, DOM-Manipulation, Edit-Modal (Bottom Sheet)

**Layout:**
- Oben: Header mit "Vermögen" Titel
- Tabs: Vermögen | Budget
- Vermögen-View: Gesamtsumme ganz oben (groß), dann Donut/Pie der Allokation (CSS-only), dann Karten pro Asset
- Budget-View: Einnahmen/Ausgaben Summary, dann gruppiert nach Kategorie

---

### Task 4: Vermögen-Frontend

**Objective:** Vermögensübersicht mit Gesamtsumme, Allokation, Asset-Karten, Bearbeitung

**Files:**
- Modify: `frontend/index.html`

**Features:**
- Hero-Sektion: Gesamtes Vermögen in großer Lora-Zahl
- Allokation: Horizontale Balken pro Asset (CSS, kein Chart.js)
- Asset-Karten: Name, Betrag, Prozente, Notiz
- Klick auf Karte → Bottom-Sheet Modal zum Bearbeiten
- "Hinzufügen" Button für neue Assets
- Speichern via PUT/POST API

**Detail:**
- Summe berechnet aus API-Daten (exkl. verliehenes Geld separat anzeigen)
- Allokations-Update: Änderung eines Betrags updated alle ist_prozent-Werte
- Farbcodierung: Gold (#D4A843), Silber (#A0A0A0), Grün (#0E6245) für ETFs, Grau für Krypto

---

### Task 5: Budget-Frontend

**Objective:** Budget-Tab mit Einnahmen/Ausgaben-Übersicht, gruppiert nach Kategorie

**Files:**
- Modify: `frontend/index.html`

**Features:**
- Summary-Box: Monatseinnahmen (grün), Monatsausgaben (rot), Saldo
- Gruppierte Liste: Fixkosten, Versicherung, Abos, Einnahmen, Lebensmittel, Investment, Taschengeld
- Jede Gruppe: Summe der Kategorie, dann einzelne Posten
- Klick auf Posten → Bottom-Sheet Edit
- "Hinzufügen" Button
- Negativbeträge in `#EF4562`, Positivbeträge in `#0E6245`

---

### Task 6: Deployment auf ZimaOS

**Objective:** Docker-Container mit CasaOS-Integration deployen

**Steps:**

```bash
# 1. HDD-Verzeichnis für persistente Daten
sudo mkdir -p /media/HDD_1TB/Vermogen
sudo chown az-a:users /media/HDD_1TB/Vermogen

# 2. main.py anpassen: DB_PATH auf /data/vermogen.db
# DATA_DIR aus Environment-Variable oder Default /data

# 3. Image bauen
cd /DATA/AppData/hermes/projects/vermogen
sudo env HOME=/tmp docker build -t vermogen .

# 4. Container starten
sudo docker run -d \
  --name Vermoegen \
  --network bridge \
  --restart unless-stopped \
  -p 3003:3003 \
  -v /media/HDD_1TB/Vermogen:/data \
  -e DATA_DIR=/data \
  -l casaos.title="Vermögen" \
  -l casaos.description="Vermögens- und Budget-Tracker für Zeyd & Talla" \
  -l casaos.icon="http://192.168.178.171:3003/icon.svg" \
  -l casaos.scheme="http" \
  -l casaos.hostname="" \
  -l casaos.port="3003" \
  -l casaos.index="/" \
  -l casaos.category="Finance" \
  vermogen
```

**Verification:**
- `curl -u zeyd:talla2024 http://localhost:3003/api/health` → ok
- CasaOS Dashboard: App erscheint als "Vermögen"
- Daten persistieren über Container-Neustarts

---

### Task 7: Finale QA und Politur

**Objective:** Alle Features testen, Edge Cases fixen, Responsive-Verhalten prüfen

**Checkliste:**
- [ ] Basic Auth funktioniert (richtige Credentials → Zugang, falsche → 401)
- [ ] Vermögen: Alle 6 Assets aus Seed-Daten sichtbar
- [ ] Vermögen: Gesamtsumme korrekt
- [ ] Vermögen: Editieren und Speichern funktioniert
- [ ] Vermögen: Neues Asset hinzufügen
- [ ] Vermögen: Löschen mit Bestätigung
- [ ] Budget: Alle 25 Posten aus Seed-Daten sichtbar
- [ ] Budget: Einnahmen/Ausgaben/Saldo korrekt
- [ ] Budget: Nach Kategorie gruppiert
- [ ] Budget: Editieren und Speichern funktioniert
- [ ] Mobile: Responsive Layout (iPhone SE → iPad)
- [ ] CasaOS: App im Dashboard klickbar, iframe funktioniert
- [ ] Daten persistent nach Container-Neustart
- [ ] Lora-Schrift lädt korrekt
- [ ] Stripe Link Design: Farben, Typografie, Cards, Weißraum stimmen

---

**Zusammenfassung:** 7 Tasks, alle unabhängig und in Reihenfolge. Nach Task 6 ist die App live, Task 7 ist QA.
