Update README.md
This commit is contained in:
273
README.md
273
README.md
@@ -26,175 +26,176 @@ Every repository on this Gitea instance that has the topic tag `dashboard` is au
|
|||||||
---
|
---
|
||||||
|
|
||||||
## 🧱 Architecture
|
## 🧱 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
|
- Lightweight and fast – ideal for an internal dashboard
|
||||||
- Server-Side Rendering (SSR) out of the box – no flickering on load
|
- Server-Side Rendering (SSR) out of the box – no flickering on load
|
||||||
- Simple reactivity without overhead
|
- Simple reactivity without overhead
|
||||||
- Perfect for data-driven dashboards with real-time updates via SSE or WebSocket
|
- 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
|
- Project cards with repo name, description, last commit, open issues
|
||||||
- Filter function by topics, language, activity
|
- Filter function by topics, language, activity
|
||||||
- Detail view: edit issues & milestones directly in the dashboard (bi-directional)
|
- Detail view: edit issues & milestones directly in the dashboard (bi-directional)
|
||||||
- Live updates via webhook events (Server-Sent Events)
|
- Live updates via webhook events (Server-Sent Events)
|
||||||
- Dark mode, responsive design
|
- 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
|
- `net/http` from the standard library is fully sufficient for ~6 endpoints
|
||||||
- No framework overhead, no breaking changes from external dependencies
|
- No framework overhead, no breaking changes from external dependencies
|
||||||
- The Go-typical approach: explicit, simple, readable
|
- The Go-typical approach: explicit, simple, readable
|
||||||
- Compiles to a single static binary – minimal Docker footprint
|
- Compiles to a single static binary – minimal Docker footprint
|
||||||
|
|
||||||
**External dependencies (minimal):**
|
**External dependencies (minimal):**
|
||||||
|
|
||||||
- `pgx` – PostgreSQL driver (direct SQL, no ORM)
|
- `pgx` – PostgreSQL driver (direct SQL, no ORM)
|
||||||
- `godotenv` – load `.env` file
|
- `godotenv` – load `.env` file
|
||||||
- `golang.org/x/oauth2` – OAuth2 flow for Gitea login
|
- `golang.org/x/oauth2` – OAuth2 flow for Gitea login
|
||||||
|
|
||||||
**Backend tasks:**
|
**Backend tasks:**
|
||||||
|
|
||||||
- `GET /api/projects` – return all tagged repos from the DB
|
- `GET /api/projects` – return all tagged repos from the DB
|
||||||
- `POST /api/webhook` – Gitea webhook listener for push, issue, tag events
|
- `POST /api/webhook` – Gitea webhook listener for push, issue, tag events
|
||||||
- `GET /api/projects/{id}/issues` – fetch issues for a repo live from Gitea
|
- `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`
|
- Background goroutine: query Gitea API every 5 minutes for repos with tag `dashboard`
|
||||||
- Cache repo data in PostgreSQL (incl. topics, last activity, issue count)
|
- Cache repo data in PostgreSQL (incl. topics, last activity, issue count)
|
||||||
|
|
||||||
**Example – HTTP server without a framework:**
|
**Example – HTTP server without a framework:**
|
||||||
|
|
||||||
```go
|
```go
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.HandleFunc("GET /api/projects", h.listProjects)
|
mux.HandleFunc("GET /api/projects", h.listProjects)
|
||||||
mux.HandleFunc("POST /api/webhook", h.handleWebhook)
|
mux.HandleFunc("POST /api/webhook", h.handleWebhook)
|
||||||
mux.HandleFunc("GET /api/projects/{id}/issues", h.listIssues)
|
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:**
|
**Setup in Gitea:**
|
||||||
1. In Gitea under **Settings → Applications → OAuth2 Applications**, register a new app
|
1. In Gitea under **Settings → Applications → OAuth2 Applications**, register a new app
|
||||||
2. Enter Client ID and Client Secret in the `.env` file
|
2. Enter Client ID and Client Secret in the `.env` file
|
||||||
3. Set the Redirect URI to `https://dashboard.example.com/auth/callback`
|
3. Set the Redirect URI to `https://dashboard.example.com/auth/callback`
|
||||||
|
|
||||||
**Flow:**
|
**Flow:**
|
||||||
- User clicks "Login with Gitea"
|
- User clicks "Login with Gitea"
|
||||||
- → Redirect to Gitea instance (Authorization Endpoint)
|
- → Redirect to Gitea instance (Authorization Endpoint)
|
||||||
- → User confirms access
|
- → User confirms access
|
||||||
- → Gitea redirects back with Authorization Code
|
- → Gitea redirects back with Authorization Code
|
||||||
- → Backend exchanges code for Access Token
|
- → Backend exchanges code for Access Token
|
||||||
- → User is logged in, Gitea identity is known
|
- → User is logged in, Gitea identity is known
|
||||||
|
|
||||||
**Advantages:**
|
**Advantages:**
|
||||||
|
|
||||||
- No custom auth system needed – Gitea handles passwords and sessions
|
- No custom auth system needed – Gitea handles passwords and sessions
|
||||||
- User identity directly available → repos and issues can be filtered per user
|
- User identity directly available → repos and issues can be filtered per user
|
||||||
- Write permissions (create/close issues) only for the respective repo owner
|
- 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
|
- Implemented with `golang.org/x/oauth2` – official Go package, no third-party lib needed
|
||||||
|
|
||||||
## 🗄️ Database: PostgreSQL
|
## 🗄️ Database: PostgreSQL
|
||||||
|
|
||||||
**Schema overview:**
|
**Schema overview:**
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
-- Cached repo information
|
-- Cached repo information
|
||||||
CREATE TABLE projects (
|
CREATE TABLE projects (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
gitea_id INTEGER UNIQUE NOT NULL,
|
gitea_id INTEGER UNIQUE NOT NULL,
|
||||||
name VARCHAR(255) NOT NULL,
|
name VARCHAR(255) NOT NULL,
|
||||||
full_name VARCHAR(255) NOT NULL,
|
full_name VARCHAR(255) NOT NULL,
|
||||||
description TEXT,
|
description TEXT,
|
||||||
html_url TEXT,
|
html_url TEXT,
|
||||||
topics TEXT[], -- e.g. ["dashboard", "freelancer"]
|
topics TEXT[], -- e.g. ["dashboard", "freelancer"]
|
||||||
language VARCHAR(100),
|
language VARCHAR(100),
|
||||||
open_issues INTEGER DEFAULT 0,
|
open_issues INTEGER DEFAULT 0,
|
||||||
last_push TIMESTAMPTZ,
|
last_push TIMESTAMPTZ,
|
||||||
is_private BOOLEAN DEFAULT false,
|
is_private BOOLEAN DEFAULT false,
|
||||||
synced_at TIMESTAMPTZ DEFAULT NOW()
|
synced_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Managed issues / tasks
|
-- Managed issues / tasks
|
||||||
CREATE TABLE issues (
|
CREATE TABLE issues (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
gitea_id INTEGER NOT NULL,
|
gitea_id INTEGER NOT NULL,
|
||||||
project_id INTEGER REFERENCES projects(id),
|
project_id INTEGER REFERENCES projects(id),
|
||||||
title TEXT NOT NULL,
|
title TEXT NOT NULL,
|
||||||
state VARCHAR(20), -- open / closed
|
state VARCHAR(20), -- open / closed
|
||||||
assignee VARCHAR(100),
|
assignee VARCHAR(100),
|
||||||
milestone TEXT,
|
milestone TEXT,
|
||||||
updated_at TIMESTAMPTZ
|
updated_at TIMESTAMPTZ
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Webhook event log
|
-- Webhook event log
|
||||||
CREATE TABLE webhook_events (
|
CREATE TABLE webhook_events (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
event_type VARCHAR(50),
|
event_type VARCHAR(50),
|
||||||
payload JSONB,
|
payload JSONB,
|
||||||
received_at TIMESTAMPTZ DEFAULT NOW()
|
received_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🚀 Roadmap
|
## 🚀 Roadmap
|
||||||
- v0.1 – Repo listing via tag `dashboard`, polling every 5 min
|
- v0.1 – Repo listing via tag `dashboard`, polling every 5 min
|
||||||
- v0.2 – Webhook listener for real-time updates
|
- v0.2 – Webhook listener for real-time updates
|
||||||
- v0.3 – Display issues & milestones in the dashboard
|
- v0.3 – Display issues & milestones in the dashboard
|
||||||
- v0.4 – Create/close issues directly from the dashboard (bi-directional)
|
- v0.4 – Create/close issues directly from the dashboard (bi-directional)
|
||||||
- v0.5 – Gitea OAuth2 login
|
- v0.5 – Gitea OAuth2 login
|
||||||
- v0.6 – Integration with freelancer dashboard (repos = projects)
|
- v0.6 – Integration with freelancer dashboard (repos = projects)
|
||||||
- v1.0 – Multi-user, public project pages
|
- v1.0 – Multi-user, public project pages
|
||||||
|
|
||||||
## 🔧 Tech Stack
|
## 🔧 Tech Stack
|
||||||
|
|
||||||
| Layer | Technology |
|
| Layer | Technology |
|
||||||
|----------|-------------------------------------|
|
|----------|-------------------------------------|
|
||||||
| Frontend | SvelteKit + TailwindCSS |
|
| Frontend | SvelteKit + TailwindCSS |
|
||||||
| Backend | Go + net/http (standard lib) |
|
| Backend | Go + net/http (standard lib) |
|
||||||
| Database | PostgreSQL + pgx |
|
| Database | PostgreSQL + pgx |
|
||||||
| Auth | Gitea OAuth2 + golang.org/x/oauth2 |
|
| Auth | Gitea OAuth2 + golang.org/x/oauth2 |
|
||||||
| API | Gitea REST API v1 |
|
| API | Gitea REST API v1 |
|
||||||
| Deploy | Docker Compose |
|
| Deploy | Docker Compose |
|
||||||
|
|
||||||
## 📦 Getting Started
|
## 📦 Getting Started
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Clone the repo
|
# Clone the repo
|
||||||
git clone https://gitea.starfour.de/Jannis/gitea-projekt-dashboard
|
git clone https://gitea.starfour.de/Jannis/gitea-projekt-dashboard
|
||||||
|
|
||||||
# Set environment variables
|
# Set environment variables
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
# Fill in GITEA_URL, GITEA_TOKEN, GITEA_CLIENT_ID, GITEA_CLIENT_SECRET, DATABASE_URL, DASHBOARD_TAG
|
# Fill in GITEA_URL, GITEA_TOKEN, GITEA_CLIENT_ID, GITEA_CLIENT_SECRET, DATABASE_URL, DASHBOARD_TAG
|
||||||
|
|
||||||
# Start with Docker
|
# Start with Docker
|
||||||
docker compose up -d
|
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)
|
||||||
Reference in New Issue
Block a user