diff --git a/AGENTS.md b/AGENTS.md
index b007ef6..50e43c3 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -38,6 +38,12 @@ Die Linter-Warnungen `react-hooks/exhaustive-deps` gibt es schon länger; neuer
```
- **Zeitabhängiger Code** (Alarme, Tageszusammenfassung, Begrüßungen, Termine): nie `time.Now()` dort, wo eine übergebene Zeit gemeint ist. Die betroffenen Go-Tests zusätzlich mit verschiedenen `TZ`-Werten laufen lassen (z. B. `Europe/Berlin`, `America/Los_Angeles`, `Asia/Tokyo`). Ein uhrzeitabhängiger Test hat schon einmal einen Release verhindert, weil er nur vormittags grün war.
+## Screenshots
+
+- Bilder in `screenshots/` (README) sind **WebP**, keine PNG: Desktop und Theme-Raster 1280 px breit, Handy 480 px, Qualität 90. Das bringt rund ein Fünftel der PNG-Größe bei sauberer Schrift.
+- Erzeugt werden sie mit `e2e/screenshots.sh`; das Skript nimmt PNGs auf und wandelt sie am Ende mit `cwebp` (Alpine-Container) um. Einzelne Bilder neu aufnehmen: denselben Ablauf aus `screenshots.mjs` verwenden und mit dem Umwandlungsschritt aus `screenshots.sh` konvertieren.
+- Chromiums eigenes WebP (`canvas.toDataURL('image/webp')`) nicht verwenden: verlustfrei wird es größer als die PNG.
+
## Release-Ablauf
**Committen** ist jederzeit erlaubt. **Jeder Push ist ein Release**, also mit Version und CHANGELOG-Eintrag.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d9c55f..7220df3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,14 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die V
## [Unreleased]
+## [0.26.0] - 2026-10-31
+
+### Added
+- Verbindungsstatus im Kopf: Ist der Server nicht erreichbar, steht am Desktop unter deinem Namen klein „● offline“ mit rotem Punkt; die Seite bleibt bedienbar. Am Handy zeigt ein kleiner Punkt unten rechts am Profilbild den Status (grün online, rot offline). Das funktioniert auch, wenn nur der Server ausgefallen ist und das Gerät selbst noch Netz hat – bisher war das nur in den Listen zu sehen.
+
+### Changed
+- Screenshots im README sind jetzt kleinere WebP-Bilder (zusammen etwa 0,5 statt 2,7 MB); das Journal-Bild zeigt die aktuelle Ansicht.
+
## [0.25.1] - 2026-10-31
### Fixed
@@ -519,7 +527,8 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die V
- Geteilte Listen (Einkaufs-, Pack- und Checklisten) mit `#Kategorie`-Gruppierung, Mengenangaben und Echtzeit-Abhaken.
- Benutzer-, Gruppen- und Admin-Verwaltung (Ersteinrichtungs-Assistent, Einladungscodes, Profilbilder, persönliche API-Keys & Webhook-Ingest `/api/v1/webhooks/ingest`, JSON-Datenexport) sowie CSS-Theme-Engine mit 4 Themes (`Dark`, `Light`, `High Contrast`, `Soft`) und PWA-Unterstützung.
-[Unreleased]: https://git.dsit.me/sandrodach/MindSift/compare/v0.25.1...dev
+[Unreleased]: https://git.dsit.me/sandrodach/MindSift/compare/v0.26.0...dev
+[0.26.0]: https://git.dsit.me/sandrodach/MindSift/compare/v0.25.1...v0.26.0
[0.25.1]: https://git.dsit.me/sandrodach/MindSift/compare/v0.25.0...v0.25.1
[0.25.0]: https://git.dsit.me/sandrodach/MindSift/compare/v0.24.2...v0.25.0
[0.24.2]: https://git.dsit.me/sandrodach/MindSift/compare/v0.24.1...v0.24.2
diff --git a/Doku/architecture.md b/Doku/architecture.md
index 49d1c6a..854d3c3 100644
--- a/Doku/architecture.md
+++ b/Doku/architecture.md
@@ -162,6 +162,7 @@ Die Tests laufen beim Image-Build (Frontend: `npm run test:run`, Backend: `go te
- **Lese-Cache** ([lib/offline.ts](../frontend/src/lib/offline.ts)): Jede erfolgreiche GET-Antwort landet pro Benutzer in IndexedDB (`mindsift-offline`). Ohne Verbindung liefert `request()` die letzte bekannte Antwort; so startet die App offline angemeldet und zeigt Gedanken, Aufgaben und Listen. Ausgenommen: Streams, Long-Polling, Notiz-Sync (eigener Speicher, [modules/collaboration.md](modules/collaboration.md)), Export, Suche. Abmelden leert Cache und Warteschlange.
- **Warteschlange (Outbox):** Offline erfasste Gedanken (`POST /inbox`) und abgehakte Aufgaben bzw. Listeneinträge (`PATCH`) werden in `localStorage` gesammelt, wiederholtes Umschalten zählt nur mit dem Endstand. Gesendet wird in Reihenfolge beim `online`-Ereignis, beim Start und alle 30 s, solange etwas wartet; vom Server abgelehnte Einträge (4xx) entfallen. Andere Änderungen brauchen weiterhin eine Verbindung.
- **Hinweis:** Ein Banner über der unteren Navigation zeigt „Offline“ und die Zahl wartender Änderungen bzw. „Synchronisiere…“.
+- **Verbindungsstatus im Kopf** ([lib/useServerOnline.ts](../frontend/src/lib/useServerOnline.ts)): Maßgeblich ist die app-weite Echtzeit-Verbindung (WebSocket/SSE), nicht `navigator.onLine`; so fällt auch ein ausgefallener Server auf. Offline gilt erst nach 4 s ohne Verbindung (Start, kurze Reconnects), ohne Gerätenetz sofort. Desktop: „● offline“ unter dem Namen, nur ohne Verbindung; Handy: Punkt am Profilbild, grün oder rot.
## App-Icons, PWA & Social-Preview (Open Graph)
diff --git a/README.md b/README.md
index 37f3f4f..8398b63 100644
--- a/README.md
+++ b/README.md
@@ -6,12 +6,12 @@
[](#)
[](#-schnellstart)
[](#-deine-daten-gehören-dir)
-[](CHANGELOG.md)
+[](CHANGELOG.md)
**MindSift** ist eine selbst gehostete Schaltstelle für spontane Gedanken, Aufgaben mit Kanban-Board, hierarchische Outliner-Notizen, die mehrere Personen gleichzeitig bearbeiten können, und gemeinsame Listen. Alles läuft als ein einzelner Container mit eingebetteter SQLite-Datenbank, auf deinem eigenen Server.
-
+
Links das helle, rechts das dunkle Theme.
@@ -43,9 +43,9 @@ Die meisten Notiz- und Aufgaben-Apps verlangen Struktur im falschen Moment: Wenn
* Papierkorb mit Wiederherstellen.
-
+
-
+
### ✅ Aufgaben & Kanban
@@ -61,7 +61,7 @@ Die meisten Notiz- und Aufgaben-Apps verlangen Struktur im falschen Moment: Wenn
* **Alarme & Benachrichtigungen:** Fälligkeits-Alarme sofort, alle übrigen Ereignisse (Freigaben, erledigte geteilte Aufgaben, beobachtete Aufgaben) gebündelt; pro Ereignis wählbar über E-Mail, Discord, eigenen Webhook und Push.
-
+
### 📝 Workspace: Outliner-Notizen
@@ -88,11 +88,11 @@ Die meisten Notiz- und Aufgaben-Apps verlangen Struktur im falschen Moment: Wenn
Technik dahinter: [Doku/modules/collaboration.md](Doku/modules/collaboration.md).
-
+
-
+
### 🛒 Geteilte Listen
@@ -101,7 +101,7 @@ Technik dahinter: [Doku/modules/collaboration.md](Doku/modules/collaboration.md)
* Freigabe an Benutzer und Gruppen (Bearbeiter oder Leser); abgehakte Einträge erscheinen bei allen in Echtzeit.
-
+
### 🏢 Benutzer, Gruppen, Administration
@@ -117,12 +117,12 @@ Technik dahinter: [Doku/modules/collaboration.md](Doku/modules/collaboration.md)
-  Fjord |
-  Terrakotta |
+  Fjord |
+  Terrakotta |
-  Polarized |
-  Suri |
+  Polarized |
+  Suri |
diff --git a/e2e/README.md b/e2e/README.md
index 28a892f..1571c4a 100644
--- a/e2e/README.md
+++ b/e2e/README.md
@@ -40,4 +40,4 @@ Der Eigentümer tippt mit normaler Verbindung, der Bearbeiter sitzt hinter einem
## Screenshots
-`e2e/screenshots.sh` baut das Image, startet es im Demo-Modus mit frischer Datenbank und erzeugt die Bilder in `screenshots/` neu (`screenshots.mjs`). Für die Versionsangabe im Kopf: `APP_VERSION=v0.2 e2e/screenshots.sh`. In der Workspace-Aufnahme bearbeitet der Demo-Benutzer `user` gleichzeitig einen Bullet, damit Sperre und Präsenz zu sehen sind.
+`e2e/screenshots.sh` baut das Image, startet es im Demo-Modus mit frischer Datenbank und erzeugt die Bilder in `screenshots/` neu (`screenshots.mjs`). Danach werden sie verkleinert (Desktop 1280 px, Handy 480 px breit) und als WebP mit Qualität 90 gespeichert (`cwebp` in einem Alpine-Container). Für die Versionsangabe im Kopf: `APP_VERSION=v0.2 e2e/screenshots.sh`. In der Workspace-Aufnahme bearbeitet der Demo-Benutzer `user` gleichzeitig einen Bullet, damit Sperre und Präsenz zu sehen sind.
diff --git a/e2e/screenshots.mjs b/e2e/screenshots.mjs
index aa9c590..bd00eb0 100644
--- a/e2e/screenshots.mjs
+++ b/e2e/screenshots.mjs
@@ -196,7 +196,10 @@ const main = async () => {
await page.getByRole('button', { name: 'Heute' }).click().catch(() => {});
await page.mouse.click(1000, 860);
await sleep(2500);
+ // Round corners (setting "Ecken: rund") for this picture only
+ await page.evaluate(() => document.documentElement.setAttribute('data-corners', 'round'));
await plain(page, 'journal_desktop.png', 'dark');
+ await page.evaluate(() => document.documentElement.removeAttribute('data-corners'));
await page.getByRole('button', { name: 'Journal', exact: true }).click(); // close it again
await tab(page, 'Listen');
diff --git a/e2e/screenshots.sh b/e2e/screenshots.sh
index 0818b7f..2b5da39 100755
--- a/e2e/screenshots.sh
+++ b/e2e/screenshots.sh
@@ -1,6 +1,7 @@
#!/usr/bin/env bash
# Builds MindSift, starts it in demo mode with a fresh database and renews the README screenshots
# in screenshots/ (title picture and colour-family grid: light and dark joined along a diagonal).
+# The PNGs from the browser are scaled down (desktop 1280 px, phone 480 px wide) and saved as WebP.
# Requires podman (or docker via ENGINE=docker). Usage: e2e/screenshots.sh, other theme pair: SHOT_LIGHT=fjord SHOT_DARK=fjord-night
set -euo pipefail
ENGINE="${ENGINE:-podman}"
@@ -21,6 +22,7 @@ cleanup() {
rm -rf "$WORK"
}
trap cleanup EXIT
+mkdir -p "$WORK/png"
echo "Baue Image …"
# Version in the header, e.g. APP_VERSION=v0.2 e2e/screenshots.sh
@@ -32,5 +34,14 @@ for _ in $(seq 1 60); do curl -s -m 1 "http://localhost:$PORT/api/v1/health" >/d
echo "Erstelle Screenshots …"
"$ENGINE" run --rm --network host -e MINDSIFT_URL="http://localhost:$PORT" -e SHOTS_DIR=/shots \
-e SHOT_LIGHT="${SHOT_LIGHT:-light}" -e SHOT_DARK="${SHOT_DARK:-dark}" -e LANG=de_DE.UTF-8 -e TZ=Europe/Berlin \
- -v "$ROOT/e2e":/e2e:Z -v "$ROOT/screenshots":/shots:Z -w /e2e mcr.microsoft.com/playwright:v1.48.2-jammy \
+ -v "$ROOT/e2e":/e2e:Z -v "$WORK/png":/shots:Z -w /e2e mcr.microsoft.com/playwright:v1.48.2-jammy \
sh -c 'npm install --no-audit --no-fund >/dev/null 2>&1 && node screenshots.mjs'
+
+echo "Wandle in WebP um …"
+"$ENGINE" run --rm -v "$WORK/png":/png:Z -v "$ROOT/screenshots":/shots:Z docker.io/library/alpine:3.20 sh -c '
+ apk add -q libwebp-tools >/dev/null
+ for f in /png/*.png; do
+ name=$(basename "$f" .png)
+ case "$name" in Mobile_*) width=480 ;; *) width=1280 ;; esac
+ cwebp -quiet -resize "$width" 0 -q 90 -m 6 -metadata none "$f" -o "/shots/$name.webp"
+ done'
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 6069a46..c238685 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "mindsift-frontend",
- "version": "0.25.1",
+ "version": "0.26.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mindsift-frontend",
- "version": "0.25.1",
+ "version": "0.26.0",
"license": "Unlicense",
"dependencies": {
"@fontsource-variable/inter": "5.3.0",
diff --git a/frontend/package.json b/frontend/package.json
index c4df013..68cfb16 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,7 +1,7 @@
{
"name": "mindsift-frontend",
"private": true,
- "version": "0.25.1",
+ "version": "0.26.0",
"license": "Unlicense",
"type": "module",
"scripts": {
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 358a61c..6112909 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -56,6 +56,7 @@ import { WorkspaceView } from './features/workspace/WorkspaceView';
import { SharedListsView } from './features/lists/SharedListsView';
import { SetupAndAuthView } from './features/auth/SetupAndAuthView';
import { OfflineBanner } from './components/OfflineBanner';
+import { useServerOnline } from './lib/useServerOnline';
import { SharedImportToast } from './components/SharedImportToast';
import { outboxCount, clearOfflineData } from './lib/offline';
import { DemoCountdown } from './components/DemoCountdown';
@@ -179,6 +180,7 @@ export const App: React.FC = () => {
// Profile Dropdown State
const [showProfileMenu, setShowProfileMenu] = useState(false);
+ const serverOnline = useServerOnline();
const [showAbout, setShowAbout] = useState(false);
const dropdownRef = useRef(null);
@@ -947,7 +949,17 @@ export const App: React.FC = () => {
}`}
title="Profil & Einstellungen"
>
-
+
+
+ {/* Connection status like in a chat app: green online, red without server */}
+
+
@@ -1013,8 +1025,20 @@ export const App: React.FC = () => {
title="Benutzermenü öffnen"
>
-
- {user.displayName}
+
+
+ {user.displayName}
+
+ {!serverOnline && (
+
+
+ offline
+
+ )}
diff --git a/frontend/src/lib/__tests__/useServerOnline.test.tsx b/frontend/src/lib/__tests__/useServerOnline.test.tsx
new file mode 100644
index 0000000..87764f8
--- /dev/null
+++ b/frontend/src/lib/__tests__/useServerOnline.test.tsx
@@ -0,0 +1,66 @@
+import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
+import { act, renderHook } from '@testing-library/react';
+
+let statusListener: ((connected: boolean) => void) | null = null;
+let currentConnected = false;
+vi.mock('../api', () => ({
+ onRealtimeStatus: (cb: (connected: boolean) => void) => {
+ statusListener = cb;
+ cb(currentConnected);
+ return () => (statusListener = null);
+ },
+}));
+
+import { useServerOnline, SERVER_OFFLINE_GRACE_MS } from '../useServerOnline';
+
+function setDeviceOnline(value: boolean) {
+ Object.defineProperty(navigator, 'onLine', { value, configurable: true });
+}
+
+describe('useServerOnline', () => {
+ beforeEach(() => {
+ vi.useFakeTimers();
+ currentConnected = false;
+ setDeviceOnline(true);
+ });
+ afterEach(() => vi.useRealTimers());
+
+ it('stays online during the grace period at app start', () => {
+ const { result } = renderHook(() => useServerOnline());
+ expect(result.current).toBe(true);
+ act(() => statusListener?.(true));
+ act(() => vi.advanceTimersByTime(SERVER_OFFLINE_GRACE_MS + 100));
+ expect(result.current).toBe(true);
+ });
+
+ it('turns offline once the server stays unreachable and back online on reconnect', () => {
+ currentConnected = true;
+ const { result } = renderHook(() => useServerOnline());
+ act(() => statusListener?.(false));
+ expect(result.current).toBe(true);
+ act(() => vi.advanceTimersByTime(SERVER_OFFLINE_GRACE_MS + 100));
+ expect(result.current).toBe(false);
+ act(() => statusListener?.(true));
+ expect(result.current).toBe(true);
+ });
+
+ it('repeated failed reconnects do not postpone the offline state', () => {
+ currentConnected = true;
+ const { result } = renderHook(() => useServerOnline());
+ for (let i = 0; i < 4; i++) {
+ act(() => statusListener?.(false));
+ act(() => vi.advanceTimersByTime(SERVER_OFFLINE_GRACE_MS / 2));
+ }
+ expect(result.current).toBe(false);
+ });
+
+ it('is offline right away without device network', () => {
+ currentConnected = true;
+ const { result } = renderHook(() => useServerOnline());
+ act(() => {
+ setDeviceOnline(false);
+ statusListener?.(false);
+ });
+ expect(result.current).toBe(false);
+ });
+});
diff --git a/frontend/src/lib/useServerOnline.ts b/frontend/src/lib/useServerOnline.ts
new file mode 100644
index 0000000..16d710b
--- /dev/null
+++ b/frontend/src/lib/useServerOnline.ts
@@ -0,0 +1,45 @@
+import { useEffect, useState } from 'react';
+import { onRealtimeStatus } from './api';
+
+// Grace period before a missing realtime connection counts as offline (app start, short reconnects)
+export const SERVER_OFFLINE_GRACE_MS = 4000;
+
+// Whether the server is reachable, judged by the app-wide realtime connection (WebSocket/SSE). Unlike
+// navigator.onLine it also notices a server that is down while the device still has network. Without
+// device network it is offline right away; otherwise only after the connection stayed away for a moment.
+export function useServerOnline(): boolean {
+ const [online, setOnline] = useState(true);
+
+ useEffect(() => {
+ let connected = false;
+ let timer: number | undefined;
+ // Reconnect attempts report "not connected" every few seconds; they must not restart the grace period
+ const update = () => {
+ if (connected) {
+ window.clearTimeout(timer);
+ timer = undefined;
+ setOnline(true);
+ } else if (navigator.onLine === false) {
+ window.clearTimeout(timer);
+ timer = undefined;
+ setOnline(false);
+ } else if (timer === undefined) {
+ timer = window.setTimeout(() => setOnline(false), SERVER_OFFLINE_GRACE_MS);
+ }
+ };
+ const unsubscribe = onRealtimeStatus((isConnected) => {
+ connected = isConnected;
+ update();
+ });
+ window.addEventListener('online', update);
+ window.addEventListener('offline', update);
+ return () => {
+ unsubscribe();
+ window.clearTimeout(timer);
+ window.removeEventListener('online', update);
+ window.removeEventListener('offline', update);
+ };
+ }, []);
+
+ return online;
+}
diff --git a/screenshots/Listen_desktop.png b/screenshots/Listen_desktop.png
deleted file mode 100644
index a710cf9..0000000
Binary files a/screenshots/Listen_desktop.png and /dev/null differ
diff --git a/screenshots/Listen_desktop.webp b/screenshots/Listen_desktop.webp
new file mode 100644
index 0000000..859100b
Binary files /dev/null and b/screenshots/Listen_desktop.webp differ
diff --git a/screenshots/Mobile_Triage.png b/screenshots/Mobile_Triage.png
deleted file mode 100644
index f4a0fbc..0000000
Binary files a/screenshots/Mobile_Triage.png and /dev/null differ
diff --git a/screenshots/Mobile_Triage.webp b/screenshots/Mobile_Triage.webp
new file mode 100644
index 0000000..24e9d10
Binary files /dev/null and b/screenshots/Mobile_Triage.webp differ
diff --git a/screenshots/Mobile_Workspace.png b/screenshots/Mobile_Workspace.png
deleted file mode 100644
index 4eb91f3..0000000
Binary files a/screenshots/Mobile_Workspace.png and /dev/null differ
diff --git a/screenshots/Mobile_Workspace.webp b/screenshots/Mobile_Workspace.webp
new file mode 100644
index 0000000..9d3b838
Binary files /dev/null and b/screenshots/Mobile_Workspace.webp differ
diff --git a/screenshots/Theme_fjord.png b/screenshots/Theme_fjord.png
deleted file mode 100644
index 619d1e6..0000000
Binary files a/screenshots/Theme_fjord.png and /dev/null differ
diff --git a/screenshots/Theme_fjord.webp b/screenshots/Theme_fjord.webp
new file mode 100644
index 0000000..461ecdd
Binary files /dev/null and b/screenshots/Theme_fjord.webp differ
diff --git a/screenshots/Theme_polarized.png b/screenshots/Theme_polarized.png
deleted file mode 100644
index 6b679e8..0000000
Binary files a/screenshots/Theme_polarized.png and /dev/null differ
diff --git a/screenshots/Theme_polarized.webp b/screenshots/Theme_polarized.webp
new file mode 100644
index 0000000..9c2c8eb
Binary files /dev/null and b/screenshots/Theme_polarized.webp differ
diff --git a/screenshots/Theme_suri.png b/screenshots/Theme_suri.png
deleted file mode 100644
index 95735b4..0000000
Binary files a/screenshots/Theme_suri.png and /dev/null differ
diff --git a/screenshots/Theme_suri.webp b/screenshots/Theme_suri.webp
new file mode 100644
index 0000000..c9d14fa
Binary files /dev/null and b/screenshots/Theme_suri.webp differ
diff --git a/screenshots/Theme_terracotta.png b/screenshots/Theme_terracotta.png
deleted file mode 100644
index 6fa4fab..0000000
Binary files a/screenshots/Theme_terracotta.png and /dev/null differ
diff --git a/screenshots/Theme_terracotta.webp b/screenshots/Theme_terracotta.webp
new file mode 100644
index 0000000..b572953
Binary files /dev/null and b/screenshots/Theme_terracotta.webp differ
diff --git a/screenshots/Triage_desktop.png b/screenshots/Triage_desktop.png
deleted file mode 100644
index 8b5bc85..0000000
Binary files a/screenshots/Triage_desktop.png and /dev/null differ
diff --git a/screenshots/Triage_desktop.webp b/screenshots/Triage_desktop.webp
new file mode 100644
index 0000000..461d7a6
Binary files /dev/null and b/screenshots/Triage_desktop.webp differ
diff --git a/screenshots/aufgaben_desktop.png b/screenshots/aufgaben_desktop.png
deleted file mode 100644
index 14fa99f..0000000
Binary files a/screenshots/aufgaben_desktop.png and /dev/null differ
diff --git a/screenshots/aufgaben_desktop.webp b/screenshots/aufgaben_desktop.webp
new file mode 100644
index 0000000..412e2cc
Binary files /dev/null and b/screenshots/aufgaben_desktop.webp differ
diff --git a/screenshots/journal_desktop.png b/screenshots/journal_desktop.png
deleted file mode 100644
index 7beb4fa..0000000
Binary files a/screenshots/journal_desktop.png and /dev/null differ
diff --git a/screenshots/journal_desktop.webp b/screenshots/journal_desktop.webp
new file mode 100644
index 0000000..db809dd
Binary files /dev/null and b/screenshots/journal_desktop.webp differ
diff --git a/screenshots/workspace_desktop.png b/screenshots/workspace_desktop.png
deleted file mode 100644
index 1363ec5..0000000
Binary files a/screenshots/workspace_desktop.png and /dev/null differ
diff --git a/screenshots/workspace_desktop.webp b/screenshots/workspace_desktop.webp
new file mode 100644
index 0000000..1f6eec8
Binary files /dev/null and b/screenshots/workspace_desktop.webp differ