Files
gitea-projekt-dashboard/README.md

102 KiB
Raw Blame History

🗂️ Projekt-Dashboard

Ein selbst gehostetes Dashboard zur zentralen Verwaltung aller persönlichen Projekte technische wie nicht-technische.


💡 Was ist ein Projekt?

Ein Projekt ist alles, woran aktiv gearbeitet wird oder wurde unabhängig davon, ob es einen Code-Repository hat oder nicht.

Beispiele:

  • 🖥️ Softwareprojekt eine selbst gehostete App, ein CLI-Tool, ein Backend-Service
  • 🔧 Hardware-Projekt Aufbau eines zweiten PCs, Einrichten eines Homelab-Servers
  • 🏗️ Infrastruktur Umstrukturierung des Heimnetzwerks, Migration zu Docker Compose
  • 📋 Organisatorisches Dokumentation aufräumen, Backupstrategie planen
  • 🌱 Persönliches Lernprojekte, Kurse, Ziele ohne technischen Bezug

Ein Projekt kann mit einer Gitea-Repository verknüpft sein, muss es aber nicht.


🏷️ Repo-Verknüpfung (optional)

Wenn ein Projekt eine zugehörige Gitea-Repository hat, kann diese durch das Topic-Tag projekt markiert werden. Das Dashboard erkennt diese Repos automatisch und zeigt zugehörige Metadaten an (letzter Commit, offene Issues, Sprache etc.).

Repos ohne das Tag projekt erscheinen nicht im Dashboard sie sind keine verwalteten Projekte.

Projekte ohne Repository existieren nur in der Datenbank des Dashboards und werden manuell angelegt.


🧱 Architektur

┌─────────────────────┐        Gitea REST API v1        ┌──────────────────────┐
│    Gitea Server     │ ◄─────────────────────────────► │   Backend Service    │
│  (Repos + Topics)   │   (nur wenn Repo verknüpft)     │   (Go, net/http)     │
└─────────────────────┘                                  └──────────┬───────────┘
                                                                     │
                                                                                                                               ┌──────────▼───────────┐
                                                                                                                                                                                         │    PostgreSQL DB      │
                                                                                                                                                                                                                                                   │  (Projekte, Tasks,   │
                                                                                                                                                                                                                                                                                                             │  Milestones, Notizen) │
                                                                                                                                                                                                                                                                                                                                                                       └──────────┬───────────┘
                                                                                                                                                                                                                                                                                                                                                                                                                                            │
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ┌──────────▼───────────┐
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                │      Frontend         │
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          │    (SvelteKit)        │
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    └──────────────────────┘
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ```

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ---

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ## 🖥️ Frontend: SvelteKit

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Warum SvelteKit?

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Leichtgewichtig und schnell  ideal für ein internes Dashboard
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Server-Side Rendering (SSR) out of the box  kein Flackern beim Laden
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Einfache Reaktivität ohne Overhead
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Perfekt für datengetriebene Übersichten mit Echtzeit-Updates

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Features im Frontend:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Projektkarten mit Name, Beschreibung, Status und offenen Tasks
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Unterscheidung zwischen repo-gebundenen und freien Projekten
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Filterfunktion nach Kategorie, Status, Aktivität
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Detailansicht: Tasks, Milestones, Notizen pro Projekt
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Live-Updates via Server-Sent Events (bei repo-gebundenen Projekten)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Dark Mode, responsive Design

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ---

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ## ⚙️ Backend: Go (net/http + pgx)

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Go eignet sich hervorragend als Backend-Sprache  die Standardbibliothek ist so vollständig, dass kein Web-Framework nötig ist. `net/http` liefert alles was gebraucht wird: Routing, Handler, Middleware.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    **Warum kein Framework?**

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - `net/http` aus der Standardbibliothek reicht für die benötigten Endpoints vollständig aus
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Kein Framework-Overhead, keine Breaking Changes durch externe Dependencies
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Go-typischer Ansatz: explizit, simpel, lesbar
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Kompiliert zu einer einzigen statischen Binary  minimaler Docker-Footprint

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    **Externe Dependencies (minimal):**

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - `pgx`  PostgreSQL-Treiber (direktes SQL, kein ORM)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - `godotenv`  `.env`-Datei laden
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - `golang.org/x/oauth2`  OAuth2-Flow für Gitea-Login (optional)

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    **Backend-Aufgaben:**

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - `GET /api/projects`  alle Projekte aus der DB zurückgeben
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - `POST /api/projects`  neues Projekt anlegen (mit oder ohne Repo-Verknüpfung)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - `GET /api/projects/{id}/tasks`  Tasks eines Projekts abrufen
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - `POST /api/webhook`  Gitea Webhook-Listener für repo-gebundene Projekte
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Hintergrund-Goroutine: Gitea API nach Repos mit Tag `projekt` abfragen und DB synchronisieren

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ---

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ## 🔐 Auth: Gitea OAuth2

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Gitea fungiert als OAuth2-Provider  Nutzer loggen sich mit ihrem Gitea-Account im Dashboard ein.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    **Flow:**

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Nutzer klickt "Login mit Gitea" → Weiterleitung zur Gitea-Instanz → Nutzer bestätigt Zugriff → Gitea leitet mit Authorization Code zurück → Backend tauscht Code gegen Access Token → Nutzer ist eingeloggt

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    **Vorteile:**

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Kein eigenes Auth-System nötig
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Nutzeridentität direkt bekannt
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    - Implementiert mit `golang.org/x/oauth2`

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ---

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ## 🗄️ Datenbank: PostgreSQL

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    **Schema-Übersicht:**

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ```sql
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    -- Alle Projekte (mit oder ohne Repo-Verknüpfung)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    CREATE TABLE projects (
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        id           SERIAL PRIMARY KEY,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            name         VARCHAR(255) NOT NULL,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                description  TEXT,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    status       VARCHAR(50) DEFAULT 'active',   -- active / paused / done
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        category     VARCHAR(100),                   -- z.B. "software", "hardware", "infra", "personal"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            gitea_repo   TEXT,                           -- optional: voller Repo-Name (z.B. "Jannis/mein-projekt")
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                gitea_id     INTEGER,                        -- optional: Gitea-interne Repo-ID
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    html_url     TEXT,                           -- optional: Link zur Repo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        language     VARCHAR(100),                   -- optional: Hauptsprache der Repo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            open_tasks   INTEGER DEFAULT 0,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                last_activity TIMESTAMPTZ,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    created_at   TIMESTAMPTZ DEFAULT NOW(),
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        synced_at    TIMESTAMPTZ                     -- NULL wenn kein Gitea-Sync
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        );

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        -- Tasks / Aufgaben pro Projekt
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        CREATE TABLE tasks (
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            id          SERIAL PRIMARY KEY,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                project_id  INTEGER REFERENCES projects(id),
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    gitea_issue_id INTEGER,                      -- optional: verknüpftes Gitea-Issue
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        title       TEXT NOT NULL,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            body        TEXT,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                state       VARCHAR(20) DEFAULT 'open',      -- open / closed
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    priority    VARCHAR(20),                     -- low / medium / high
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        milestone   TEXT,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            assignee    VARCHAR(100),
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                updated_at  TIMESTAMPTZ DEFAULT NOW()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                );

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                -- Milestones pro Projekt
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                CREATE TABLE milestones (
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    id          SERIAL PRIMARY KEY,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        project_id  INTEGER REFERENCES projects(id),
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            title       TEXT NOT NULL,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                description TEXT,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    due_date    TIMESTAMPTZ,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        closed      BOOLEAN DEFAULT false
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        );

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        -- Webhook-Event-Log (nur für repo-gebundene Projekte)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        CREATE TABLE webhook_events (
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            id           SERIAL PRIMARY KEY,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                event_type   VARCHAR(50),
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    project_id   INTEGER REFERENCES projects(id),
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        payload      JSONB,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            received_at  TIMESTAMPTZ DEFAULT NOW()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            );
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ```

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ---

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ## 🚀 Roadmap

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            - **v0.1**  Projekt-Listing: manuelle Projekte anlegen, Repos mit Tag `projekt` automatisch einlesen
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            - **v0.2**  Webhook-Listener für Echtzeit-Sync bei repo-gebundenen Projekten
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            - **v0.3**  Tasks & Milestones im Dashboard anzeigen und verwalten
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            - **v0.4**  Tasks direkt aus dem Dashboard erstellen/schließen (bi-direktional mit Gitea)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            - **v0.5**  Gitea OAuth2 Login
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            - **v0.6**  Kategorien, Filter, Status-Verwaltung für alle Projekttypen
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            - **v1.0**  Multi-User, öffentliche Projektseiten

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ---

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ## 🔧 Tech Stack

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Schicht     | Technologie                        |
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |-------------|-------------------------------------|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Frontend    | SvelteKit + TailwindCSS            |
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Backend     | Go + net/http (Standardlib)        |
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Datenbank   | PostgreSQL + pgx                   |
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Auth        | Gitea OAuth2 + golang.org/x/oauth2 |
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | API         | Gitea REST API v1 (optional)       |
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Deployment  | Docker Compose                     |

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ---

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ## 📦 Getting Started

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ```bash
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            # Repo klonen
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            git clone https://gitea.starfour.de/Jannis/gitea-projekt-dashboard

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            # Umgebungsvariablen setzen
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            cp .env.example .env
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            # GITEA_URL, GITEA_TOKEN, DATABASE_URL, PROJEKT_TAG eintragen

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            # Mit Docker starten
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            docker compose up -d
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ```

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ---

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Dieses Projekt ist Teil der persönlichen Projekt-Ideen-Sammlung.  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Zugehöriges Übersichts-Repo: [projekt-ideen](https://gitea.starfour.de/Jannis/projekt-ideen)