jannis-patch-1 #40

Merged
Jannis merged 2 commits from jannis-patch-1 into master 2026-05-13 08:38:10 +00:00
Showing only changes of commit 8b5cee8a6f - Show all commits

273
README.md
View File

@@ -26,175 +26,176 @@ Every repository on this Gitea instance that has the topic tag `dashboard` is au
---
## 🧱 Architecture
```
┌─────────────────┐ Gitea REST API v1 ┌─────────────────────┐
│ Gitea Server │ ◄────────────────────► │ Backend Service │
│ (Repos + Topics)│ │ (Go, net/http) │
└─────────────────┘ └──────────┬──────────┘
┌──────────▼───────────┐
│ PostgreSQL DB │
│ (Repos, Issues, │
│ Milestones, Cache) │
└──────────┬───────────┘
┌──────────▼───────────┐
│ Frontend │
│ (SvelteKit) │
└──────────────────────┘
```
┌─────────────────┐ 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?**
**Why SvelteKit?**
- 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
- 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
**Frontend features:**
**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
- 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 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.
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.
**Why no framework?**
**Why no framework?**
- `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
- `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
**External dependencies (minimal):**
**External dependencies (minimal):**
- `pgx` PostgreSQL driver (direct SQL, no ORM)
- `godotenv` load `.env` file
- `golang.org/x/oauth2` OAuth2 flow for Gitea login
- `pgx` PostgreSQL driver (direct SQL, no ORM)
- `godotenv` load `.env` file
- `golang.org/x/oauth2` OAuth2 flow for Gitea login
**Backend tasks:**
**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)
- `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)
**Example HTTP server without a framework:**
**Example HTTP server without a 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)
```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)
log.Fatal(http.ListenAndServe(":8080", mux))
```
log.Fatal(http.ListenAndServe(":8080", mux))
```
## 🔐 Auth: Gitea OAuth2
## 🔐 Auth: Gitea OAuth2
Gitea can act as its own OAuth2 provider users log into the dashboard with their Gitea account, just like "Login with GitHub".
Gitea can act as its own OAuth2 provider users log into the dashboard with their Gitea account, just like "Login with GitHub".
**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`
**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`
**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
**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:**
**Advantages:**
- 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
- 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
## 🗄️ Database: PostgreSQL
## 🗄️ Database: PostgreSQL
**Schema overview:**
**Schema overview:**
```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()
);
```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()
);
-- 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
);
-- 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()
);
```
-- Webhook event log
CREATE TABLE webhook_events (
id SERIAL PRIMARY KEY,
event_type VARCHAR(50),
payload JSONB,
received_at TIMESTAMPTZ DEFAULT NOW()
);
```
## 🚀 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
## 🚀 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
## 🔧 Tech Stack
## 🔧 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 |
| 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 |
## 📦 Getting Started
## 📦 Getting Started
```bash
# Clone the repo
git clone https://gitea.starfour.de/Jannis/gitea-projekt-dashboard
```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
# Set environment variables
cp .env.example .env
# Fill in GITEA_URL, GITEA_TOKEN, GITEA_CLIENT_ID, GITEA_CLIENT_SECRET, DATABASE_URL, DASHBOARD_TAG
# Start with Docker
docker compose up -d
```
# Start with Docker
docker compose up -d
```
This project is part of the personal project ideas collection. Related overview repo: [projekt-ideen](https://gitea.starfour.de/Jannis/projekt-ideen)
This project is part of the personal project ideas collection. Related overview repo: [projekt-ideen](https://gitea.starfour.de/Jannis/projekt-ideen)