Zum Hauptinhalt springen

Zurück zum Devlog

Freitag, 03. April 2026

Feature

80 Commits

13 min Lesezeit

Habits, Automations, Notes/Finance/Places + Stalwart Mail + Undo

Vier neue Module (habits, automations, notes/finance, places mit GPS), Cross-Module Trigger-Registry für Automations, Stalwart Mail-Server intern, Undo-Toasts auf 14 DetailViews und cross-module clickable links mit overlay stacking.

T

Till Schneider

Autor

Highlights

  • Vier neue Module: habits, automations, notes, finance, places (GPS)
  • Automations Trigger-Registry — cross-module Aktionen reagieren aufeinander
  • Stalwart Mail-Server intern für mana-notify (raus aus Brevo-only)
  • Undo-Toasts auf 14 DetailViews + Task-Completion
  • Cross-Module clickable links mit Overlay-Stacking
  • Page-Shell: Drag-Header + Move/Min/Max/Close in eine Bar
  • −249k LOC (massive Cleanup-Welle: 25 archivierte Apps endgültig gelöscht, Legacy-Code raus)

Habits-Modul

Habits war eines der letzten Module die noch fehlten. Heute scaffolded und in einem Aufwasch produktiv:

Features

  • Tally-Board als Standardansicht — jeden Tag eine Spalte, jede Habit eine Zeile
  • Inline-Create in der Liste, kein Modal
  • Detail-View mit Streak-Anzeige, Verlauf, Notizen pro Tag
  • Phosphor-Icons statt Emojis — neuer shared <IconPicker> (mit Suche), gilt jetzt auch für andere Module die Icons brauchen
  • Photos-Upload an Daily-Entries möglich

Datenmodell: habits (Definition) + habitEntries (eine pro Tag pro Habit). Beide auf encrypted-by-default.


Automations-Modul

Das wahrscheinlich konzeptuell interessanteste Stück des Tages: Automations als eigenes Modul, das aus jedem anderen Modul Trigger empfangen kann.

Cross-Module Trigger-Registry

Module registrieren ihre Trigger zentral:

// modules/todo/automations.ts
registerTriggers('todo', [
	{ id: 'task.completed', label: 'Aufgabe abgehakt' },
	{ id: 'task.created', label: 'Aufgabe erstellt' },
	{ id: 'task.due_today', label: 'Aufgabe wird heute fällig' },
]);

Und ihre Aktionen:

registerActions('calendar', [{ id: 'event.create', label: 'Termin erstellen', schema: ZEvent }]);

Eine Automation verbindet Trigger → Bedingungen → Aktion:

WHEN  todo.task.completed
WHERE task.tag === 'sport'
THEN  habits.entry.create  habit='workout'

UI für Trigger-Rules

Eine eigene Page in der Automations-App listet alle aktiven Rules. Inline-Editor mit Auto-Suggest aus der Trigger/Action-Registry.

Proaktive Suggestions

Plus: das System schaut sich an was der User regelmäßig manuell macht (“nach jedem task.completed mit Tag ‘sport’ erstellt User eine habit.entry”) und schlägt eine entsprechende Automation inline vor — dort wo das Verhalten passiert, nicht in einer separaten View.


Notes, Finance — und ein konsolidiertes Registry

Zwei kleine Module nebenher gebaut:

Notes

  • Leichtes Notes-Modul (kein Markdown-Editor — pure Plain-Text + Tags)
  • Click-to-edit, ListView mit kompaktem Input oben
  • Workbench-Panel mit Inline-Edit (kein Detail-Modal nötig für Quick-Capture)

Finance

  • Buchhaltungs-Light (Income / Expense / Categories)
  • Workbench-Panel direkt nutzbar — Eingabe + sofortige Liste

Unified AppDescriptor

Vorher gab es zwei Registries: Entity-Registry (für DnD-Targets) + App-Registry (für Branding/Routing). Heute zusammengeführt zu einem AppDescriptor, der alles in einer Datei pro Modul beschreibt:

export const todoApp: AppDescriptor = {
  id: 'todo',
  label: 'Todo',
  color: '#6366f1',
  icon: 'check',
  routes: [...],
  entityTypes: ['task', 'project', 'page'],
  dragSources: [...],
  dropTargets: [...],
  searchProvider: searchTodos,
};

Module registrieren sich mit einem einzigen Aufruf statt drei.


Places-Modul mit GPS-Tracking

Das fünfte neue Modul des Tages: Places — einfache Location-Verwaltung, mit optionalem GPS-Tracking im Hintergrund.

  • GPS-Background-Tracking opt-in (per Service-Worker / Permissions API)
  • Visit-Detection via Stationary-Phasen
  • Reverse Geocoding über OSM (Nominatim)
  • Map-View mit OSM-Embeds (leaflet wurde im selben Sweep entfernt — siehe unten)

Kombiniert mit dem Detail-Overlay-System von gestern: jedes Item kann auf Items aus anderen Modulen verweisen, und ein Klick öffnet das Ziel on top des aktuellen Overlays.

TaskDetail (Overlay #1)
  → Linked Event "Sprint Review"
       Click → EventDetail (Overlay #2)
                 → Linked Contact "Anna"
                      Click → ContactDetail (Overlay #3)

ESC schließt nur das oberste Overlay. Das System tracked welche Items gerade offen sind, um Doppel-Open zu verhindern.

Detail-View Polish

  • Animated Close + ESC-Key (gestern war’s nur Open-Animation)
  • Mehrere DetailViews offen über AppPages hinweg
  • Tag-Pills mit Click-to-Remove in jeder DetailView
  • Tags als Pills statt Dots anzeigen — endlich mit Label

Undo-Toasts — wirklich überall

Bisher gab es Undo nur für gelöschte Tasks. Heute ausgeweitet auf:

  • 14 DetailViews (delete + tag removal)
  • Task-Completion (mit “Doch nicht erledigt”-Toast)

Pattern: jede destruktive Aktion stagged eine pendingDelete für 5 Sekunden, im Hintergrund läuft der Undo-Timer. Klick auf “Rückgängig” → restore. Sonst → flush.


Stalwart Mail-Server

mana-notify lief bisher nur über Brevo (extern). Für interne Mails (User-Verifikation, System-Alerts, Memoro-Invites) ist das ungeeignet — Brevo zählt jeden Verify-Mail als “Marketing-Email”.

Stalwart als interner Postfix-Ersatz

# docker-compose.macmini.yml
stalwart:
  image: stalwartlabs/stalwart
  ports:
    - '25:25'
    - '587:587'
  volumes:
    - stalwart-data:/opt/stalwart

mana-notify wird auf SMTP umgestellt — Stalwart ist Default für interne Mails, Brevo bleibt für Massenmails (Newsletter etc., später).

Eine Reihe von Iterations

Stalwart ist neu — es gab heute mehrere Bugs:

IssueFix
Falscher Image-Namestalwartlabs/stalwart (nicht stalwart-mail)
Port-Mapping kollidierte mit Host-Postfix25 + 587 explizit gemapped
Healthcheck schlug fehlTCP-Check auf 587
LOGIN-Auth schlug fehlmana-notify SMTP-Sender komplett neu mit LOGIN auth
Insecure TLS für intern erlaubtSelf-Signed-Zertifikate akzeptiert für interne Hops
Falsche Account-Rollenoreply mit user-Role statt admin
Brevo SMTP_USER fehlt als DefaultBackward-compat für externe Mails
Service-Key zwischen mana-auth & mana-notifyAligned, sonst lehnt notify die Auth-Mails ab
Message-ID + Date-Headers fehltenOutgoing-Mails landen sonst in Spam

Am Ende: Auth-Mails vom mana-auth Service gehen jetzt vollständig intern über Stalwart raus. Spam-Score: gut.

mana-authmana-notify Refactor

mana-auth hatte Nodemailer-Code für Verifikations-Mails. Jetzt routet es ALLE Mails über mana-notify (eine API, ein Sender, eine Stelle für Templates).


PageShell: Drag + Window-Controls in eine Bar

Bisher hatte jede Page einen Drag-Bereich oben + separate Window-Controls in der Ecke. Confusing. Jetzt:

┌────────────────────────────────────────────────┐
│ ←  •••  Title  •••  → │ □  ⊟  ⊠  ✕            │
└────────────────────────────────────────────────┘
   Drag Handle              Min  Max  Close
  • Volle Drag-Bar als Header (height reduziert auf das Nötige)
  • Window-Controls (min/max/close) integriert
  • Left/Right Arrow Buttons für Page-Navigation
  • Drag Preview zeigt Item-Title + App-Color (statt nur “1 Item”)
  • Drag-Handles immer sichtbar, nicht nur on hover

Drag vs Click Bug

Bug: nach DnD wurde der Click auch noch ausgelöst → Detail-View öffnete sich. Fix: Click-Event blocken wenn ein Drag gerade stattgefunden hat.


Workbench Page-System

  • PageCarousel full-width auf Homepage (kein Side-Padding)
  • Left scroll offset damit die erste Page nicht am Rand klebt
  • Page Drag restricted auf Handle-Area damit Items innerhalb der Page noch greifbar sind
  • Mobile responsive — Page-Width passt sich an Viewport an

Cleanup-Welle (−249k LOC)

Heute war auch Aufräumtag. Mit den 25 archivierten Apps von gestern und der Stabilität des Unified-Stacks konnte massiv Legacy raus:

CleanupLOC
25 web-archived directories endgültig gelöschtgroßer Teil
Legacy per-app IndexedDB Migration~3k
Backend-API-Clients (Ghost-Code, kein Server mehr da)~5k
Stale Stubs in Workspace-Config
shared-auth-stores, shared-profile-ui, shared-app-onboarding Referenzen
Leaflet → OSM-Embeds (kein 200 KB JS-Bundle mehr)
Codebase-weiter Consolidate-Sweepviele Dateien

Note: Wir haben aktuell noch keine User in Production. Dieser Cleanup-Modus ist genau jetzt richtig — danach wird’s politisch.


Fixes & Polish

FixBeschreibung
Effect depth exceededguestMode wurde versehentlich $state(), hat sich selbst getriggert
Entity registration hangRace-Condition zwischen Registry-Init und Module-Mount
40 Svelte dev warningsClean-Startup ohne Console-Spam
Default Port unified API3050 → 3060 (3050 ist mana-sync)
API-Server Dev-ScriptsAlle Scripts auf den Unified API umgestellt
Status-Page / Prometheus / CloudflaredConfigs für unified app aktualisiert
Race in status-page-genLock-File während Generation
Analytics Umami Website-IDNach DB-Reset neue ID gepflegt
getTagsByIdsFehlender allTags Param in zitare gefixt
ManaContacts → KontakteBranding-Rename
AppDrawer → new tabApps öffnen sich extern statt innerhalb der App
bindclient:Height → calculatedBottom-Chrome-Height berechnet, nicht gemessen
CSP localhost erlaubtIn Dev-Mode
bottomChromeHeight OrderDeklaration vor Verwendung
Sync revertPer-app SSE → HTTP polling als Fallback (SSE-Bugs morgen klären)
@const revertInnerhalb <div> invalid

Branding & UI

  • PillNav cleanup: Observatory, API Keys, Gifts entfernt — waren Stubs
  • InputBar Toggle: PillNav-Toggle nach rechts in InputBar verschoben (vorher links, blockierte Tag-Strip)
  • Tags: leftmost Position in PillNav, größerer Toggle-Button

Dokumentation

  • docs/MAIL_STALWART.md — Setup-Notes, Auth-Config, Troubleshooting
  • docs/UNIFIED_APP_PHASE7_NOTES.md — Detail-Patterns für Drag/Drop und Overlays

Zusammenfassung

BereichCommitsHighlights
Neue Module~14habits, automations, notes, finance, places
Stalwart Mail~13Setup, 8 Iterations bis stabil, mana-auth Refactor
Undo-Toasts~314 DetailViews + Task-Completion
Cross-Module Links~5Overlay-Stacking, animated close, ESC
Workbench / PageShell~12Drag + Window-Controls in eine Bar
Cleanup~10−249k LOC, Legacy + 25 archived Apps endgültig weg
Tag UI~5Pills statt Dots, Click-to-Remove
Fixes~18Reactivity, Race-Conditions, Sync-Revert, CSP

Nächste Schritte

  • Mobile-Responsive für alle Module (PWA-fähig machen)
  • Habits + Tasks scheduling: gemeinsamer Time-Block
  • Finance Quick-Stats Widget für Dashboard
  • Sync SSE-Bugs root-causen, polling wieder zurückbauen

Tags

#manacore #habits #automations #notes #finance #places #stalwart #mail #undo #workbench #context-menu