From cb4dbfdf9f7aa90003ba076cbea1167106621224 Mon Sep 17 00:00:00 2001 From: Florian Wilde Date: Sat, 25 Jul 2026 19:35:14 +0200 Subject: [PATCH] docs: README und Funktionsuebersicht README als Einstieg: was Nebula ist, drei Wege zur Inbetriebnahme (Standalone, komplett Docker, eigene PostgreSQL), Tabelle aller Umgebungsvariablen, Anleitung fuer die Git-Verbindung inklusive der noetigen Token-Scopes je System, Projektstruktur, npm-Skripte, API-Uebersicht, Sicherheitshinweise und eine Fehlersuchtabelle. FEATURES.md listet den Funktionsumfang vollstaendig nach Bereichen auf: Projekte und Status, Dashboard, Notizen, Git-Anbindung inklusive der beim Sync geholten Daten, Oberflaeche sowie Datenmodell, Sicherheit und Betrieb. Am Ende stehen bewusst nicht umgesetzte Ideen fuer spaeter. Co-Authored-By: Claude Opus 5 (1M context) --- FEATURES.md | 207 ++++++++++++++++++++++++++++++++++++++++++ README.md | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 459 insertions(+) create mode 100644 FEATURES.md create mode 100644 README.md diff --git a/FEATURES.md b/FEATURES.md new file mode 100644 index 0000000..66b2110 --- /dev/null +++ b/FEATURES.md @@ -0,0 +1,207 @@ +# Funktionsübersicht + +Vollständige Auflistung dessen, was Nebula kann — gegliedert nach Bereichen. +Für Installation und Betrieb siehe [README.md](README.md). + +--- + +## 1. Projekte + +### 1.1 Anlegen und Verwalten + +- **Idee genügt.** Ein Projekt braucht nur einen Namen. Alles Weitere — Beschreibung, + Repository, Tags — lässt sich jederzeit nachtragen. Neue Projekte starten deshalb + standardmäßig im Status *Idee*. +- **Bearbeiten** über einen Dialog, der auf dem Dashboard und der Projektseite + identisch funktioniert. +- **Löschen** mit Rückfrage; zugehörige Notizen und der Repo-Snapshot verschwinden mit + (Fremdschlüssel mit `ON DELETE CASCADE`). +- **Slug** wird automatisch aus dem Namen erzeugt (umlautfest) und bei Namenskollision + durchnummeriert. + +### 1.2 Felder + +| Feld | Beschreibung | +| --- | --- | +| Name | Pflichtfeld | +| Kurzbeschreibung | Ein Satz für die Karte im Board | +| Beschreibung | Ausführliche Ideenskizze, Zeilenumbrüche bleiben erhalten | +| Status | Idee · In Planung · Offen · In Entwicklung · Fertig · Archiviert | +| Priorität | Niedrig · Normal · Hoch · Kritisch | +| Fortschritt | 0–100 %, per Regler | +| Akzentfarbe | Sechs Farbverläufe, prägen Karte und Detailseite | +| Tags | Kommagetrennt, bis zu 12 Stück, kleingeschrieben und dedupliziert | +| Favorit | Anpinnen — Favoriten stehen im Board immer oben | +| Git-Verbindung | Optionale Zuordnung zu einem Git-System | +| Repository | URL sowie Owner/Name (werden aus der URL abgeleitet) | + +### 1.3 Status + +Sechs Zustände, jeder mit eigener Farbe und Erklärung im Auswahlmenü: + +| Status | Bedeutung | +| --- | --- | +| **Idee** | Noch ein Gedanke — nichts gebaut, nichts entschieden | +| **In Planung** | Scope, Stack und Schnitt werden festgelegt | +| **Offen** | Startklar, liegt aber gerade still | +| **In Entwicklung** | Wird aktiv gebaut | +| **Fertig** | Ausgeliefert und abgeschlossen | +| **Archiviert** | Ruht — bleibt erhalten, ist im Board aber ausgeblendet | + +Der Status ist **direkt auf der Projektkarte** umschaltbar, ohne den Detailbereich zu +öffnen. Die Änderung wird optimistisch angezeigt und bei einem Fehler zurückgerollt. + +--- + +## 2. Dashboard + +- **Kennzahlen** oben: Anzahl Projekte mit Ø-Fortschritt, offene Ideen, aktive + Entwicklungen, fertige Projekte, verknüpfte Repositories. +- **Volltextsuche** über Name, Kurzbeschreibung, Beschreibung, Tags und Repo-Pfad. +- **Statusfilter** als Chips mit Trefferzähler, mehrere gleichzeitig kombinierbar. +- **Sortierung** nach zuletzt geändert, Anlagedatum, Name, Fortschritt oder Priorität — + Favoriten bleiben stets oben. +- **Zwei Ansichten**: freies Raster oder nach Status gruppierte Abschnitte. +- **Archiv** ist standardmäßig ausgeblendet und per Schalter einblendbar. +- **Leerzustände** mit direktem Einstieg statt einer leeren Fläche. + +### Projektkarte auf einen Blick + +Name und Favoritenstern · Kurzbeschreibung · Fortschrittsbalken · Provider-Badge · +Default-Branch samt Anzahl weiterer Branches · letzter Tag · Alter des letzten Commits · +Anzahl Notizen · Warnung bei Sync-Fehler · Tags · Statusauswahl · Priorität. + +--- + +## 3. Notizen + +- **Beliebig viele Notizen pro Projekt**, mit optionalem Titel und mehrzeiligem Text. +- **Anpinnen** — angepinnte Notizen stehen oben und sind farblich hervorgehoben. +- **Bearbeiten und Löschen** direkt in der Liste; Löschen fragt nach. +- **Zeitstempel**: Anlagedatum immer, „bearbeitet vor …" nur bei echter Änderung. +- Zeilenumbrüche und Einrückungen bleiben erhalten — Checklisten und Code-Schnipsel + überleben das Speichern. +- Eine neue Notiz aktualisiert die Änderungszeit des Projekts, damit die Sortierung + „zuletzt geändert" die tatsächliche Aktivität abbildet. + +--- + +## 4. Git-Anbindung + +### 4.1 Unterstützte Systeme + +| System | API | Authentifizierung | Besonderheit | +| --- | --- | --- | --- | +| **GitHub** | REST v3 | `Authorization: Bearer` | github.com und GitHub Enterprise (`/api/v3`) | +| **GitLab** | API v4 | `PRIVATE-TOKEN` | gitlab.com und Self-Hosted, verschachtelte Gruppen | +| **Gitea / Forgejo** | API v1 | `Authorization: token` | beliebige eigene Instanz | + +Mehrere Verbindungen desselben Typs sind möglich — etwa privates GitHub und +Firmen-Gitea nebeneinander. + +### 4.2 Verbindungen verwalten + +- Anlegen mit Anzeigename, System, Basis-URL und Access Token. +- **Verbindungstest** auf Knopfdruck: prüft Erreichbarkeit und Token, zeigt den erkannten + Benutzer und bei Gitea zusätzlich die Serverversion. Ergebnis und Zeitpunkt werden + gespeichert und in der Karte angezeigt. +- **Token-Verwaltung**: verschlüsselt gespeichert, in der UI nur als Hinweis (`ghp_…9f3a`) + sichtbar. Beim Bearbeiten bedeutet ein leeres Feld „unverändert lassen". +- **Repository-Auswahl**: Nebula listet alle Repos, auf die der Token Zugriff hat, mit + Suchfeld. Ein Klick übernimmt URL, Owner, Name und — falls noch leer — Projektname und + Kurzbeschreibung. +- **Löschen** trennt nur die Verknüpfung; die Projekte selbst bleiben erhalten. + +### 4.3 Was beim Sync geholt wird + +| Bereich | Details | +| --- | --- | +| Repository | Voller Pfad, Beschreibung, Default-Branch, Sichtbarkeit, Größe, letzte Aktivität | +| Kennzahlen | Stars, Forks, offene Issues, offene Pull-/Merge-Requests | +| Branches | bis zu 50, mit SHA, Default-Markierung, Schutzstatus und (wo die API es liefert) letztem Commit | +| Tags | bis zu 25, mit SHA, Nachricht und Datum | +| Commits | die letzten 15, mit Kurz-SHA, Nachricht, Autor, Datum und Link | +| Releases | bis zu 10, inklusive Pre-Release- und Draft-Kennzeichnung | +| Sprachen | Verteilung als Balken mit Prozentwerten | + +- **Snapshot-Prinzip**: Alle Daten werden in der Datenbank abgelegt. Das Dashboard bleibt + ohne Netzverbindung oder bei erreichtem Rate-Limit vollständig nutzbar. +- **URL-Erkennung** für `https://…`, `git@host:owner/repo.git` und GitLab-Weboberflächen-URLs + mit `/-/tree/…`; verschachtelte Gruppenpfade bleiben erhalten. +- **Ohne Token** funktionieren öffentliche Repositories, mit deutlich strengerem Rate-Limit. +- **Fehler landen am Projekt** statt in einer Fehlerseite: die Karte zeigt „Sync-Fehler", + die Projektseite die genaue Meldung. Typische HTTP-Codes werden in Klartext übersetzt + (401 Token, 403 Scopes/Rate-Limit, 404 Pfad, 408 Timeout). +- **Zeitlimit** pro Aufruf über `GIT_API_TIMEOUT_MS` einstellbar; die Teilabfragen laufen + parallel, eine fehlschlagende Liste bricht den restlichen Sync nicht ab. + +--- + +## 5. Oberfläche + +- **Dark Glassmorphism**: milchige Glasflächen, driftende Nebel im Hintergrund, feines + Raster, Neon-Akzente pro Projektfarbe. +- **Animationen**: gestaffelt einblendende Karten, Hover-Lift mit Farbverlaufsrand, + animierte Fortschrittsbalken. +- **Responsiv** von Handy bis Ultrawide (bis zu vier Kartenspalten). +- **Barrierearm**: durchgehende ARIA-Labels, Escape schließt Dialoge, sichtbarer + Fokusring, `prefers-reduced-motion` schaltet Animationen ab. +- **Deutschsprachig**, Datums- und Zahlenformate in `de-DE` mit fester Zeitzone + Europe/Berlin, damit Server- und Browser-Darstellung übereinstimmen. + +--- + +## 6. Daten und Technik + +### 6.1 Datenmodell + +| Tabelle | Inhalt | +| --- | --- | +| `Project` | Projektstammdaten, Status, Fortschritt, Repo-Verknüpfung | +| `Note` | Notizen (n:1 zu Projekt, Cascade-Delete) | +| `GitConnection` | Git-Systeme inkl. verschlüsseltem Token | +| `RepoSnapshot` | Zwischengespeicherter Repo-Stand (1:1 zu Projekt) | + +Listen wie Branches oder Commits liegen als `JSONB`, damit providerspezifische Felder +nicht verloren gehen. Indizes auf Status, Verbindung und Änderungsdatum. + +### 6.2 Sicherheit + +- Access Tokens verschlüsselt mit **AES-256-GCM**, Schlüssel per **scrypt** aus + `APP_SECRET` abgeleitet, Chiffrat versioniert (`v1...`). +- Tokens werden nie an den Browser gesendet — alle API-Antworten nutzen eine Feldauswahl + ohne `tokenCipher`. +- **Zod-Validierung** jeder Eingabe an der API-Grenze mit Feldfehlern für die UI. +- Prisma arbeitet ausschließlich mit parametrisierten Abfragen. + +### 6.3 Betrieb + +- **Zwei gleichwertige Betriebsarten**: Standalone (Node-Prozess, beliebige PostgreSQL) + oder komplett in Docker — dieselbe Codebasis, dieselbe `.env`. +- **Docker-Compose-Profile**: `db` läuft immer, `--profile full` startet zusätzlich die + App, `--profile tools` bringt Adminer als DB-Oberfläche mit. +- **Automatische Migration** beim Containerstart, inklusive Warteschleife auf die + Datenbank. +- **Healthchecks**: `pg_isready` für Postgres, `/api/health` für die App. +- **Setup-Skript** erzeugt die `.env` samt zufälligem `APP_SECRET`. +- **Seed-Daten** auf Wunsch, idempotent — mehrfaches Ausführen legt nichts doppelt an. + +### 6.4 API + +Zehn REST-Endpunkte für Projekte, Notizen, Verbindungen, Sync, Repo-Listen und Health. +Alles, was die Oberfläche kann, ist damit auch scriptbar. Übersicht in der +[README](README.md#api). + +--- + +## 7. Ideen für später + +Bewusst nicht umgesetzt, aber vorgemerkt: + +- Kanban-Board mit Drag & Drop zwischen den Statusspalten +- Webhooks, damit Pushes den Snapshot ohne Knopfdruck aktualisieren +- Markdown-Rendering in Beschreibung und Notizen +- Volltextsuche über Notizen hinweg +- Export eines Projekts als Markdown +- Automatischer Sync im Hintergrund (Intervall pro Verbindung) +- Mehrbenutzerbetrieb mit Login diff --git a/README.md b/README.md new file mode 100644 index 0000000..02982bb --- /dev/null +++ b/README.md @@ -0,0 +1,252 @@ +
+ +# ✦ Nebula + +**Das Kontrollzentrum für deine Vibe-Coding Projekte.** + +Ideen festhalten · Status pflegen · Notizen sammeln · Git-Repos live im Blick + +Next.js 15 · TypeScript · Tailwind CSS 4 · Prisma · PostgreSQL · Docker + +
+ +--- + +## Was ist Nebula? + +Vibe Coding produziert schnell viele halbfertige Projekte: ein Repo hier, eine Idee dort, +irgendwo eine Notiz in einer Textdatei. Nebula bündelt das an einem Ort. + +Jedes Projekt bekommt einen **Status** (von der rohen Idee bis „Fertig"), beliebig viele +**Notizen** und optional ein **verknüpftes Repository**. Nebula holt sich von dort per API +Branches, Tags, Commits, Releases und offene Issues/PRs — egal ob **GitHub**, **GitLab** +oder eine selbst gehostete **Gitea**-Instanz. + +Alle Daten liegen in **deiner lokalen PostgreSQL**. Es gibt keinen Cloud-Dienst dahinter, +Access Tokens werden verschlüsselt abgelegt. + +Eine vollständige Auflistung aller Funktionen steht in **[FEATURES.md](FEATURES.md)**. + +--- + +## Schnellstart + +Zwei Betriebsarten, dieselbe Codebasis. Beide brauchen zuerst eine `.env`: + +```bash +node scripts/setup.mjs # legt .env an und erzeugt ein zufälliges APP_SECRET +``` + +> Ohne Node zur Hand? Einfach `.env.example` nach `.env` kopieren und `APP_SECRET` von Hand +> auf einen langen Zufallswert setzen. + +### Variante A — Standalone (empfohlen zum Entwickeln) + +Die App läuft nativ auf dem Rechner, nur PostgreSQL kommt aus dem Container: + +```bash +docker compose up -d db # Postgres 17 auf localhost:5432 +npm install +npm run db:migrate # Schema anlegen +npm run db:seed # optional: drei Beispielprojekte +npm run dev # → http://localhost:3000 +``` + +Für den Produktivbetrieb ohne Docker: + +```bash +npm run build +npm start # → http://localhost:3000 +``` + +### Variante B — Alles in Docker + +```bash +docker compose --profile full up -d --build # → http://localhost:3000 +``` + +Der App-Container spielt beim Start automatisch die Migrationen ein und wartet dabei auf +die Datenbank. Logs mitlesen: + +```bash +docker compose --profile full logs -f app +``` + +Stoppen: + +```bash +docker compose --profile full down # Container weg, Daten bleiben +docker compose --profile full down -v # inkl. Datenbank-Volume +``` + +### Variante C — Eigene, bereits laufende PostgreSQL + +Docker wird gar nicht gebraucht. In der `.env` nur den Connection-String setzen: + +```env +DATABASE_URL="postgresql://benutzer:passwort@dbhost:5432/nebula?schema=public" +``` + +Dann `npm install && npm run db:migrate && npm run dev`. + +--- + +## Voraussetzungen + +| Variante | Benötigt | +| --- | --- | +| Standalone | Node.js ≥ 20.11, npm, PostgreSQL ≥ 14 (lokal oder via Docker) | +| Docker | Docker Engine ≥ 24 mit Compose v2 | + +--- + +## Konfiguration + +Alle Variablen sind in [`.env.example`](.env.example) dokumentiert. + +| Variable | Bedeutung | Default | +| --- | --- | --- | +| `DATABASE_URL` | PostgreSQL-Verbindung (Prisma) | `postgresql://nebula:nebula@localhost:5432/nebula` | +| `APP_SECRET` | Schlüssel für die Token-Verschlüsselung (AES-256-GCM) | — **unbedingt setzen** | +| `PORT` | Port der Anwendung | `3000` | +| `APP_PORT` | Host-Port-Mapping des App-Containers | `3000` | +| `POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB` | Zugangsdaten des DB-Containers | `nebula` | +| `POSTGRES_PORT` | Host-Port der Datenbank | `5432` | +| `ADMINER_PORT` | Host-Port von Adminer (`--profile tools`) | `8080` | +| `GIT_API_TIMEOUT_MS` | Timeout für Git-API-Aufrufe | `15000` | + +> **`APP_SECRET` nachträglich ändern** macht bereits gespeicherte Git-Tokens unlesbar. +> Sie müssen dann in den Verbindungen neu hinterlegt werden — die restlichen Daten bleiben +> unberührt. + +--- + +## Git-Verbindung einrichten + +1. Im Git-System einen **Personal Access Token** mit Leserechten erzeugen: + + | System | Scopes | + | --- | --- | + | GitHub | Fine-grained Token: *Contents: Read*, *Metadata: Read*, *Issues: Read*, *Pull requests: Read* | + | GitLab | `read_api` (alternativ `read_repository`) | + | Gitea / Forgejo | `repository:read`, `issue:read`, `user:read` | + +2. In Nebula unter **Git-Verbindungen → Verbindung hinzufügen** eintragen: + System wählen, Basis-URL (z. B. `https://git.meine-firma.de`, ohne `/api`) und Token. +3. Mit **Testen** prüfen — Nebula meldet den erkannten Benutzer zurück. +4. Beim Anlegen oder Bearbeiten eines Projekts die Verbindung auswählen und über + **Repos laden** das Repository aussuchen (oder die URL direkt eintippen). +5. Auf der Projektseite **Jetzt synchronisieren** — Branches, Tags, Commits und Releases + werden geholt und als Snapshot gespeichert. + +Der Snapshot bleibt in der Datenbank, das Dashboard funktioniert also auch offline. +Ohne Token gehen nur öffentliche Repositories, mit strengem Rate-Limit. + +--- + +## Projektstruktur + +``` +nebula/ +├── docker/entrypoint.sh Migrationen + Serverstart im Container +├── docker-compose.yml db (immer) · app (--profile full) · adminer (--profile tools) +├── Dockerfile Multi-Stage-Build auf Basis des Next-Standalone-Outputs +├── prisma/ +│ ├── schema.prisma Datenmodell +│ ├── migrations/ versionierte SQL-Migrationen +│ └── seed.ts Beispieldaten +├── scripts/setup.mjs .env erzeugen inkl. APP_SECRET +└── src/ + ├── app/ + │ ├── page.tsx Dashboard (Board, Filter, Kennzahlen) + │ ├── projects/[id]/ Projektdetail: Beschreibung, Notizen, Git + │ ├── connections/ Verwaltung der Git-Verbindungen + │ └── api/ REST-Endpunkte (Projekte, Notizen, Verbindungen, Sync) + ├── components/ UI-Komponenten (Board, Karten, Panels, Dialoge) + ├── lib/ + │ ├── crypto.ts AES-256-GCM für Access Tokens + │ ├── db.ts Prisma-Client + │ ├── git/ Provider-Adapter: github.ts · gitlab.ts · gitea.ts + │ ├── sync.ts Repo-Snapshot holen und speichern + │ └── validation.ts Zod-Schemas für alle Eingaben + └── types/ gemeinsame Typen für Server und Client +``` + +--- + +## npm-Skripte + +| Skript | Zweck | +| --- | --- | +| `npm run dev` | Entwicklungsserver mit Hot Reload | +| `npm run build` / `npm start` | Produktionsbuild und -start (ohne Docker) | +| `npm run setup` | `.env` anlegen inkl. generiertem `APP_SECRET` | +| `npm run db:migrate` | Migrationen einspielen (`prisma migrate deploy`) | +| `npm run db:migrate:dev` | Neue Migration aus Schemaänderungen erzeugen | +| `npm run db:seed` | Beispielprojekte anlegen | +| `npm run db:studio` | Prisma Studio öffnen | +| `npm run db:reset` | Datenbank zurücksetzen (**löscht alles**) | +| `npm run typecheck` | TypeScript prüfen | +| `npm run docker:db` | Nur die Datenbank starten | +| `npm run docker:up` / `docker:down` | Kompletten Stack starten / stoppen | +| `npm run docker:tools` | Adminer auf `http://localhost:8080` | + +--- + +## API + +Alle Endpunkte liefern und erwarten JSON. + +| Methode | Pfad | Zweck | +| --- | --- | --- | +| `GET` | `/api/health` | Status inkl. Datenbankverbindung (Docker-Healthcheck) | +| `GET` `POST` | `/api/projects` | Projekte auflisten / anlegen | +| `GET` `PATCH` `DELETE` | `/api/projects/:id` | Projekt lesen / ändern / löschen | +| `POST` | `/api/projects/:id/sync` | Repo-Daten vom Git-System holen | +| `GET` `POST` | `/api/projects/:id/notes` | Notizen des Projekts | +| `PATCH` `DELETE` | `/api/notes/:id` | Notiz ändern / löschen | +| `GET` `POST` | `/api/connections` | Git-Verbindungen | +| `PATCH` `DELETE` | `/api/connections/:id` | Verbindung ändern / löschen | +| `POST` | `/api/connections/:id/check` | Verbindung und Token testen | +| `GET` | `/api/connections/:id/repos` | Zugängliche Repositories auflisten | + +Beispiel — Idee per Kommandozeile anlegen: + +```bash +curl -X POST http://localhost:3000/api/projects \ + -H "Content-Type: application/json" \ + -d '{"name":"Neue Idee","status":"IDEA","tags":["experiment"]}' +``` + +--- + +## Sicherheitshinweise + +- Nebula hat **keine Benutzerverwaltung** und ist für den Betrieb im eigenen Netz gedacht. + Vor einer Veröffentlichung im Internet unbedingt einen Reverse Proxy mit Authentifizierung + davorschalten. +- Access Tokens werden mit **AES-256-GCM** verschlüsselt gespeichert, aus `APP_SECRET` per + scrypt abgeleitet. Sie werden ausschließlich serverseitig entschlüsselt und nie an den + Browser ausgeliefert — die API zeigt nur einen Hinweis wie `ghp_…9f3a`. +- Ist `APP_SECRET` nicht gesetzt, warnt die App beim Start und nutzt einen unsicheren + Entwicklungsschlüssel. + +--- + +## Fehlersuche + +| Symptom | Ursache / Lösung | +| --- | --- | +| `Can't reach database server` | Läuft `docker compose up -d db`? Stimmt `DATABASE_URL`? | +| `The table ... does not exist` | Migrationen fehlen: `npm run db:migrate` | +| Sync meldet `401` | Token abgelaufen oder falsche Scopes — unter Git-Verbindungen neu setzen | +| Sync meldet `404` | Owner/Repo prüfen; bei GitLab gehört die volle Gruppenkette in „Owner" | +| Sync meldet `403 Rate-Limit` | Ohne Token ist das Limit sehr niedrig — Token hinterlegen | +| Tokens plötzlich ungültig | `APP_SECRET` wurde geändert — Tokens neu eintragen | +| Port 3000 belegt | `APP_PORT` in der `.env` ändern (Docker) bzw. `npm run dev -- -p 3001` | + +--- + +## Lizenz + +MIT — siehe [LICENSE](LICENSE).