docs(readme): redesign README as clean product showcase without internal schema dumps
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
This commit is contained in:
1 parent
7802eb2cf0
commit
0f24cbdbf4
1 file changed
+70
-551
@@ -3,498 +3,87 @@
|
|||||||
# 🧠 MindSift
|
# 🧠 MindSift
|
||||||
### *Der Kopf frei in drei Sekunden.*
|
### *Der Kopf frei in drei Sekunden.*
|
||||||
|
|
||||||
[](https://gitea.io)
|
[](#)
|
||||||
[](https://hub.docker.com)
|
[](#-in-60-sekunden-starten)
|
||||||
[](https://go.dev)
|
[](#)
|
||||||
[](https://react.dev)
|
[](LICENSE)
|
||||||
[%20%2F%20Postgres-003B57?logo=sqlite&logoColor=white)](https://sqlite.org)
|
|
||||||
[](#-designsystem--ästhetik)
|
|
||||||
[](LICENSE)
|
|
||||||
|
|
||||||
**MindSift** verbindet den schnellsten Brain-Dump der Welt mit der Eleganz eines modernen Workspaces, spielerischer Tinder-Style-Triage und kollaborativen Echtzeit-Listen für Familien und Teams — 100 % Self-Hosted & Open Source.
|
**MindSift** ist deine zentrale Schaltstelle für spontane Gedanken, strukturierte Aufgaben, vernetztes Wissen und gemeinsame Echtzeit-Listen — kompromisslos schnell, ablenkungsfrei gestaltet und zu 100 % unter deiner eigenen Kontrolle.
|
||||||
|
|
||||||
[Manifest](#-das-manifest) • [Features](#-features--workflow) • [Architektur](#-technische-architektur--tech-stack) • [Datenbankschema](#-datenbankschema) • [API & Webhooks](#-api-spezifikation--webhooks) • [CI/CD](#-gitea-cicd-pipeline) • [Deployment](#-deployment--schnellstart) • [Roadmap](#-schrittweiser-phasenplan)
|
[Philosophie](#-die-philosophie) • [Funktionen](#-was-mindsift-auszeichnet) • [Für wen?](#-für-wen-ist-mindsift-gemacht) • [Schnellstart](#-in-60-sekunden-starten)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## 📜 Das Manifest
|
## 💡 Die Philosophie: *Erst raus aus dem Kopf – später sortieren*
|
||||||
|
|
||||||
Große Workspace-Tools wie Notion sind genial, wenn man am Schreibtisch sitzt und ein monatelanges Projekt plant. Aber sie scheitern im Alltag genau an einer Stelle: **im echten Moment**.
|
Klassische Produktivitäts- und Notiz-Apps scheitern im Alltag oft an derselben Hürde: **Sie verlangen Struktur im falschen Moment.**
|
||||||
|
Wenn dir mitten im Gespräch, unterwegs oder kurz vor dem Feierabend ein wichtiger Gedanke kommt, willst du keinen Ordner auswählen, keine Datenbank-Eigenschaften pflegen und kein Formular ausfüllen. Du willst den Gedanken in drei Sekunden loswerden – und sicher sein, dass er nicht verloren geht.
|
||||||
|
|
||||||
Wenn dir an der Supermarktkasse eine Idee kommt, du im Auto über einen Geistesblitz nachdenkst oder schnell eine Zutat aufschreiben willst, hast du keine Zeit, durch fünf verschachtelte Ordner und relationale Datenbanken zu navigieren. Du brauchst ein Tool, das in einer halben Sekunde bereitsteht, deinen Gedanken friert und dir später hilft, ihn spielerisch auszusortieren.
|
**MindSift trennt das Erfassen radikal vom Organisieren:**
|
||||||
|
|
||||||
**MindSift löst dieses Problem durch ein dreistufiges Prinzip:**
|
1. **Sofort abladen (Quick Dump):** Oben in der Eingabeleiste tippen, `Enter` drücken, fertig. Dein Kopf ist wieder frei. Wer möchte, kann einen Eintrag aber auch direkt bei der Eingabe einer Aufgabenliste, einer Einkaufsliste oder einer Notiz zuordnen.
|
||||||
1. **Erfassen:** Sofortiger Brain-Dump ohne jede Reibung.
|
2. **Spielerisch sichten (Triage):** Wenn du später Ruhe hast, arbeitest du deinen Gedanken-Stapel Karte für Karte durch. Nach links verwerfen, auf „Später“ schieben oder mit einem Klick in eine echte Aufgabe, ein Dokument oder einen Listeneintrag verwandeln.
|
||||||
2. **Sichten (Sift):** Spielerische Triage im Tinder-Style (Inbox Zero für dein Gehirn).
|
3. **Nahtlos weiterarbeiten:** Aus flüchtigen Ideen werden strukturierte Aufgaben-Boards, verlinkte Wiki-Dokumente oder geteilte Listen für Familie und Team.
|
||||||
3. **Strukturieren & Teilen:** Workspace für reifende Gedanken und geteilte Echtzeit-Listen für den Alltag.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ✨ Features & Workflow
|
## ✨ Was MindSift auszeichnet
|
||||||
|
|
||||||
```
|
### ⚡ Quick-Dump & Triage-Deck
|
||||||
[ 🚀 Instant Capture ]
|
* **Immer griffbereit:** Die Schnell-Eingabeleiste sitzt prominent ganz oben – jederzeit erreichbar per Klick oder Tastendruck (`C` oder `/`).
|
||||||
Handy raus • PWA • Webhook • Sprache
|
* **Entscheiden ohne Stress:** Im Triage-Deck siehst du immer genau eine Karte im Fokus, während darunter deine Warteschlange bereitliegt. Bearbeite den Text direkt auf der Karte, vergib ein Fälligkeitsdatum oder sortiere ihn per Swipe und Tastatur-Kürzel weg.
|
||||||
│
|
|
||||||
▼
|
|
||||||
[ 📥 Thought Inbox ]
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
[ 🃏 Tinder-Style Triage ]
|
|
||||||
┌──────────┴──────────┐
|
|
||||||
▼ ▼
|
|
||||||
[ 👈 Nach Links ] [ 👉 Nach Rechts ]
|
|
||||||
Verwerfen / Done Behalten / Vertiefen
|
|
||||||
┌───────┼───────┐
|
|
||||||
▼ ▼ ▼
|
|
||||||
Task Doc Shared List
|
|
||||||
```
|
|
||||||
|
|
||||||
* **⚡ Capture First (Instant Puffer):**
|
### ✅ Aufgabenlisten & Kanban-Board
|
||||||
Handy raus, App antippen, Cursor steht im Feld. Text tippen oder diktieren (Web Speech API), absenden, fertig. Kein Ordner wählen, kein Tagging, kein Nachdenken. PWA-Shortcut für direkten Homescreen-Capture (< 300 ms Latenz).
|
* **Mehrere Aufgabenlisten:** Trenne Berufliches, Privates, Projekte oder gemeinsame Team-Aufgaben sauber in eigenen Listen.
|
||||||
* **🃏 Triage im Tinder-Style:**
|
* **Liste oder Kanban:** Wechsle jederzeit mit einem Klick zwischen einer kompakten Listenansicht und einem übersichtlichen **3-Spalten-Kanban-Board** (*Zu erledigen*, *In Bearbeitung*, *Erledigt*).
|
||||||
Abends oder am Wochenende gehst du deine unstrukturierten Gedanken durch wie ein Kartendeck:
|
* **Detailtiefe bei Bedarf:** Füge Aufgaben Fälligkeiten, Prioritäten und ausführliche Notizen hinzu – oder wandle eine wachsende Aufgabe direkt in ein großes Workspace-Dokument um.
|
||||||
* **Wisch nach links:** Weg damit (Gedanke erledigt oder irrelevant).
|
|
||||||
* **Wisch nach rechts:** Behalten, verfeinern, in eine To-Do mit Fälligkeitsdatum verwandeln oder in ein Projekt einsortieren.
|
### 📝 Workspace: Komfort wie in Word, gespeichert als echtes Markdown
|
||||||
* **📝 Notion-Flair, aber ohne Ballast:**
|
* **Formatieren auf Knopfdruck:** Nutze die übersichtliche Werkzeugleiste für Überschriften, Fett/Kursiv, Checklisten, Code-Blöcke, Hervorhebungen, Tabellen und Fortschrittsbalken – ganz ohne Markdown-Befehle auswendig lernen zu müssen.
|
||||||
Wächst ein Gedanke zum Projekt heran, wechselst du in den Workspace. Reiner, ablenkungsfreier Block-Editor mit Überschriften, Listen, Codeblöcken und Task-Elementen – ohne relationale Datenbank-Überkomplexität.
|
* **Vernetztes Wiki:** Verknüpfe Dokumente untereinander über interne `[[Wiki-Links]]` und organisiere dein Wissen in einer klaren Ordner- und Unterordner-Struktur.
|
||||||
* **🛒 Geteilte Listen & Family Spaces (Echtzeit):**
|
* **Volle Datenhoheit (Kein Lock-in):** Jedes Dokument wird im Hintergrund als saubere, standardisierte `.md`-Datei in deiner Ordnerstruktur auf der Festplatte abgelegt. Du kannst deine Notizen jederzeit direkt aus dem Dateisystem kopieren, sichern oder mit anderen Programmen nutzen.
|
||||||
Einkaufslisten oder Urlaubsplaner per Link teilen. Hakst du an der Kasse die Hafermilch ab, verschwindet sie bei deinem Partner in Millisekunden dank WebSocket-Synchronisation.
|
|
||||||
* **🤖 Webhooks & Ingestion API:**
|
### 🛒 Geteilte Echtzeit-Listen
|
||||||
Smarthome-Alarme (z. B. Home Assistant, Zigbee2MQTT), Cronjobs oder Webhooks speisen dringende Aufgaben oder Messpunkte direkt in deine Inbox ein.
|
* **Gemeinsam abhaken:** Ob Wocheneinkauf, Packliste für den Urlaub oder Checkliste fürs Projekt – teile Spaces per Einladungscode mit Partnern, Familie oder Kollegen.
|
||||||
* **🛡️ 100 % Self-Hosted & Datensouveränität:**
|
* **Live-Synchronisation:** Hakst du im Supermarkt einen Artikel ab, verschwindet er im selben Augenblick auf den Bildschirmen aller anderen Mitglieder.
|
||||||
Keine fremde Cloud liest mit. Ein schlanker Docker-Container, SQLite mit Write-Ahead-Log (WAL) oder PostgreSQL.
|
|
||||||
|
### 🏢 Organisationen, Teams & Berechtigungskonzept
|
||||||
|
* **Geführte Ersteinrichtung:** Beim ersten Start begrüßt dich ein Einrichtungs-Assistent, mit dem du dein Administrator-Konto und die Sicherheitseinstellungen deines Servers festlegst.
|
||||||
|
* **Geschlossene Gesellschaft oder offenes Team:** Schalte die öffentliche Registrierung ab und vergib gezielte **Einladungscodes**, oder lege Benutzer direkt über die Administration an.
|
||||||
|
* **Drei klare Rollen:** Unterscheide zwischen **Server-Admin** (volle Server- und Mail-Steuerung), **Team-Admin** (darf Nutzer einladen sowie Organisationen und Teams verwalten) und **Mitglied**.
|
||||||
|
* **Sichtbarkeits-Isolation nach Maß:** Bestimme als Administrator zentral, ob Nutzer komplett isoliert für sich arbeiten (*Strikt Privat*), nur Mitglieder ihrer eigenen Teams sehen (*Teams isoliert*) oder serverweit zusammenarbeiten (*Offen*).
|
||||||
|
|
||||||
|
### 🔔 Multi-Channel-Alarme & Eigene Webhooks
|
||||||
|
* **Keine Frist mehr verpassen:** Lass dich vor Fälligkeit einer Aufgabe automatisch benachrichtigen – frei wählbar per **E-Mail**, **Discord-Nachricht** oder **eigenem Webhook**.
|
||||||
|
* **Offen für deine Automatisierung:** Erzeuge persönliche API-Schlüssel in deinen Kontoeinstellungen und schicke System-Alarme, Server-Statusmeldungen oder eigene Skripte per einfachem `curl`-Befehl direkt als Aufgabe oder Notiz in dein MindSift.
|
||||||
|
|
||||||
|
### 🖤 Fokussiertes, eckiges Dark-Design
|
||||||
|
* **Ruhe fürs Auge:** Ein klares, monochromes dunkles Design mit präzisen Kanten und einer einzigen, gezielt eingesetzten Akzentfarbe. Keine Ablenkung, keine überladenen Menüs, volle Konzentration auf deine Inhalte.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🎨 Designsystem & Ästhetik
|
## 👥 Für wen ist MindSift gemacht?
|
||||||
|
|
||||||
MindSift setzt konsequent auf eine ultramoderne, dunkle Productivity-Suite-Ästhetik — fokussiert, augenschonend und schnell:
|
* **Für Vielbeschäftigte & Kreative**, die tagsüber hunderte Gedanken, To-Dos und Links im Kopf jonglieren und ein System suchen, das schneller ist als jede klassische Notiz-App.
|
||||||
|
* **Für Familien, Paare & WGs**, die gemeinsame Einkaufslisten, Erledigungen und Planungen ohne Werbe-Apps und ohne fremde Cloud synchronisieren möchten.
|
||||||
* **Dark Mode First (Deep Charcoal Canvas):**
|
* **Für Teams, Selbstständige & Homelab-Enthusiasten**, die Aufgaben, Projektdokumentation, Server-Webhooks und Benutzerrechte souverän auf der eigenen Infrastruktur betreiben wollen.
|
||||||
* Hintergrund primär: `#16171a`
|
|
||||||
* Oberflächen/Karten: `#222428` mit feinen `1px` Konturen (`rgba(255, 255, 255, 0.08)`)
|
|
||||||
* Elevated & Hover: `#282a2f` / `#2b2d33`
|
|
||||||
* Primär-Brand: Electric Blue (`#1d8cf8`)
|
|
||||||
* Status-Akzente: Vivid Green (`#22c55e`), Coral Red (`#ef4444`), Vivid Orange (`#f97316`)
|
|
||||||
* **Squircles & Solid Color Badges:** Quadratisch abgerundete Icons (`rounded-xl`) mit satten Einzelfarben ohne grelle AI-Farbverläufe.
|
|
||||||
* **Pill-Buttons & Active Highlighting:** Filter-Chips (`All`, `Favorite`) und Action-Buttons in Pillenform (`rounded-full`); aktive Aufgaben erhalten eine scharfe grüne Kontur (`border border-[#22c55e]/70`).
|
|
||||||
* **Floating Bottom Dock:** Zentrale Daumenleiste mit markantem blauem `+` Action-Button zum blitzschnellen Gedanken-Erfassen von überall.
|
|
||||||
* **Haptik & Touch-Optimierung:** Große Interaktionsradien (mind. 48px Touch-Targets), Vibrations-Feedback via Web Vibration API bei Karten-Swipes.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🏗️ Technische Architektur & Tech-Stack
|
## 🚀 In 60 Sekunden starten
|
||||||
|
|
||||||
Als Lead-Architektur wurde ein **Single-Binary / Single-Container** Paradigma gewählt. Das Go-Backend kompiliert das React-Frontend direkt in ein einziges Executable ein (`embed.FS`).
|
MindSift läuft als einzelner, ressourcenschonender Container und bringt alles mit, was du brauchst.
|
||||||
|
|
||||||
```
|
### Start mit Docker Compose
|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ Client (Mobile PWA / Desktop) │
|
|
||||||
│ React 19 • Vite • Tailwind CSS v4 • Framer Motion • Tiptap Block-Editor │
|
|
||||||
└───────────────────────────────┬─────────────────────────────────────────┘
|
|
||||||
│ HTTP/2 / REST & WebSockets (WSS)
|
|
||||||
┌───────────────────────────────▼─────────────────────────────────────────┐
|
|
||||||
│ MindSift Single Container (Go 1.24) │
|
|
||||||
│ │
|
|
||||||
│ ┌─────────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
|
|
||||||
│ │ Embedded Assets │ │ Chi HTTP Mux │ │ WebSocket Hub │ │
|
|
||||||
│ │ (React SPA Dist) │ │ REST / Webhook │ │ (Realtime Sync) │ │
|
|
||||||
│ └─────────────────────┘ └────────┬────────┘ └────────┬────────┘ │
|
|
||||||
│ │ │ │
|
|
||||||
│ ┌───────▼─────────────────────▼────────┐ │
|
|
||||||
│ │ Business Service Layer │ │
|
|
||||||
│ │ (Capture, Triage, Docs, Lists) │ │
|
|
||||||
│ └──────────────────┬───────────────────┘ │
|
|
||||||
│ │ │
|
|
||||||
│ ┌──────────────────▼───────────────────┐ │
|
|
||||||
│ │ Data Access Layer (sqlc / WAL) │ │
|
|
||||||
│ └──────────────────┬───────────────────┘ │
|
|
||||||
└─────────────────────────────────────────────────┼───────────────────────┘
|
|
||||||
│
|
|
||||||
┌──────────────────▼───────────────────┐
|
|
||||||
│ SQLite 3 (WAL Mode, zero-config) │
|
|
||||||
│ *Optional: PostgreSQL Driver │
|
|
||||||
└──────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### Stack-Entscheidungen & Rationale
|
Lege eine `docker-compose.yml` an:
|
||||||
|
|
||||||
| Schicht | Technologie | Begründung & Architekturentscheidung |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| **Backend** | **Go 1.24+ (Chi Router)** | Extrem geringer Speicherverbrauch (~15–25 MB RAM idle), Kaltstart in < 5 ms, überlegene Concurrency für WebSockets, erzeugt ein statisches Binary. |
|
|
||||||
| **Frontend** | **React 19 + TypeScript + Vite** | Bietet mit **Framer Motion** die beste Gesten- und Physik-Engine für flüssige Tinder-Swipes und mit **Tiptap** den industrieweit führenden blockbasierten Rich-Text-Editor. |
|
|
||||||
| **Styling** | **Tailwind CSS v4** | Höchste Performance, null CSS-Runtime-Overhead, perfekte Abbildung des Deep Dark Themes mit Design-Tokens. |
|
|
||||||
| **Realtime** | **Go WebSockets (`nhooyr/websocket`)** | Schlanke, native WebSocket-Rooms für kollaborative Einkaufslisten mit Sub-10ms-Latenz und automatischem Reconnect. |
|
|
||||||
| **Datenbank** | **SQLite (WAL-Modus) / sqlc** | Standardmäßig Zero-Config mit Write-Ahead-Logging, ACID-sicher und als einzelne Datei einfachst per Backup sicherbar. Optional umschaltbar auf PostgreSQL per `DATABASE_URL`. |
|
|
||||||
| **PWA / Offline** | **Workbox / IndexedDB** | App startet auch im Funkloch sofort; Gedanken werden lokal vorgehalten und beim nächsten Verbindungsaufbau transparent synchronisiert. |
|
|
||||||
| **Container** | **Distroless / Alpine Scratch** | Minimalistisches Multi-Stage Dockerfile. End-Image-Größe < 35 MB. Keine Sicherheitsrisiken durch überflüssige System-Pakete. |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🗄️ Datenbankschema
|
|
||||||
|
|
||||||
Das Schema ist relational strukturiert, normalisiert und auf Lese- sowie Schreibgeschwindigkeit im Sub-Millisekundenbereich optimiert.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
erDiagram
|
|
||||||
USERS ||--o{ THOUGHTS : owns
|
|
||||||
USERS ||--o{ DOCUMENTS : authors
|
|
||||||
USERS ||--o{ SPACE_MEMBERS : participates
|
|
||||||
USERS ||--o{ API_KEYS : possesses
|
|
||||||
SPACES ||--o{ SPACE_MEMBERS : contains
|
|
||||||
SPACES ||--o{ LISTS : hosts
|
|
||||||
LISTS ||--o{ LIST_ITEMS : contains
|
|
||||||
DOCUMENTS ||--o{ DOCUMENT_BLOCKS : contains
|
|
||||||
|
|
||||||
USERS {
|
|
||||||
uuid id PK
|
|
||||||
string email UK
|
|
||||||
string password_hash
|
|
||||||
string display_name
|
|
||||||
timestamp created_at
|
|
||||||
}
|
|
||||||
|
|
||||||
THOUGHTS {
|
|
||||||
uuid id PK
|
|
||||||
uuid user_id FK
|
|
||||||
text content
|
|
||||||
string voice_transcript
|
|
||||||
string status "inbox | kept | discarded | converted"
|
|
||||||
string converted_type "task | document | list_item"
|
|
||||||
uuid converted_ref_id
|
|
||||||
timestamp due_date
|
|
||||||
timestamp created_at
|
|
||||||
timestamp triaged_at
|
|
||||||
}
|
|
||||||
|
|
||||||
DOCUMENTS {
|
|
||||||
uuid id PK
|
|
||||||
uuid user_id FK
|
|
||||||
uuid space_id FK
|
|
||||||
string title
|
|
||||||
string icon
|
|
||||||
boolean is_archived
|
|
||||||
timestamp created_at
|
|
||||||
timestamp updated_at
|
|
||||||
}
|
|
||||||
|
|
||||||
DOCUMENT_BLOCKS {
|
|
||||||
uuid id PK
|
|
||||||
uuid document_id FK
|
|
||||||
string block_type "paragraph | heading | task | code"
|
|
||||||
jsonb content
|
|
||||||
int sort_order
|
|
||||||
timestamp updated_at
|
|
||||||
}
|
|
||||||
|
|
||||||
SPACES {
|
|
||||||
uuid id PK
|
|
||||||
string name
|
|
||||||
string icon
|
|
||||||
boolean is_personal
|
|
||||||
timestamp created_at
|
|
||||||
}
|
|
||||||
|
|
||||||
SPACE_MEMBERS {
|
|
||||||
uuid space_id PK,FK
|
|
||||||
uuid user_id PK,FK
|
|
||||||
string role "owner | editor | viewer"
|
|
||||||
timestamp joined_at
|
|
||||||
}
|
|
||||||
|
|
||||||
LISTS {
|
|
||||||
uuid id PK
|
|
||||||
uuid space_id FK
|
|
||||||
string title
|
|
||||||
string list_type "shopping | checklist"
|
|
||||||
timestamp updated_at
|
|
||||||
}
|
|
||||||
|
|
||||||
LIST_ITEMS {
|
|
||||||
uuid id PK
|
|
||||||
uuid list_id FK
|
|
||||||
string content
|
|
||||||
boolean is_completed
|
|
||||||
uuid completed_by FK
|
|
||||||
timestamp completed_at
|
|
||||||
int sort_order
|
|
||||||
}
|
|
||||||
|
|
||||||
API_KEYS {
|
|
||||||
uuid id PK
|
|
||||||
uuid user_id FK
|
|
||||||
string name
|
|
||||||
string key_hash UK
|
|
||||||
string scopes
|
|
||||||
timestamp last_used_at
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### SQL DDL Definitionen (Auszug SQLite / Postgres kompatibel)
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- Aktivierung von WAL & Foreign Keys für SQLite
|
|
||||||
PRAGMA journal_mode = WAL;
|
|
||||||
PRAGMA foreign_keys = ON;
|
|
||||||
PRAGMA busy_timeout = 5000;
|
|
||||||
|
|
||||||
-- Gedanken & Instant Inbox Puffer
|
|
||||||
CREATE TABLE IF NOT EXISTS thoughts (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
user_id TEXT NOT NULL,
|
|
||||||
content TEXT NOT NULL,
|
|
||||||
status TEXT CHECK(status IN ('inbox', 'kept', 'discarded', 'converted')) DEFAULT 'inbox',
|
|
||||||
converted_type TEXT CHECK(converted_type IN ('task', 'document', 'list_item', NULL)),
|
|
||||||
converted_ref_id TEXT,
|
|
||||||
due_date DATETIME,
|
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
triaged_at DATETIME,
|
|
||||||
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX idx_thoughts_user_status ON thoughts(user_id, status, created_at DESC);
|
|
||||||
|
|
||||||
-- Kollaborative Listen (z.B. Familie & Einkaufen)
|
|
||||||
CREATE TABLE IF NOT EXISTS list_items (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
list_id TEXT NOT NULL,
|
|
||||||
content TEXT NOT NULL,
|
|
||||||
is_completed BOOLEAN NOT NULL DEFAULT 0,
|
|
||||||
completed_by TEXT,
|
|
||||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
completed_at DATETIME,
|
|
||||||
FOREIGN KEY(list_id) REFERENCES lists(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX idx_list_items_sync ON list_items(list_id, is_completed, sort_order ASC);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔌 API-Spezifikation & Webhooks
|
|
||||||
|
|
||||||
Alle Endpunkte antworten mit `application/json` und nutzen Standard-HTTP-Statuscodes. Die Authentifizierung erfolgt über `Bearer <JWT>` oder dedizierte Ingestion-Keys.
|
|
||||||
|
|
||||||
### 1. Instant Capture & Ingestion (Sub-Second Entry)
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /api/v1/inbox
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"content": "Zündkerzen für den Rasenmäher bestellen #garage",
|
|
||||||
"due_date": "2026-10-25T18:00:00Z" // Optional
|
|
||||||
}
|
|
||||||
```
|
|
||||||
**Response (201 Created - < 30ms):**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "th_9f8a3c21",
|
|
||||||
"status": "inbox",
|
|
||||||
"created_at": "2026-10-24T16:25:00Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Smarthome & Externe Webhook Ingestion
|
|
||||||
|
|
||||||
Für Home Assistant, Node-RED, n8n oder Shell-Skripte:
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /api/v1/webhooks/ingest?token=mindsift_sec_789xyz
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"title": "Kellerfeuchtigkeit über 70%",
|
|
||||||
"priority": "urgent",
|
|
||||||
"tags": ["smarthome", "keller"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Triage & Tinder-Style Swipe Deck
|
|
||||||
|
|
||||||
* **Gedanken-Deck laden:** `GET /api/v1/triage/deck?limit=20`
|
|
||||||
* **Gedanke wischen (Swipe Action):**
|
|
||||||
```http
|
|
||||||
PATCH /api/v1/triage/th_9f8a3c21
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"action": "keep", // oder "discard"
|
|
||||||
"convert_to": "task", // optional: "task" | "document" | "list_item"
|
|
||||||
"target_list_id": "lst_shopping_123", // wenn convert_to = "list_item"
|
|
||||||
"due_date": "2026-10-28T09:00:00Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Realtime WebSocket Protocol (Kollaborative Listen)
|
|
||||||
|
|
||||||
Client verbindet sich zu `wss://mindsift.local/api/v1/ws/spaces/:space_id`.
|
|
||||||
|
|
||||||
* **Event: Item hinzugefügt/aktualisiert**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"event": "ITEM_UPDATED",
|
|
||||||
"payload": {
|
|
||||||
"list_id": "lst_shopping_123",
|
|
||||||
"item_id": "itm_456",
|
|
||||||
"content": "Hafermilch (Barista)",
|
|
||||||
"is_completed": true,
|
|
||||||
"user_name": "Sandro"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Gitea CI/CD Pipeline
|
|
||||||
|
|
||||||
Das Projekt ist für den Betrieb mit **Gitea Actions** optimiert. Bei jedem Push auf `main` oder einem Release-Tag baut die Pipeline automatisch ein Multi-Arch-Docker-Image (`linux/amd64`, `linux/arm64`) und schiebt es in die Gitea Container Registry.
|
|
||||||
|
|
||||||
### Workflow-Datei: `.gitea/workflows/build-and-publish.yaml`
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
name: MindSift Multi-Arch Docker Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
tags:
|
|
||||||
- 'v*'
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
name: Lint & Unit Tests
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout Code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: '1.24'
|
|
||||||
cache: true
|
|
||||||
|
|
||||||
- name: Run Backend Tests
|
|
||||||
run: |
|
|
||||||
go vet ./...
|
|
||||||
go test -v -race ./...
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '22'
|
|
||||||
cache: 'npm'
|
|
||||||
cache-dependency-path: frontend/package-lock.json
|
|
||||||
|
|
||||||
- name: Run Frontend Tests
|
|
||||||
run: |
|
|
||||||
cd frontend
|
|
||||||
npm ci
|
|
||||||
npm run lint
|
|
||||||
npm run test:run
|
|
||||||
|
|
||||||
build-docker:
|
|
||||||
name: Build & Push Docker Image
|
|
||||||
needs: test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name == 'push'
|
|
||||||
steps:
|
|
||||||
- name: Checkout Code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up QEMU (Multi-Arch)
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Login to Gitea Container Registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ${{ gitea.server_url }}
|
|
||||||
username: ${{ gitea.actor }}
|
|
||||||
password: ${{ secrets.GITEA_TOKEN }}
|
|
||||||
|
|
||||||
- name: Extract Metadata
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: ${{ gitea.server_url }}/${{ gitea.repository }}
|
|
||||||
tags: |
|
|
||||||
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
|
|
||||||
- name: Build and Push
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
```
|
|
||||||
|
|
||||||
### Multi-Stage Dockerfile (`Dockerfile`)
|
|
||||||
|
|
||||||
```dockerfile
|
|
||||||
# Stage 1: Frontend Build
|
|
||||||
FROM node:22-alpine AS frontend-builder
|
|
||||||
WORKDIR /app/frontend
|
|
||||||
COPY frontend/package*.json ./
|
|
||||||
RUN npm ci
|
|
||||||
COPY frontend/ ./
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# Stage 2: Go Backend Build
|
|
||||||
FROM golang:1.24-alpine AS backend-builder
|
|
||||||
WORKDIR /app
|
|
||||||
RUN apk add --no-cache build-base git
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
RUN go mod download
|
|
||||||
COPY . .
|
|
||||||
# Kopiere gebaute Frontend Assets in das embed.FS-Verzeichnis
|
|
||||||
COPY --from=frontend-builder /app/frontend/dist ./server/dist
|
|
||||||
RUN CGO_ENABLED=1 GOOS=linux go build -ldflags="-s -w -extldflags '-static'" -o mindsift ./cmd/server
|
|
||||||
|
|
||||||
# Stage 3: Minimal Production Image
|
|
||||||
FROM alpine:3.21
|
|
||||||
RUN apk add --no-cache ca-certificates tzdata
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=backend-builder /app/mindsift /app/mindsift
|
|
||||||
|
|
||||||
ENV PORT=8080
|
|
||||||
ENV DATA_DIR=/data
|
|
||||||
VOLUME ["/data"]
|
|
||||||
|
|
||||||
EXPOSE 8080
|
|
||||||
USER 1000:1000
|
|
||||||
ENTRYPOINT ["/app/mindsift"]
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐳 Deployment & Schnellstart
|
|
||||||
|
|
||||||
### 1. Schnellstart mit Docker Compose (Empfohlen)
|
|
||||||
|
|
||||||
Erstelle eine `docker-compose.yml`:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
mindsift:
|
mindsift:
|
||||||
image: gitea.your-domain.com/user/mindsift:latest
|
image: git.dsit.me/sandrodach/mindsift:dev
|
||||||
container_name: mindsift
|
container_name: mindsift
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
@@ -504,109 +93,39 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- PORT=8080
|
- PORT=8080
|
||||||
- DATA_DIR=/data
|
- DATA_DIR=/data
|
||||||
- JWT_SECRET=change_this_to_a_secure_random_key_min_32_chars
|
- JWT_SECRET=bitte-hier-ein-langes-sicheres-geheimnis-eintragen
|
||||||
- BASE_URL=https://mindsift.local
|
- ALLOW_REGISTRATION=false
|
||||||
- LOG_LEVEL=info
|
# Optional: Eigener SMTP-Server für E-Mail-Alarme
|
||||||
|
# (kann alternativ auch später direkt in der Admin-Oberfläche eingetragen werden)
|
||||||
|
- SMTP_HOST=
|
||||||
|
- SMTP_PORT=587
|
||||||
|
- SMTP_USER=
|
||||||
|
- SMTP_PASS=
|
||||||
|
- SMTP_FROM=
|
||||||
|
- SMTP_TLS=true
|
||||||
```
|
```
|
||||||
|
|
||||||
Starte den Service:
|
Container starten:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
Die Weboberfläche steht sofort unter `http://localhost:8080` bereit.
|
|
||||||
|
|
||||||
### 2. Standalone Docker Run
|
Öffne anschließend **`http://localhost:8080`** im Browser. Beim allerersten Aufruf führt dich MindSift automatisch durch die **Ersteinrichtung** für dein Administrator-Konto.
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run -d \
|
|
||||||
--name mindsift \
|
|
||||||
--restart unless-stopped \
|
|
||||||
-p 8080:8080 \
|
|
||||||
-v $(pwd)/mindsift-data:/data \
|
|
||||||
-e JWT_SECRET="dein-super-sicheres-geheimnis" \
|
|
||||||
gitea.your-domain.com/user/mindsift:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
### Umgebungsvariablen
|
|
||||||
|
|
||||||
| Variable | Standardwert | Beschreibung |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| `PORT` | `8080` | Interner HTTP/WebSocket Port |
|
|
||||||
| `DATA_DIR` | `/data` | Verzeichnis für SQLite DB, Uploads und Cache |
|
|
||||||
| `DATABASE_URL` | `sqlite:///data/mindsift.db` | Optional: PostgreSQL DSN (`postgres://user:pass@host:5432/db`) |
|
|
||||||
| `JWT_SECRET` | *Pflichtfeld* | Secret für Authentifizierungs-Tokens (mind. 32 Zeichen) |
|
|
||||||
| `BASE_URL` | `http://localhost:8080` | Externe URL für Einladungslinks und Webhooks |
|
|
||||||
| `ALLOW_REGISTRATION`| `true` | Erstregistrierung erlauben (`false` nach Admin-Erstellung) |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🗺️ Schrittweiser Phasenplan
|
## 🔒 Deine Daten gehören dir
|
||||||
|
|
||||||
```
|
* **100 % Self-Hosted:** Keine externen Cloud-Dienste, keine versteckte Telemetrie, kein Tracking.
|
||||||
Phase 1: Foundation ────► Phase 2: Triage Deck ────► Phase 3: Workspace
|
* **Portabel & Transparent:** Alle Workspace-Notizen liegen als lesbare Markdown-Dateien im Datenverzeichnis; zusätzlich kannst du jederzeit ein komplettes Backup deiner Daten als JSON-Datei herunterladen.
|
||||||
(Go + PWA + DB) (Framer Physics) (Tiptap Blocks)
|
|
||||||
│
|
|
||||||
Phase 6: Hardening ◄──── Phase 5: Webhooks ◄──── Phase 4: Realtime
|
|
||||||
(CI/CD + Release) (Smarthome Ingest) (Family Lists)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Phase 1: Core Foundation & Instant Capture (Sprint 1)
|
|
||||||
- [x] Repository-Initialisierung & Architektur-Design
|
|
||||||
- [x] Go Backend-Grundgerüst (Chi Router, Konfigurations-Management, Healthcheck)
|
|
||||||
- [x] SQLite Storage-Layer mit WAL-Modus und automatischer Migration
|
|
||||||
- [x] JWT-Authentifizierung & User-Management
|
|
||||||
- [x] Mobile-First PWA Setup (Vite, React, Tailwind CSS, Deep Dark Theme)
|
|
||||||
- [x] **Instant-Capture-Interface:** Autofokus-Eingabemaske, Sprachaufnahme (Web Speech API), Latenz < 300 ms
|
|
||||||
|
|
||||||
### Phase 2: Tinder-Style Triage & Task Engine (Sprint 2)
|
|
||||||
- [x] Interaktives Swipe-Deck mit **Framer Motion** (Gesten, Rotation, elastische Rückfederung)
|
|
||||||
- [x] Triage-Status-Engine (`inbox` -> `kept` / `discarded` / `converted`)
|
|
||||||
- [x] Quick-Convert: Wisch nach rechts transformiert Gedanken direkt in Aufgaben mit Due-Date, Projekt-Notizen oder Listen-Einträge
|
|
||||||
- [x] Tastatur-Shortcuts für Power-User am Desktop (`H`/`L` oder Pfeiltasten, `C`/`/` für Capture)
|
|
||||||
- [x] Haptisches Feedback auf Mobilgeräten (Web Vibration API)
|
|
||||||
|
|
||||||
### Phase 3: Notion-Style Workspace (Sprint 3)
|
|
||||||
- [x] Block-Editor (Headings, Task-Checkboxes, Code-Blöcke, Callouts, Listen)
|
|
||||||
- [x] Dokumenten-Verwaltung für vertiefte Gedanken inkl. Pinning & Icon-Picker
|
|
||||||
- [x] Tagging & Volltextsuche über Gedanken und Dokumente
|
|
||||||
- [x] Markdown Export (`.md`)
|
|
||||||
|
|
||||||
### Phase 4: Realtime Spaces & Family Sync (Sprint 4)
|
|
||||||
- [x] Multi-User Space-Architektur (Familien- und Team-Räume mit Invite-Codes)
|
|
||||||
- [x] Go WebSocket Hub mit Raum-Multiplexing
|
|
||||||
- [x] Echtzeit-Einkaufslisten: Sofortige Synchronisation von Checked-States über alle Endgeräte
|
|
||||||
- [x] Optimistische UI-Updates für verzögerungsfreies Offline-/Online-Erlebnis
|
|
||||||
|
|
||||||
### Phase 5: Smarthome Webhooks & External Ecosystem (Sprint 5)
|
|
||||||
- [x] Ingestion-API mit API-Token-Management (`mindsift_sec_...`)
|
|
||||||
- [x] Webhook-Endpunkte für Home Assistant, Zigbee2MQTT, n8n und Cronjobs
|
|
||||||
- [x] Interaktiver Live-Webhook-Simulator in der UI
|
|
||||||
- [x] Backup- und Export-Endpunkt (kompletter JSON-Export)
|
|
||||||
|
|
||||||
### Phase 6: Production Hardening, CI/CD & v1.0 (Sprint 6)
|
|
||||||
- [x] Gitea Actions Multi-Arch Workflow (`amd64`, `arm64`)
|
|
||||||
- [x] Single-Container Packaging (`embed.FS`) & Multi-Stage Dockerfile
|
|
||||||
- [x] Automatisierte Backend-Unit-Tests (`internal/storage/sqlite_test.go`)
|
|
||||||
- [ ] End-to-End Tests (Playwright) auf Ziel-Cluster
|
|
||||||
- [x] Erstellung der offiziellen Dokumentation & v1.0 Release-Bereitschaft
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔒 Sicherheit & Datenschutz
|
|
||||||
|
|
||||||
* **Zero Tracking:** Keine Analytics, keine externen CDNs, keine Telemetrie.
|
|
||||||
* **Content Security Policy (CSP):** Strikte Header; alle Assets und Fonts werden lokal ausgeliefert.
|
|
||||||
* **Sichere Passwörter:** Argon2id Passwort-Hashing nach OWASP-Empfehlung.
|
|
||||||
* **Isolierte Container:** Der Container läuft standardmäßig unter einer Non-Root-UID (`1000:1000`).
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📄 Lizenz
|
## 📄 Lizenz
|
||||||
|
|
||||||
Dieses Projekt ist lizenziert unter der **MIT-Lizenz** – siehe [LICENSE](LICENSE) für Details.
|
Veröffentlicht unter der **MIT-Lizenz** – siehe [LICENSE](LICENSE).
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<sub>Designed with ❤️ for clarity, speed and digital sovereignty.</sub>
|
<sub>Gebaut für maximale Klarheit, Geschwindigkeit und digitale Souveränität.</sub>
|
||||||
</div>
|
</div>
|
||||||
Reference in new issue
Block a user