From cb2700066aa2f614c5b25ec6a085e56a5009bdec Mon Sep 17 00:00:00 2001 From: Jannis Date: Wed, 13 May 2026 08:11:47 +0000 Subject: [PATCH] Update README.md --- README.md | 318 ++++++++++++++++++++++++++---------------------------- 1 file changed, 150 insertions(+), 168 deletions(-) diff --git a/README.md b/README.md index dca674b..c2a3323 100644 --- a/README.md +++ b/README.md @@ -1,218 +1,200 @@ -# πŸ—‚οΈ Gitea Projekt-Dashboard +# πŸ—‚οΈ Gitea Project Dashboard > [!WARNING] -> **⏸️ Projekt pausiert** +> **⏸️ Project paused** > -> Dieses Projekt ist aktuell pausiert. Ich entwickle eine eigene LΓΆsung weiter, die Beego ersetzen soll. -> Sobald mein eigenes Web-Framework weit genug ist, wird dieses Projekt damit neu aufgesetzt. +> This project is currently paused. I am continuing to develop my own solution to replace Beego. Once my own web framework is far enough along, this project will be rebuilt with it. > -> πŸ‘‰ **Eigene LΓΆsung in Entwicklung:** [go-webframework](https://gitea.starfour.de/Jannis/go-webframework) +> πŸ‘‰ **Own solution in development:** [go-webframework](https://gitea.starfour.de/Jannis/go-webframework) - -Ein selbst gehostetes Dashboard zur zentralen Verwaltung aller persΓΆnlichen Projekte – technische wie nicht-technische. Projekte kΓΆnnen mit einer Gitea-Repository verknΓΌpft sein, mΓΌssen es aber nicht. +A self-hosted dashboard for centrally managing all personal projects – technical and non-technical alike. Projects can be linked to a Gitea repository, but don't have to be. --- -## 🏷️ Funktionsprinzip: Tag-basierte Projektanzeige +## 🏷️ How It Works: Tag-Based Project Display -Jedes Repository, das auf dieser Gitea-Instanz mit dem Topic-Tag `dashboard` versehen ist, wird automatisch im Dashboard angezeigt. +Every repository on this Gitea instance that has the topic tag `dashboard` is automatically shown in the dashboard. -### So funktioniert es: +### How it works: +1. In a Gitea repository, go to **Settings β†’ Topics** and add the tag `dashboard` +2. The backend service polls the Gitea API regularly (or via webhook) for all repos with this tag +3. The found repos are stored and cached in the PostgreSQL database +4. The frontend displays all tagged repos as project cards with live data -1. Du setzt in einem Gitea-Repository unter **Settings β†’ Topics** das Tag `dashboard` -2. Der Backend-Service pollt regelmÀßig (oder per Webhook) die Gitea API nach allen Repos mit diesem Tag -3. Die gefundenen Repos werden in der PostgreSQL-Datenbank gespeichert und gecacht -4. Das Frontend zeigt alle getaggten Repos als Projektkarten mit Live-Daten an - -> **Beispiel:** Repo `mein-projekt` bekommt das Topic `dashboard` β†’ erscheint sofort im Dashboard mit Issues, letztem Commit, Status und Beschreibung. +> **Example:** Repo `my-project` gets the topic `dashboard` β†’ immediately appears in the dashboard with issues, last commit, status, and description. --- -## 🧱 Architektur - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” Gitea REST API v1 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Gitea Server β”‚ ◄────────────────────────► β”‚ Backend Service β”‚ -β”‚ (Repos + Topics)β”‚ β”‚ (Go, net/http) β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ PostgreSQL DB β”‚ - β”‚ (Repos, Issues, β”‚ - β”‚ Milestones, Cache) β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Frontend β”‚ - β”‚ (SvelteKit) β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +## 🧱 Architecture ``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” Gitea REST API v1 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Gitea Server β”‚ ◄────────────────────► β”‚ Backend Service β”‚ +β”‚ (Repos + Topics)β”‚ β”‚ (Go, net/http) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ PostgreSQL DB β”‚ + β”‚ (Repos, Issues, β”‚ + β”‚ Milestones, Cache) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Frontend β”‚ + β”‚ (SvelteKit) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ``` ---- + ## πŸ–₯️ Frontend: SvelteKit -## πŸ–₯️ Frontend: **SvelteKit** + **Why 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 Dashboards mit Echtzeit-Updates via SSE oder WebSocket + - Lightweight and fast – ideal for an internal dashboard + - Server-Side Rendering (SSR) out of the box – no flickering on load + - Simple reactivity without overhead + - Perfect for data-driven dashboards with real-time updates via SSE or WebSocket -**Features im Frontend:** -- Projektkarten mit Repo-Name, Beschreibung, letztem Commit, offenen Issues -- Filterfunktion nach Topics, Sprache, AktivitΓ€t -- Detailansicht: Issues & Milestones direkt im Dashboard bearbeiten (bi-direktional) -- Live-Updates via Webhook-Events (Server-Sent Events) -- Dark Mode, responsive Design + **Frontend features:** ---- + - Project cards with repo name, description, last commit, open issues + - Filter function by topics, language, activity + - Detail view: edit issues & milestones directly in the dashboard (bi-directional) + - Live updates via webhook events (Server-Sent Events) + - Dark mode, responsive design -## βš™οΈ Backend: **Go (net/http + pgx)** + ## βš™οΈ 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. Das Ergebnis ist eine dependency-arme, gut lesbare Codebasis. + Go is an excellent backend language – the standard library is so complete that no web framework is needed. `net/http` provides everything required: routing, handlers, middleware. The result is a dependency-light, readable codebase. -**Warum kein Framework?** -- `net/http` aus der Standardbibliothek reicht fΓΌr ~6 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 + **Why no framework?** -**Externe Dependencies (minimal):** -- `pgx` – PostgreSQL-Treiber (direktes SQL, kein ORM) -- `godotenv` – `.env`-Datei laden -- `golang.org/x/oauth2` – OAuth2-Flow fΓΌr Gitea-Login + - `net/http` from the standard library is fully sufficient for ~6 endpoints + - No framework overhead, no breaking changes from external dependencies + - The Go-typical approach: explicit, simple, readable + - Compiles to a single static binary – minimal Docker footprint -**Backend-Aufgaben:** -- `GET /api/projects` – alle getaggten Repos aus der DB zurΓΌckgeben -- `POST /api/webhook` – Gitea Webhook-Listener fΓΌr Push, Issue, Tag-Events -- `GET /api/projects/{id}/issues` – Issues eines Repos live aus Gitea holen -- Hintergrund-Goroutine: alle 5 Minuten Gitea API nach Repos mit Tag `dashboard` abfragen -- Repo-Daten in PostgreSQL cachen (inkl. Topics, letzter AktivitΓ€t, Issue-Count) + **External dependencies (minimal):** -**Beispiel – HTTP-Server ohne Framework:** -```go -mux := http.NewServeMux() -mux.HandleFunc("GET /api/projects", h.listProjects) -mux.HandleFunc("POST /api/webhook", h.handleWebhook) -mux.HandleFunc("GET /api/projects/{id}/issues", h.listIssues) + - `pgx` – PostgreSQL driver (direct SQL, no ORM) + - `godotenv` – load `.env` file + - `golang.org/x/oauth2` – OAuth2 flow for Gitea login -log.Fatal(http.ListenAndServe(":8080", mux)) -``` + **Backend tasks:** ---- + - `GET /api/projects` – return all tagged repos from the DB + - `POST /api/webhook` – Gitea webhook listener for push, issue, tag events + - `GET /api/projects/{id}/issues` – fetch issues for a repo live from Gitea + - Background goroutine: query Gitea API every 5 minutes for repos with tag `dashboard` + - Cache repo data in PostgreSQL (incl. topics, last activity, issue count) -## πŸ” Auth: **Gitea OAuth2** + **Example – HTTP server without a framework:** -Gitea kann selbst als OAuth2-Provider fungieren – Nutzer loggen sich mit ihrem Gitea-Account im Dashboard ein, genau wie "Login with GitHub". + ```go + mux := http.NewServeMux() + mux.HandleFunc("GET /api/projects", h.listProjects) + mux.HandleFunc("POST /api/webhook", h.handleWebhook) + mux.HandleFunc("GET /api/projects/{id}/issues", h.listIssues) -### Setup in Gitea: + log.Fatal(http.ListenAndServe(":8080", mux)) + ``` -1. In Gitea unter **Settings β†’ Applications β†’ OAuth2 Applications** eine neue App registrieren -2. `Client ID` und `Client Secret` in die `.env` eintragen -3. Redirect URI auf `https://dashboard.example.com/auth/callback` setzen + ## πŸ” Auth: Gitea OAuth2 -### Flow: + Gitea can act as its own OAuth2 provider – users log into the dashboard with their Gitea account, just like "Login with GitHub". -``` -Nutzer klickt "Login mit Gitea" - β†’ Weiterleitung zur Gitea-Instanz (Authorization Endpoint) - β†’ Nutzer bestΓ€tigt Zugriff - β†’ Gitea leitet mit Authorization Code zurΓΌck - β†’ Backend tauscht Code gegen Access Token - β†’ Nutzer ist eingeloggt, Gitea-IdentitΓ€t bekannt -``` + **Setup in Gitea:** + 1. In Gitea under **Settings β†’ Applications β†’ OAuth2 Applications**, register a new app + 2. Enter Client ID and Client Secret in the `.env` file + 3. Set the Redirect URI to `https://dashboard.example.com/auth/callback` -**Vorteile:** -- Kein eigenes Auth-System nΓΆtig – Gitea ΓΌbernimmt PasswΓΆrter und Sessions -- NutzeridentitΓ€t direkt bekannt β†’ Repos und Issues kΓΆnnen nutzerbasiert gefiltert werden -- Schreibrechte (Issues erstellen/schließen) nur fΓΌr den jeweiligen Repo-Owner -- Implementiert mit `golang.org/x/oauth2` – offizielles Go-Paket, keine Drittanbieter-Lib nΓΆtig + **Flow:** + - User clicks "Login with Gitea" + - β†’ Redirect to Gitea instance (Authorization Endpoint) + - β†’ User confirms access + - β†’ Gitea redirects back with Authorization Code + - β†’ Backend exchanges code for Access Token + - β†’ User is logged in, Gitea identity is known ---- + **Advantages:** -## πŸ—„οΈ Datenbank: **PostgreSQL** + - No custom auth system needed – Gitea handles passwords and sessions + - User identity directly available β†’ repos and issues can be filtered per user + - Write permissions (create/close issues) only for the respective repo owner + - Implemented with `golang.org/x/oauth2` – official Go package, no third-party lib needed -**Schema-Übersicht:** + ## πŸ—„οΈ Database: PostgreSQL -```sql --- Gecachte Repo-Informationen -CREATE TABLE projects ( - id SERIAL PRIMARY KEY, - gitea_id INTEGER UNIQUE NOT NULL, - name VARCHAR(255) NOT NULL, - full_name VARCHAR(255) NOT NULL, - description TEXT, - html_url TEXT, - topics TEXT[], -- z.B. ["dashboard", "freelancer"] - language VARCHAR(100), - open_issues INTEGER DEFAULT 0, - last_push TIMESTAMPTZ, - is_private BOOLEAN DEFAULT false, - synced_at TIMESTAMPTZ DEFAULT NOW() -); + **Schema overview:** --- Gemanagte Issues / Aufgaben -CREATE TABLE issues ( - id SERIAL PRIMARY KEY, - gitea_id INTEGER NOT NULL, - project_id INTEGER REFERENCES projects(id), - title TEXT NOT NULL, - state VARCHAR(20), -- open / closed - assignee VARCHAR(100), - milestone TEXT, - updated_at TIMESTAMPTZ -); + ```sql + -- Cached repo information + CREATE TABLE projects ( + id SERIAL PRIMARY KEY, + gitea_id INTEGER UNIQUE NOT NULL, + name VARCHAR(255) NOT NULL, + full_name VARCHAR(255) NOT NULL, + description TEXT, + html_url TEXT, + topics TEXT[], -- e.g. ["dashboard", "freelancer"] + language VARCHAR(100), + open_issues INTEGER DEFAULT 0, + last_push TIMESTAMPTZ, + is_private BOOLEAN DEFAULT false, + synced_at TIMESTAMPTZ DEFAULT NOW() + ); --- Webhook-Event-Log -CREATE TABLE webhook_events ( - id SERIAL PRIMARY KEY, - event_type VARCHAR(50), - payload JSONB, - received_at TIMESTAMPTZ DEFAULT NOW() -); -``` + -- Managed issues / tasks + CREATE TABLE issues ( + id SERIAL PRIMARY KEY, + gitea_id INTEGER NOT NULL, + project_id INTEGER REFERENCES projects(id), + title TEXT NOT NULL, + state VARCHAR(20), -- open / closed + assignee VARCHAR(100), + milestone TEXT, + updated_at TIMESTAMPTZ + ); ---- + -- Webhook event log + CREATE TABLE webhook_events ( + id SERIAL PRIMARY KEY, + event_type VARCHAR(50), + payload JSONB, + received_at TIMESTAMPTZ DEFAULT NOW() + ); + ``` -## πŸš€ Roadmap + ## πŸš€ Roadmap + - v0.1 – Repo listing via tag `dashboard`, polling every 5 min + - v0.2 – Webhook listener for real-time updates + - v0.3 – Display issues & milestones in the dashboard + - v0.4 – Create/close issues directly from the dashboard (bi-directional) + - v0.5 – Gitea OAuth2 login + - v0.6 – Integration with freelancer dashboard (repos = projects) + - v1.0 – Multi-user, public project pages -- [ ] **v0.1** – Repo-Listing via Tag `dashboard`, Polling alle 5 min -- [ ] **v0.2** – Webhook-Listener fΓΌr Echtzeit-Updates -- [ ] **v0.3** – Issues & Milestones im Dashboard anzeigen -- [ ] **v0.4** – Issues direkt aus dem Dashboard erstellen/schließen (bi-direktional) -- [ ] **v0.5** – Gitea OAuth2 Login -- [ ] **v0.6** – VerknΓΌpfung mit Freelancer-Dashboard (Repos = Projekte) -- [ ] **v1.0** – Multi-User, ΓΆffentliche Projektsseiten + ## πŸ”§ Tech Stack ---- + | Layer | Technology | + |----------|-------------------------------------| + | Frontend | SvelteKit + TailwindCSS | + | Backend | Go + net/http (standard lib) | + | Database | PostgreSQL + pgx | + | Auth | Gitea OAuth2 + golang.org/x/oauth2 | + | API | Gitea REST API v1 | + | Deploy | Docker Compose | -## πŸ”§ Tech Stack + ## πŸ“¦ Getting Started -| 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 | -| Deployment | Docker Compose | + ```bash + # Clone the repo + git clone https://gitea.starfour.de/Jannis/gitea-projekt-dashboard ---- + # Set environment variables + cp .env.example .env + # Fill in GITEA_URL, GITEA_TOKEN, GITEA_CLIENT_ID, GITEA_CLIENT_SECRET, DATABASE_URL, DASHBOARD_TAG -## πŸ“¦ Getting Started + # Start with Docker + docker compose up -d + ``` -```bash -# Repo klonen -git clone https://gitea.starfour.de/Jannis/gitea-projekt-dashboard - -# Umgebungsvariablen setzen -cp .env.example .env -# GITEA_URL, GITEA_TOKEN, GITEA_CLIENT_ID, GITEA_CLIENT_SECRET, DATABASE_URL, DASHBOARD_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)* \ No newline at end of file + This project is part of the personal project ideas collection. Related overview repo: [projekt-ideen](https://gitea.starfour.de/Jannis/projekt-ideen) \ No newline at end of file