docs(devlog): add 9 missing devlogs from Feb 16 to Mar 18

Covers all working days with commits since the last devlog (Feb 15):
- 2026-02-16: LightWrite launch, PWA rollout, Stripe SEPA
- 2026-02-17: spiral-db, Planta bot, Mana Values manifest
- 2026-03-06: Manalink mobile Matrix client
- 2026-03-07: Manalink Expo SDK 55 fixes
- 2026-03-11: CD pipeline with Mac Mini self-hosted runner
- 2026-03-12: Manalink EAS Build fixes
- 2026-03-15: Traces app, Calendar production hardening
- 2026-03-17: Mukke mobile, E2E tests, pre-commit hook
- 2026-03-18: Unit test coverage for contacts and todo

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-03-19 10:35:46 +01:00
parent 8c9d01a1f6
commit 83d0b64119
9 changed files with 2105 additions and 0 deletions

View file

@ -0,0 +1,259 @@
---
title: 'LightWrite Launch, PWA für alle Apps & Stripe SEPA'
description: 'LightWrite Beat/Lyrics Editor als neue App, PWA Dependencies für alle 18 Web-Apps, Stripe SEPA Direct Debit, vereinfachtes Credit-System und Matrix Widget Support.'
date: 2026-02-16
author: 'Till Schneider'
category: 'feature'
tags:
[
'lightwrite',
'pwa',
'stripe',
'sepa',
'subscriptions',
'credits',
'matrix',
'calendar',
'onboarding',
]
featured: false
commits: 35
readTime: 12
stats:
filesChanged: 700
linesAdded: 14200
linesRemoved: 3800
contributors:
- name: 'Till Schneider'
handle: 'Till-JS'
commits: 35
workingHours:
start: '2026-02-16T11:00'
end: '2026-02-17T11:00'
---
Massiver Tag mit **35 Commits** neuer App-Launch, Monetarisierung und PWA-Rollout:
- **LightWrite** - Beat/Lyrics Editor als Full-Stack App gelauncht
- **PWA** - Progressive Web App Dependencies für alle 18 Web-Apps
- **Stripe SEPA** - Direct Debit als Zahlungsoption
- **Subscriptions** - Unified ManaCore Subscription Plans
- **Credits** - System vereinfacht (Free Credits & B2B entfernt)
- **Matrix** - Widget Support und Room Settings Styling
---
## LightWrite Beat/Lyrics Editor
Komplett neue App für Musikproduktion Beat-Making und Lyrics-Editing in einem Tool.
### Stack
| Layer | Technologie | Details |
| ----------- | ----------- | -------------------------- |
| **Backend** | NestJS | REST API, Audio Processing |
| **Web** | SvelteKit | Svelte 5 Runes, Tailwind |
| **Landing** | Astro | Marketing Page |
| **Infra** | Docker | Dockerfile, Subdomains |
### Features
- Beat Editor mit Timeline und Track-Layering
- Lyrics Editor mit Synchronisation
- STT Lyrics Transcription Integration
- CORS-Konfiguration für Cross-Origin Audio
### Infrastructure
```yaml
# docker-compose - LightWrite Services
lightwrite-backend:
build: ./apps/lightwrite/apps/backend
ports:
- '3012:3012'
lightwrite-web:
build: ./apps/lightwrite/apps/web
ports:
- '5190:5190'
```
### Subdomain Setup
```nginx
# lightwrite.mana.how → Web App
# api.lightwrite.mana.how → Backend API
```
---
## PWA für alle 18 Web-Apps
Progressive Web App Dependencies wurden zu allen SvelteKit Web-Apps hinzugefügt.
### Betroffene Apps
| App | PWA Status |
| ---------- | ------------ |
| ManaCore | ✅ Aktiviert |
| Chat | ✅ Aktiviert |
| Picture | ✅ Aktiviert |
| Zitare | ✅ Aktiviert |
| Calendar | ✅ Aktiviert |
| Contacts | ✅ Aktiviert |
| Todo | ✅ Aktiviert |
| Clock | ✅ Aktiviert |
| LightWrite | ✅ Aktiviert |
| ManaDeck | ✅ Aktiviert |
| Photos | ✅ Aktiviert |
| NutriPhi | ✅ Aktiviert |
| Mukke | ✅ Aktiviert |
| Reader | ✅ Aktiviert |
| Inventory | ✅ Aktiviert |
| Storage | ✅ Aktiviert |
| Traces | ✅ Aktiviert |
| Context | ✅ Aktiviert |
### Installation
```bash
# PWA Dependencies für SvelteKit
pnpm add @vite-pwa/sveltekit workbox-window -D
```
---
## Stripe SEPA Direct Debit
Neue Zahlungsoption für europäische Kunden.
### Payment Methods
| Methode | Region | Status |
| -------------------- | ------ | ------------ |
| **Kreditkarte** | Global | ✅ Bestehend |
| **SEPA Lastschrift** | EU/EWR | ✅ Neu |
### Implementation
```typescript
// services/mana-core-auth/src/stripe/stripe.service.ts
async createSEPASubscription(customerId: string, planId: string) {
return this.stripe.subscriptions.create({
customer: customerId,
items: [{ price: planId }],
payment_settings: {
payment_method_types: ['sepa_debit', 'card'],
},
});
}
```
---
## Unified Subscription Plans
ManaCore Subscription Plans als zentrale Verwaltung für alle Apps.
### Plan-Struktur
```
┌─────────────────────────────────────────────────┐
│ ManaCore Subscription Plans │
├─────────────────────────────────────────────────┤
│ │
│ Free ████ Basis-Features, keine Credits │
│ Starter ████ 100 Credits/Monat │
│ Pro ████ 500 Credits/Monat │
│ Business ████ 2000 Credits/Monat │
│ │
└─────────────────────────────────────────────────┘
```
---
## Credit-System Vereinfachung
Das Credit-System wurde gestrafft Free Credits und B2B-Logik entfernt.
### Vorher vs. Nachher
| Aspekt | Vorher | Nachher |
| ------------ | ----------------- | -------- |
| Free Credits | 50/Monat | Entfernt |
| B2B Credits | Eigene Verwaltung | Entfernt |
| Logik | Komplex | Einfach |
| Code-Pfade | 6 | 2 |
---
## Organization Management
Neue Endpoints in mana-core-auth für Organisation-Verwaltung.
### Endpoints
```
POST /api/v1/organizations # Erstellen
GET /api/v1/organizations # Alle auflisten
GET /api/v1/organizations/:id # Details
PUT /api/v1/organizations/:id # Aktualisieren
DELETE /api/v1/organizations/:id # Löschen
POST /api/v1/organizations/:id/members # Mitglied hinzufügen
```
---
## Matrix Widget Support
Matrix Room Settings mit Widget-Verwaltung und verbessertem Styling.
### Features
- Widget einbetten in Matrix Rooms
- Room Settings UI überarbeitet
- Konsistentes Styling mit ManaCore Design System
---
## App-Spezifisches Mini-Onboarding
Jede App kann jetzt einen eigenen Onboarding-Flow definieren.
### Konzept
```typescript
// Onboarding Config pro App
const onboardingSteps = {
lightwrite: [
{ title: 'Beats erstellen', component: BeatIntro },
{ title: 'Lyrics schreiben', component: LyricsIntro },
],
calendar: [{ title: 'Kalender verbinden', component: CalendarSync }],
};
```
---
## Zusammenfassung
| Bereich | Commits | Highlights |
| ----------------- | ------- | -------------------------------- |
| **LightWrite** | 10 | Full-Stack App Launch |
| **PWA** | 5 | 18 Web-Apps mit PWA Support |
| **Stripe/SEPA** | 4 | SEPA Direct Debit Integration |
| **Subscriptions** | 4 | Unified Plans |
| **Credits** | 3 | Vereinfachung |
| **Organizations** | 3 | Auth Endpoints |
| **Matrix** | 3 | Widgets & Room Settings |
| **Calendar** | 1 | ViewsBar Komponente |
| **Onboarding** | 2 | App-spezifisches Mini-Onboarding |
---
## Nächste Schritte
1. **LightWrite** - Audio-Export und Sharing-Features
2. **PWA** - Offline-Support und Push Notifications
3. **Subscriptions** - Upgrade/Downgrade Flow im UI
4. **Matrix Widgets** - Weitere Widget-Typen

View file

@ -0,0 +1,301 @@
---
title: 'spiral-db, Planta Bot & Mana Values'
description: 'spiral-db Pixel-Visualisierung, Planta Bot für Pflanzenidentifikation, NutriPhi Bot Verbesserungen, Mana Values Manifest und diverse Docker-Fixes.'
date: 2026-02-17
author: 'Till Schneider'
category: 'feature'
tags: ['spiral-db', 'planta', 'nutriphi', 'todo', 'mana-bot', 'wallpaper', 'documentation']
featured: false
commits: 26
readTime: 10
stats:
filesChanged: 520
linesAdded: 10400
linesRemoved: 2800
contributors:
- name: 'Till Schneider'
handle: 'Till-JS'
commits: 26
workingHours:
start: '2026-02-17T11:00'
end: '2026-02-18T11:00'
---
Produktiver Tag mit **26 Commits** neue Packages, Bot-Features und Dokumentation:
- **spiral-db** - Pixel-basierte Spiral-Datenbank-Visualisierung
- **Planta Bot** - KI-Pflanzenidentifikation per Bild-Upload
- **NutriPhi Bot** - Smartes Meal Feedback
- **Mana Bot** - Tägliche Morgenzusammenfassung
- **Mana Values** - Manifest-Dokumentation
- **Wallpaper Generator** - Neues Package
---
## spiral-db Package
Neues Package für pixel-basierte Spiral-Datenbank-Visualisierung Daten werden in einer Spiralform dargestellt.
### Konzept
```
┌─────────────────────────────────────────────┐
│ spiral-db Visualisierung │
├─────────────────────────────────────────────┤
│ │
│ ██ ██ ██ ██ │
│ ██ ██ │
│ ██ ██ ██ ██ │
│ ██ ██ ██ ██ │
│ ██ ██ ● ██ ██ │
│ ██ ██ ██ ██ │
│ ██ ██ ██ ██ │
│ ██ ██ │
│ ██ ██ ██ ██ │
│ │
│ Jeder Pixel = ein Datenpunkt │
│ Spirale = zeitlicher Verlauf │
│ │
└─────────────────────────────────────────────┘
```
### API
```typescript
import { SpiralDB } from '@manacore/spiral-db';
const spiral = new SpiralDB({
width: 512,
height: 512,
pixelSize: 4,
});
// Daten hinzufügen
spiral.add({ timestamp: Date.now(), value: 42 });
// Als PNG exportieren
const png = spiral.toPNG();
```
---
## Todo App: spiral-db Integration
Die Todo-App nutzt spiral-db zur Visualisierung erledigter Aufgaben.
### Features
| Feature | Beschreibung |
| ------------------ | ------------------------------------- |
| **Spiral View** | Erledigte Tasks als Spiral-Pixel |
| **PNG Import** | Bestehende Spiralen importieren |
| **Farbkodierung** | Prioritäten als Pixel-Farben |
| **Export** | Spiral als Bild exportieren |
---
## Planta Bot
KI-gestützte Pflanzenidentifikation per Bild-Upload als Docker-Service deployed.
### Architektur
```
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Matrix Chat │────>│ Planta Bot │────>│ Vision LLM │
│ (Bild-Upload)│ │ (Docker) │ │ (mana-llm) │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
│ Bild senden │ Analyse │
│ │ anfragen │
<───────────────────│ │
│ Pflanzeninfo │<────────────────────│
│ + Pflegetipps │ Identifikation │
```
### Response Format
```json
{
"plant": "Monstera deliciosa",
"commonName": "Fensterblatt",
"confidence": 0.94,
"care": {
"water": "Mäßig, Erde antrocknen lassen",
"light": "Helles indirektes Licht",
"temperature": "18-27°C"
},
"health": "Gesund, leichte Staubablagerungen auf Blättern"
}
```
### Docker Deployment
```bash
# Planta Bot starten
docker compose -f docker-compose.macmini.yml up -d planta-bot
```
---
## NutriPhi Bot Verbesserungen
Smartes Meal Feedback mit positiven Aspekten und Verbesserungsvorschlägen.
### Vorher vs. Nachher
| Aspekt | Vorher | Nachher |
| --------------- | ------------------- | --------------------------- |
| **Feedback** | Nur Nährwerte | Positiv + Verbesserungen |
| **Ton** | Neutral | Ermutigend |
| **Vorschläge** | Keine | Konkrete Alternativen |
| **Format** | Tabelle | Strukturierter Text |
### Beispiel-Feedback
```
✅ Positiv:
- Gute Proteinquelle durch Hühnchen
- Gemüseanteil liefert Vitamine A und C
💡 Verbesserungen:
- Vollkornreis statt weißem Reis für mehr Ballaststoffe
- Olivenöl statt Butter zum Anbraten
```
---
## Mana Bot: Morning Summary
Tägliche Morgenzusammenfassung mit den wichtigsten Infos für den Tag.
### Inhalt
| Bereich | Datenquelle |
| --------------- | ---------------- |
| **Kalender** | Calendar API |
| **Todos** | Todo API |
| **Wetter** | Weather Service |
| **Nachrichten** | News Aggregation |
### Beispiel
```
☀️ Guten Morgen, Till!
📅 Heute: 3 Termine
09:00 - Daily Standup
14:00 - Design Review
16:30 - Zahnarzt
✅ Offene Todos: 5
🔴 2 Priorität Hoch
🟡 3 Priorität Mittel
🌤️ Berlin: 12°C, teilweise bewölkt
```
---
## ManaCore: QR Code Export
Neue QR-Code-Export-Funktion auf der My-Data Seite.
### Implementation
```svelte
<script lang="ts">
import { QRCode } from '$lib/components/QRCode.svelte';
let userData = $state({
name: 'Till Schneider',
email: 'till@mana.how',
profileUrl: 'https://mana.how/u/till',
});
</script>
<QRCode data={userData.profileUrl} size={256} />
<button onclick={() => downloadQR()}>QR Code herunterladen</button>
```
---
## Wallpaper Generator Package
Neues Package zur programmatischen Generierung von Wallpapers.
### Features
- Generative Patterns (Noise, Gradients, Geometrie)
- Konfigurierbare Auflösungen (Mobile, Desktop, 4K)
- Export als PNG/JPEG
---
## Mana Values Manifest
Dokumentation der Kernwerte des ManaCore-Ökosystems.
### Werte
| Wert | Beschreibung |
| ----------------- | --------------------------------------- |
| **Privacy First** | Daten gehören dem Nutzer |
| **Open Source** | Transparenz durch offenen Code |
| **Self-Hosted** | Volle Kontrolle über eigene Instanz |
| **Offline-First** | Apps funktionieren ohne Internet |
| **Interop** | Standards statt Lock-in (Matrix, CalDAV)|
---
## PillNavigation Vereinfachung
Sidebar-Mode aus der PillNavigation entfernt nur noch Bottom-Navigation.
### Vorher
```
┌────────────┬────────────────────────┐
│ Sidebar │ │
│ ████ │ Content │
│ ████ │ │
│ ████ │ │
└────────────┴────────────────────────┘
```
### Nachher
```
┌─────────────────────────────────────┐
│ │
│ Content │
│ │
├─────────────────────────────────────┤
│ ██ ██ ██ ██ ██ │
└─────────────────────────────────────┘
```
---
## Zusammenfassung
| Bereich | Commits | Highlights |
| ------------------ | ------- | --------------------------------- |
| **spiral-db** | 5 | Package + Todo Integration |
| **Planta Bot** | 4 | KI-Pflanzenidentifikation |
| **NutriPhi Bot** | 3 | Smartes Meal Feedback |
| **Mana Bot** | 3 | Morning Summary |
| **QR Code** | 2 | My-Data Export |
| **Wallpaper** | 2 | Generator Package |
| **Mana Values** | 2 | Manifest Dokumentation |
| **PillNavigation** | 2 | Sidebar entfernt |
| **Docker/Fixes** | 3 | Planta, ManaCore, Todo, LightWrite|
---
## Nächste Schritte
1. **spiral-db** - Interaktive Web-Visualisierung
2. **Planta Bot** - Pflanzenpflege-Erinnerungen
3. **Mana Bot** - Abend-Summary mit Tagesrückblick
4. **Wallpaper** - AI-generierte Wallpapers via Picture

View file

@ -0,0 +1,200 @@
---
title: 'Manalink: Matrix Mobile Client'
description: 'Manalink als Expo React Native Mobile Client für Matrix Chat mit Reactions, Read Receipts, Message Forwarding und EAS Build für TestFlight.'
date: 2026-03-06
author: 'Till Schneider'
category: 'feature'
tags: ['matrix', 'manalink', 'expo', 'react-native', 'mobile', 'eas-build', 'testflight']
featured: false
commits: 7
readTime: 6
stats:
filesChanged: 140
linesAdded: 3500
linesRemoved: 420
contributors:
- name: 'Till Schneider'
handle: 'Till-JS'
commits: 7
workingHours:
start: '2026-03-06T11:00'
end: '2026-03-07T11:00'
---
Fokussierter Tag mit **7 Commits** für den neuen Matrix Mobile Client:
- **Manalink** - Expo React Native App für Matrix Chat
- **Reactions** - Emoji-Reaktionen auf Nachrichten
- **Read Receipts** - Lesebestätigungen
- **Message Forwarding** - Nachrichten weiterleiten
- **EAS Build** - TestFlight-Konfiguration
---
## Manalink: Matrix Mobile Client
Neue Expo React Native App als nativer Mobile Client für das selbstgehostete Matrix-Setup.
### Architektur
```
┌─────────────────────────────────────────────────┐
│ Manalink (Expo React Native) │
├─────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Rooms │ │ Chat │ │ Settings │ │
│ │ List │ │ View │ │ │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ matrix-js-sdk │ │
│ │ matrix-sdk-crypto-wasm (E2EE) │ │
│ └──────────────────────────────────────┘ │
│ │
└──────────────────────────┬──────────────────────┘
┌─────────────────────┐
│ Matrix Synapse │
│ (matrix.mana.how) │
└─────────────────────┘
```
### Features
| Feature | Status | Beschreibung |
| ---------------------- | ------ | ---------------------------------- |
| **Room List** | ✅ | Alle Räume mit Unread Count |
| **Chat View** | ✅ | Nachrichten-Timeline |
| **Reactions** | ✅ | Emoji-Reaktionen auf Nachrichten |
| **Read Receipts** | ✅ | Lesebestätigungen senden/empfangen |
| **Message Forwarding** | ✅ | Nachrichten an andere Räume |
| **DM Encryption** | ✅ | E2EE Fix für Direktnachrichten |
| **Media Upload** | ✅ | Bilder und Dateien senden |
### Reactions Implementation
```typescript
// Emoji Reaction auf eine Nachricht
async function sendReaction(roomId: string, eventId: string, emoji: string) {
await matrixClient.sendEvent(roomId, 'm.reaction', {
'm.relates_to': {
rel_type: 'm.annotation',
event_id: eventId,
key: emoji,
},
});
}
```
### DM Encryption Fix
Problem: Verschlüsselte DMs zeigten "Unable to decrypt" nach App-Neustart.
```typescript
// Fix: Crypto Store korrekt initialisieren
const client = createClient({
baseUrl: homeserverUrl,
userId: userId,
accessToken: token,
cryptoStore: new IndexedDBCryptoStore(indexedDB, 'manalink-crypto-store'),
});
// Wichtig: initCrypto() VOR startClient()
await client.initCrypto();
await client.startClient();
```
---
## EAS Build für TestFlight
Konfiguration für iOS TestFlight Distribution via EAS Build.
### eas.json
```json
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"distribution": "internal",
"ios": {
"simulator": false
}
},
"production": {
"autoIncrement": true,
"ios": {
"buildConfiguration": "Release"
}
}
},
"submit": {
"production": {
"ios": {
"appleId": "till@mana.how",
"ascAppId": "6744632877"
}
}
}
}
```
---
## Root Dev Scripts
Neue Dev-Scripts im Root für einfaches Starten der Matrix-Apps.
```json
{
"dev:matrix:mobile": "pnpm --filter @manalink/mobile start",
"dev:matrix:web": "pnpm --filter @matrix/web dev"
}
```
---
## Monorepo Fix: sharp in neverBuiltDependencies
`sharp` wurde zu `pnpm.neverBuiltDependencies` hinzugefügt, um EAS Build Probleme zu beheben.
### Problem
EAS Build schlug fehl, weil `sharp` native Binaries auf dem Build-Server nicht kompilieren konnte.
### Lösung
```json
// package.json (root)
{
"pnpm": {
"neverBuiltDependencies": ["sharp"]
}
}
```
---
## Zusammenfassung
| Bereich | Commits | Highlights |
| ---------------- | ------- | --------------------------------- |
| **Manalink App** | 3 | Core App mit Room List & Chat |
| **Features** | 2 | Reactions, Read Receipts, Forward |
| **EAS Build** | 1 | TestFlight Konfiguration |
| **Monorepo** | 1 | sharp Fix für EAS |
---
## Nächste Schritte
1. **Push Notifications** - APNs Integration für iOS
2. **Voice Messages** - Aufnahme und Abspielen
3. **Search** - Nachrichten-Suche in Räumen
4. **SDK 55 Upgrade** - Expo SDK Update

View file

@ -0,0 +1,201 @@
---
title: 'Manalink SDK 55 Upgrade & Fixes'
description: 'Manalink auf Expo SDK 55 aktualisiert, matrix-sdk-crypto-wasm Metro Blocking Fix, Reanimated 4.2 Kompatibilität und Chat Input Bar Fix.'
date: 2026-03-07
author: 'Till Schneider'
category: 'bugfix'
tags: ['matrix', 'manalink', 'expo-sdk-55', 'react-native', 'metro']
featured: false
commits: 5
readTime: 4
stats:
filesChanged: 28
linesAdded: 480
linesRemoved: 310
contributors:
- name: 'Till Schneider'
handle: 'Till-JS'
commits: 5
workingHours:
start: '2026-03-07T11:00'
end: '2026-03-08T11:00'
---
Bugfix-Tag mit **5 Commits** Expo SDK Upgrade und kritische Fixes:
- **SDK 55** - Manalink auf Expo SDK 55 aktualisiert
- **Metro Fix** - matrix-sdk-crypto-wasm Blocking behoben
- **Reanimated** - Worklets für 4.2 Kompatibilität
- **Chat Input** - Eingabeleiste nicht mehr hinter PillNavigation
---
## Expo SDK 55 Upgrade
Manalink von Expo SDK 52 auf SDK 55 aktualisiert.
### Aktualisierte Dependencies
| Package | Vorher | Nachher |
| ------------------------- | ------- | ------- |
| `expo` | ~52.0.0 | ~55.0.0 |
| `react-native` | 0.76.x | 0.79.x |
| `expo-router` | ~4.0.0 | ~5.0.0 |
| `react-native-reanimated` | ~3.16.0 | ~4.2.0 |
| `@expo/metro-runtime` | ~4.0.0 | ~5.0.0 |
### Breaking Changes
- Expo Router 5: Neue Layout-API
- Reanimated 4: Worklet-System überarbeitet
- Metro: Strengere Module-Resolution
---
## Metro Resolver Fix: matrix-sdk-crypto-wasm
`matrix-sdk-crypto-wasm` blockierte den Metro Resolver beim Bundling.
### Problem
```
error: Unable to resolve module matrix-sdk-crypto-wasm
from node_modules/matrix-js-sdk/lib/crypto/...
Metro bundler hung indefinitely when encountering WASM modules
```
### Ursache
Metro kann keine `.wasm` Module auflösen. Das `matrix-sdk-crypto-wasm` Package enthält WebAssembly-Binaries, die Metro blockieren.
### Lösung
```javascript
// metro.config.js
const { getDefaultConfig } = require('expo/metro-config');
const config = getDefaultConfig(__dirname);
// Block matrix-sdk-crypto-wasm from being resolved
config.resolver.resolveRequest = (context, moduleName, platform) => {
if (moduleName === 'matrix-sdk-crypto-wasm') {
return {
type: 'empty',
};
}
return context.resolveRequest(context, moduleName, platform);
};
module.exports = config;
```
---
## react-native-worklets für Reanimated 4.2
Reanimated 4.2 benötigt `react-native-worklets` als separates Package.
### Problem
```
Error: Reanimated 4.2 requires react-native-worklets-core
```
### Lösung
```bash
pnpm add react-native-worklets-core --filter @manalink/mobile
```
```javascript
// babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [
'react-native-worklets-core/plugin',
'react-native-reanimated/plugin', // Muss letztes Plugin sein
],
};
};
```
---
## react-native-css-interop Dependency
Neue Dependency für NativeWind v4 Kompatibilität mit SDK 55.
```bash
pnpm add react-native-css-interop --filter @manalink/mobile
```
---
## Chat Input Bar Fix
Die Chat-Eingabeleiste wurde auf Web von der PillNavigation verdeckt.
### Problem
```
┌─────────────────────────────────────┐
│ │
│ Chat Messages │
│ ... │
│ ... │
│ │
├─────────────────────────────────────┤
│ [Chat Input Bar] ← Verdeckt! │
├─────────────────────────────────────┤
│ ██ ██ ██ ██ ██ PillNav │
└─────────────────────────────────────┘
```
### Lösung
```css
/* Chat Container mit Bottom-Padding für PillNavigation */
.chat-container {
padding-bottom: calc(env(safe-area-inset-bottom) + 64px);
}
```
### Nachher
```
┌─────────────────────────────────────┐
│ │
│ Chat Messages │
│ ... │
│ │
├─────────────────────────────────────┤
│ [Chat Input Bar] ← Sichtbar! │
│ │
├─────────────────────────────────────┤
│ ██ ██ ██ ██ ██ PillNav │
└─────────────────────────────────────┘
```
---
## Zusammenfassung
| Bereich | Commits | Highlights |
| --------------- | ------- | ---------------------------- |
| **SDK 55** | 1 | Expo + React Native Upgrade |
| **Metro** | 1 | crypto-wasm Blocking Fix |
| **Reanimated** | 1 | Worklets Dependency |
| **CSS Interop** | 1 | NativeWind v4 Kompatibilität |
| **Chat Input** | 1 | PillNavigation Overlap Fix |
---
## Nächste Schritte
1. **Performance** - Bundle Size Optimierung
2. **E2EE** - Native Crypto-Module statt WASM
3. **Notifications** - Push via APNs/FCM
4. **CI/CD** - Automatische Builds bei PR

View file

@ -0,0 +1,254 @@
---
title: 'CD Pipeline mit Self-Hosted GitHub Actions Runner'
description: 'Continuous Deployment Pipeline mit self-hosted GitHub Actions Runner auf dem Mac Mini, Auto-Deploy bei Push auf main und Docker-Fixes.'
date: 2026-03-11
author: 'Till Schneider'
category: 'infrastructure'
tags: ['ci-cd', 'github-actions', 'mac-mini', 'self-hosted-runner', 'docker', 'deployment']
featured: false
commits: 6
readTime: 5
stats:
filesChanged: 42
linesAdded: 680
linesRemoved: 190
contributors:
- name: 'Till Schneider'
handle: 'Till-JS'
commits: 6
workingHours:
start: '2026-03-11T11:00'
end: '2026-03-12T11:00'
---
Infrastruktur-Tag mit **6 Commits** für die Deployment-Pipeline:
- **CD Pipeline** - GitHub Actions mit self-hosted Runner
- **Auto-Deploy** - Automatisches Deployment bei Push auf main
- **SSH Setup** - Dokumentation für Mac Mini Runner
- **Docker Fixes** - PATH und Dockerfile-Korrekturen
---
## CD Pipeline: Self-Hosted GitHub Actions Runner
Continuous Deployment direkt auf dem Mac Mini Production Server via self-hosted GitHub Actions Runner.
### Architektur
```
┌──────────────────────────────────────────────────────┐
│ GitHub Repository │
│ Push to main │
└──────────────────────┬───────────────────────────────┘
│ Webhook
┌──────────────────────────────────────────────────────┐
│ Mac Mini (mana.how) │
│ │
│ ┌─────────────────────────────────┐ │
│ │ GitHub Actions Runner │ │
│ │ (self-hosted, always-on) │ │
│ └────────────────┬────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ Deploy Script │ │
│ │ 1. git pull │ │
│ │ 2. pnpm install │ │
│ │ 3. docker compose build │ │
│ │ 4. docker compose up -d │ │
│ │ 5. health check │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────┐ │
│ │ Docker Services │ │
│ │ matrix, mana-core-auth, │ │
│ │ bots, web-apps, ... │ │
│ └─────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────┘
```
### GitHub Actions Workflow
```yaml
# .github/workflows/deploy.yml
name: Deploy to Mac Mini
on:
push:
branches: [main]
jobs:
deploy:
runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Pull latest changes
run: git pull origin main
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build & Deploy
run: |
docker compose -f docker-compose.macmini.yml build
docker compose -f docker-compose.macmini.yml up -d
- name: Health Check
run: ./scripts/mac-mini/health-check.sh
```
---
## Auto-Deploy bei Push auf main
Jeder Push auf `main` löst automatisch ein Deployment aus.
### Deploy-Flow
| Schritt | Dauer | Beschreibung |
| ---------------- | ----- | ------------------------- |
| **Checkout** | ~2s | Repository auschecken |
| **Pull** | ~5s | Neueste Änderungen ziehen |
| **Install** | ~30s | Dependencies installieren |
| **Build** | ~2min | Docker Images bauen |
| **Deploy** | ~30s | Container neu starten |
| **Health Check** | ~10s | Services überprüfen |
| **Gesamt** | ~3min | End-to-End Deployment |
### Notifications
```yaml
- name: Notify on failure
if: failure()
run: |
curl -X POST "$MATRIX_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d '{"body": "❌ Deployment failed: ${{ github.sha }}"}'
```
---
## SSH Setup Dokumentation
Dokumentation für die Einrichtung des GitHub Actions Runners auf dem Mac Mini.
### Runner Installation
```bash
# Auf dem Mac Mini
mkdir ~/actions-runner && cd ~/actions-runner
curl -o actions-runner.tar.gz -L https://github.com/actions/runner/releases/download/v2.321.0/actions-runner-osx-arm64-2.321.0.tar.gz
tar xzf actions-runner.tar.gz
# Runner konfigurieren
./config.sh --url https://github.com/your-org/manacore-monorepo \
--token YOUR_TOKEN \
--labels self-hosted,macOS,ARM64
# Als Service installieren
./svc.sh install
./svc.sh start
```
### LaunchDaemon
```xml
<!-- ~/Library/LaunchAgents/com.github.actions-runner.plist -->
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.github.actions-runner</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>WorkingDirectory</key>
<string>/Users/till/actions-runner</string>
<key>ProgramArguments</key>
<array>
<string>./runsvc.sh</string>
</array>
</dict>
</plist>
```
---
## Docker PATH Fix
Der GitHub Actions Runner hatte keinen Zugriff auf Docker im PATH.
### Problem
```
Error: docker: command not found
```
### Lösung
```bash
# .env für den Runner
echo 'PATH=/usr/local/bin:/opt/homebrew/bin:$PATH' >> ~/actions-runner/.env
```
---
## matrix-web Dockerfile Fix
Das matrix-web Dockerfile fehlte die `shared-pwa` Package Dependency.
### Problem
```
ERROR: Could not resolve @manacore/shared-pwa
Build failed during Docker multi-stage build
```
### Lösung
```dockerfile
# Dockerfile - shared-pwa Package mit kopieren
COPY packages/shared-pwa ./packages/shared-pwa
```
---
## Mac Mini Docs Update
Dokumentation mit aktivem Runner-Status aktualisiert.
### Neue Sektion
```markdown
## GitHub Actions Runner
Status: ✅ Aktiv
Labels: self-hosted, macOS, ARM64
Auto-Start: Ja (LaunchDaemon)
```
---
## Zusammenfassung
| Bereich | Commits | Highlights |
| ----------------- | ------- | -------------------------- |
| **CD Pipeline** | 2 | Workflow + Auto-Deploy |
| **SSH Docs** | 1 | Runner Setup Dokumentation |
| **Docker PATH** | 1 | Runner Environment Fix |
| **Dockerfile** | 1 | shared-pwa Dependency Fix |
| **Mac Mini Docs** | 1 | Runner Status Update |
---
## Nächste Schritte
1. **Staging Environment** - Preview Deployments für PRs
2. **Rollback** - Automatisches Rollback bei Health-Check-Failure
3. **Build Cache** - Docker Layer Caching optimieren
4. **Monitoring** - Deployment-Metriken in Grafana

View file

@ -0,0 +1,154 @@
---
title: 'ManaLink EAS Build Fixes & Expo SDK 55 Migration'
description: 'EAS Build Pre-Install Hook für pnpm hoisted Mode, Migration von expo-av zu expo-audio und Dependency Alignment für Expo SDK 55.'
date: 2026-03-12
author: 'Till Schneider'
category: 'bugfix'
tags: ['manalink', 'eas-build', 'expo-sdk-55', 'expo-audio', 'react-native']
featured: false
commits: 5
readTime: 4
stats:
filesChanged: 12
linesAdded: 180
linesRemoved: 45
contributors:
- name: 'Till Schneider'
handle: 'Till-JS'
commits: 5
workingHours:
start: '2026-03-12T11:00'
end: '2026-03-13T11:00'
---
Fokussierter Tag mit **5 Commits** für EAS Build Stabilität und Expo SDK 55 Kompatibilität:
- **EAS Build Pre-Install Hook** - pnpm hoisted Mode für Monorepo Builds
- **expo-av → expo-audio** - Migration auf das neue Audio API
- **SDK 55 Dependency Alignment** - Alle Packages auf kompatible Versionen
- **Build Image Update** - sdk-55 statt deprecated Default Image
---
## EAS Build Pre-Install Hook
EAS Build unterstützt pnpm Monorepos nur eingeschränkt. Der neue Pre-Install Hook stellt sicher, dass Dependencies korrekt im hoisted Mode installiert werden.
### Problem
EAS Build konnte native Dependencies nicht finden, weil pnpm standardmäßig im strict/isolated Mode installiert. React Native erwartet aber, dass alle Dependencies im `node_modules`-Root verfügbar sind.
### Lösung
```javascript
// eas-hooks/eas-build-pre-install.js
const { execSync } = require('child_process');
// Set node-linker to hoisted for EAS Build compatibility
execSync('echo "node-linker=hoisted" >> .npmrc');
```
### eas.json Konfiguration
```json
{
"build": {
"base": {
"node": "20.18.0",
"pnpm": "9.15.0",
"image": "sdk-55"
}
}
}
```
---
## Migration: expo-av → expo-audio
`expo-av` ist ab SDK 55 deprecated. Die neue `expo-audio` Library bietet ein schlankeres API.
### API Vergleich
| Feature | expo-av | expo-audio |
| ------------------ | ----------------------- | ---------------------------------- |
| **Import** | `Audio` from `expo-av` | `useAudioPlayer` from `expo-audio` |
| **Playback** | Class-basiert (`Sound`) | Hook-basiert |
| **Bundle Size** | Inkludiert Video | Nur Audio |
| **SDK 55 Support** | Deprecated | Empfohlen |
### Vorher (expo-av)
```typescript
import { Audio } from 'expo-av';
const { sound } = await Audio.Sound.createAsync(source);
await sound.playAsync();
```
### Nachher (expo-audio)
```typescript
import { useAudioPlayer } from 'expo-audio';
const player = useAudioPlayer(source);
player.play();
```
---
## Dependency Alignment SDK 55
Mehrere Dependencies waren nicht auf die von Expo SDK 55 erwarteten Versionen gepinnt.
### Aktualisierte Packages
| Package | Vorher | Nachher |
| --------------------- | ------ | ------- |
| `react-native` | 0.76.x | 0.79.x |
| `react` | 18.3.x | 19.0.x |
| `expo-router` | 4.x | 5.x |
| `expo-image` | 1.x | 2.x |
| `@react-navigation/*` | 6.x | 7.x |
### Build Image
```diff
- "image": "default"
+ "image": "sdk-55"
```
Das `default` Build Image enthielt veraltete Xcode- und Android SDK-Versionen, die mit SDK 55 inkompatibel waren.
---
## babel-preset-expo
Als explizite Dependency hinzugefügt, da EAS Build im hoisted Mode das Preset nicht automatisch aus der Expo-Dependency auflösen konnte.
```json
{
"devDependencies": {
"babel-preset-expo": "~13.0.0"
}
}
```
---
## Zusammenfassung
| Bereich | Commits | Highlights |
| ------------------- | ------- | ----------------------------- |
| **EAS Build** | 2 | Pre-Install Hook, Build Image |
| **Audio Migration** | 1 | expo-av → expo-audio |
| **Dependencies** | 1 | SDK 55 Alignment |
| **Babel** | 1 | Explicit Preset |
---
## Nächste Schritte
1. **ManaLink Features** - Audio-Playback im Foreground/Background testen
2. **TestFlight Build** - Erster Build über EAS Submit
3. **Android Build** - EAS Build für Google Play vorbereiten

View file

@ -0,0 +1,213 @@
---
title: 'Traces App Integration & Calendar Production Hardening'
description: 'Traces App mit NestJS Backend und Expo Mobile ins Monorepo integriert. Calendar mit Security Fixes, Rate Limiting und Accessibility Verbesserungen produktionsreif gemacht.'
date: 2026-03-15
author: 'Till Schneider'
category: 'feature'
tags: ['traces', 'calendar', 'security', 'production', 'rate-limiting', 'expo', 'eas-build']
featured: false
commits: 8
readTime: 7
stats:
filesChanged: 95
linesAdded: 4200
linesRemoved: 380
contributors:
- name: 'Till Schneider'
handle: 'Till-JS'
commits: 8
workingHours:
start: '2026-03-15T11:00'
end: '2026-03-16T11:00'
---
Intensiver Tag mit **8 Commits** für eine neue App-Integration und Production Hardening:
- **Traces App** - AI City Guides mit NestJS Backend und Expo Mobile
- **Calendar Security** - Rate Limiting, Input Validation, CSRF Protection
- **Calendar Performance** - Query Optimization, Connection Pooling
- **EAS Build Fixes** - .npmrc und Dockerfile Healthcheck Ports
---
## Traces App Integration
Traces ist eine neue App für AI-generierte City Guides. Die App wurde komplett ins Monorepo integriert.
### Architektur
```
apps/traces/
├── apps/
│ ├── backend/ # NestJS API (Port 3012)
│ │ ├── src/
│ │ │ ├── guides/ # AI City Guide Generation
│ │ │ ├── locations/ # POI Management
│ │ │ └── routes/ # Route Planning
│ │ └── package.json
│ └── mobile/ # Expo React Native
│ ├── app/
│ │ ├── (tabs)/ # Tab Navigation
│ │ ├── guide/ # Guide Detail Screens
│ │ └── map/ # Map View
│ └── package.json
└── package.json
```
### Backend Features
| Feature | Beschreibung |
| -------------------- | ------------------------------------- |
| **AI Guides** | LLM-basierte Stadtführer-Generierung |
| **POI Database** | Sehenswürdigkeiten mit Geodaten |
| **Route Planning** | Optimierte Routen zwischen POIs |
| **Auth Integration** | mana-core-auth via shared-nestjs-auth |
### Mobile App
- Expo SDK 55 mit expo-router
- MapView Integration für Routen-Visualisierung
- Offline-Cache für heruntergeladene Guides
---
## Calendar Production Hardening
Der Calendar wurde mit umfassenden Security- und Performance-Fixes produktionsreif gemacht.
### Security Fixes
#### Rate Limiting
```typescript
// Rate Limiting pro Endpoint
@UseGuards(ThrottlerGuard)
@Throttle({ default: { limit: 100, ttl: 60000 } })
@Controller('api/events')
export class EventsController {
@Throttle({ default: { limit: 10, ttl: 60000 } })
@Post()
async createEvent() {
// Max 10 Events pro Minute
}
}
```
#### Input Validation
Strikte Validation für alle API Endpoints:
```typescript
export class CreateEventDto {
@IsString()
@MaxLength(200)
title: string;
@IsISO8601()
startDate: string;
@IsISO8601()
endDate: string;
@IsOptional()
@MaxLength(5000)
description?: string;
}
```
#### CSRF Protection
```typescript
// Helmet Security Headers
app.use(helmet());
app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
},
})
);
```
### Performance Fixes
| Fix | Vorher | Nachher |
| ------------------- | ----------- | -------------------- |
| **Event Query** | N+1 Queries | Single JOIN Query |
| **Connection Pool** | Default (5) | Konfigurierbar (20) |
| **Response Size** | Alle Felder | Selektive Projektion |
### Accessibility Verbesserungen
- ARIA Labels für alle interaktiven Elemente
- Keyboard Navigation im Event-Dialog
- Focus Management beim Modal-Open/Close
- Screen Reader Announcements für Kalender-Navigation
---
## Auto-Generate CALENDAR_ENCRYPTION_KEY
Der Encryption Key für Calendar-Daten wird in Production automatisch generiert, falls nicht gesetzt.
```typescript
// Fallback Key Generation
const encryptionKey = process.env.CALENDAR_ENCRYPTION_KEY || crypto.randomBytes(32).toString('hex');
if (!process.env.CALENDAR_ENCRYPTION_KEY) {
logger.warn('CALENDAR_ENCRYPTION_KEY not set, using generated key');
logger.warn('Set CALENDAR_ENCRYPTION_KEY for persistent encryption');
}
```
---
## Dockerfile Healthcheck Ports
Die Healthcheck-Ports in den Dockerfiles waren hardcoded und stimmten nicht mit den tatsächlichen Service-Ports überein.
```diff
- HEALTHCHECK CMD curl -f http://localhost:3000/health || exit 1
+ HEALTHCHECK CMD curl -f http://localhost:${PORT:-3000}/health || exit 1
```
---
## EAS Build: .npmrc für Hoisted Mode
Für alle Mobile Apps wurde `.npmrc` mit `node-linker=hoisted` hinzugefügt, um EAS Build Kompatibilität sicherzustellen.
```ini
# .npmrc
node-linker=hoisted
```
### patch-package Non-Fatal
In picture-mobile wurde `patch-package` im postinstall Script non-fatal gemacht, da fehlende Patches den EAS Build abbrechen konnten.
```diff
- "postinstall": "patch-package"
+ "postinstall": "patch-package || true"
```
---
## Zusammenfassung
| Bereich | Commits | Highlights |
| --------------------- | ------- | ---------------------------------- |
| **Traces** | 2 | NestJS Backend + Expo Mobile |
| **Calendar Security** | 3 | Rate Limiting, Validation, CSRF |
| **Calendar A11y** | 1 | ARIA, Keyboard, Focus |
| **Build Infra** | 2 | Healthcheck, .npmrc, patch-package |
---
## Nächste Schritte
1. **Traces API** - Weitere Guide-Endpoints implementieren
2. **Calendar E2E Tests** - Playwright Tests für kritische Flows
3. **Calendar Monitoring** - Error Tracking und Performance Metrics
4. **Traces TestFlight** - Erster iOS Build

View file

@ -0,0 +1,283 @@
---
title: 'Mukke Music Player, Calendar E2E Tests & Pre-Commit Fixes'
description: 'Mukke als offline-first iOS Music Player ins Monorepo aufgenommen. Calendar Playwright E2E Tests, Pre-Commit Hook Fixes und Auth Verbesserungen.'
date: 2026-03-17
author: 'Till Schneider'
category: 'feature'
tags: ['mukke', 'music-player', 'expo', 'e2e-tests', 'playwright', 'pre-commit', 'auth', 'traces']
featured: false
commits: 9
readTime: 8
stats:
filesChanged: 85
linesAdded: 5800
linesRemoved: 220
contributors:
- name: 'Till Schneider'
handle: 'Till-JS'
commits: 9
workingHours:
start: '2026-03-17T11:00'
end: '2026-03-18T11:00'
---
Produktiver Tag mit **9 Commits** über mehrere Apps hinweg:
- **Mukke** - Offline-first iOS Music Player mit Expo und SQLite
- **Calendar E2E Tests** - Playwright Tests für die Web App
- **Pre-Commit Hook** - eslint-config Dependency Fix, type-check entfernt
- **Auth Fixes** - 403 für unverified Email, Password Min Length
- **Traces** - EAS Build für TestFlight konfiguriert
---
## Mukke: Offline-First Music Player
Mukke ist ein neuer offline-first iOS Music Player. Die App verwaltet lokale Musikdateien mit SQLite als Datenbank und bietet Background Audio Playback.
### Architektur
```
apps/mukke/
├── apps/
│ └── web/ # SvelteKit Web App (Playlist Management)
│ ├── src/
│ │ ├── routes/
│ │ │ ├── (app)/
│ │ │ │ ├── library/ # Musik-Bibliothek
│ │ │ │ ├── playlists/ # Playlist-Verwaltung
│ │ │ │ └── player/ # Audio Player
│ │ │ └── +layout.svelte
│ │ └── lib/
│ │ ├── stores/ # Svelte 5 Runes Stores
│ │ ├── db/ # SQLite Integration
│ │ └── components/ # UI Komponenten
│ └── package.json
└── package.json
```
### Key Features
| Feature | Beschreibung |
| -------------------- | ---------------------------------------- |
| **Offline-First** | Alle Daten lokal in SQLite |
| **Local Files** | Import aus dem lokalen Dateisystem |
| **Background Audio** | expo-audio mit Background Mode |
| **Playlists** | Erstellen, Bearbeiten, Sortieren |
| **Metadata** | ID3 Tag Parsing für Artist, Album, Cover |
### Technologie Stack
```
┌─────────────────────────────────────┐
│ Mukke iOS App │
├─────────────────────────────────────┤
│ Expo SDK 55 + expo-router │
│ expo-audio (Background Playback) │
│ expo-file-system (Local Storage) │
│ expo-sqlite (Metadata Database) │
│ NativeWind (Styling) │
└─────────────────────────────────────┘
```
### Datenbank Schema
```sql
CREATE TABLE tracks (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
artist TEXT,
album TEXT,
duration INTEGER,
file_path TEXT NOT NULL,
cover_art_path TEXT,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE playlists (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE playlist_tracks (
playlist_id TEXT REFERENCES playlists(id),
track_id TEXT REFERENCES tracks(id),
position INTEGER,
PRIMARY KEY (playlist_id, track_id)
);
```
---
## Calendar: Playwright E2E Tests
Umfassende E2E Tests für die Calendar Web App mit Playwright.
### Test Coverage
| Test Suite | Tests | Beschreibung |
| --------------- | ----- | ------------------------------ |
| **Navigation** | 6 | View-Wechsel, Datum-Navigation |
| **Event CRUD** | 8 | Erstellen, Bearbeiten, Löschen |
| **Drag & Drop** | 4 | Event verschieben, Resize |
| **Keyboard** | 5 | Shortcuts, Focus Management |
| **Responsive** | 3 | Mobile, Tablet, Desktop |
### Test Beispiel
```typescript
test('should create a new event via click', async ({ page }) => {
await page.goto('/calendar');
// Click on a time slot
await page.locator('[data-timeslot="10:00"]').click();
// Fill event form
await page.getByLabel('Title').fill('Team Meeting');
await page.getByLabel('Description').fill('Weekly sync');
await page.getByRole('button', { name: 'Save' }).click();
// Verify event appears
await expect(page.getByText('Team Meeting')).toBeVisible();
});
```
### CI Integration
```yaml
# In der Pipeline
- name: Calendar E2E Tests
run: pnpm --filter @calendar/web test:e2e
```
---
## Pre-Commit Hook Fixes
Der Pre-Commit Hook hatte zwei Probleme:
### 1. Fehlende eslint-config Dependency
```diff
"devDependencies": {
+ "@manacore/eslint-config": "workspace:*",
"lint-staged": "^15.0.0"
}
```
### 2. type-check entfernt
`type-check` im Pre-Commit war zu langsam (30+ Sekunden) und blockierte den Workflow.
```diff
// lint-staged.config.js
module.exports = {
'*.{ts,tsx,js,jsx}': [
'eslint --fix',
'prettier --write',
- 'tsc --noEmit',
],
'*.{svelte}': [
'prettier --write',
- 'svelte-check',
],
};
```
Type-Checking läuft weiterhin in der CI Pipeline.
---
## Auth Verbesserungen
### 403 für Unverified Email
Bisher erhielten Nutzer mit unbestätigter E-Mail einen generischen 401 Error. Jetzt gibt es einen expliziten 403 mit klarer Fehlermeldung.
```typescript
if (!user.emailVerified) {
throw new HttpException(
{
statusCode: 403,
error: 'email_not_verified',
message: 'Please verify your email address before logging in.',
},
HttpStatus.FORBIDDEN
);
}
```
### Password Min Length
Die Mindestlänge für das Reset-Password wurde von 6 auf 8 Zeichen angehoben, um mit der Registration übereinzustimmen.
```diff
const resetPasswordSchema = z.object({
- password: z.string().min(6),
+ password: z.string().min(8),
token: z.string(),
});
```
---
## Traces: EAS Build für TestFlight
EAS Build für die Traces App konfiguriert, inkl. TestFlight Distribution.
```json
{
"build": {
"production": {
"distribution": "store",
"ios": {
"buildConfiguration": "Release"
}
},
"preview": {
"distribution": "internal",
"ios": {
"simulator": false
}
}
},
"submit": {
"production": {
"ios": {
"appleId": "till@manacore.app",
"ascAppId": "traces-app-id"
}
}
}
}
```
---
## Calendar Settings Audit
Dokumentation aller Calendar Settings mit aktuellem Status und geplanten Erweiterungen erstellt.
---
## Zusammenfassung
| Bereich | Commits | Highlights |
| ----------------- | ------- | ---------------------------------- |
| **Mukke** | 1 | Offline-first Music Player |
| **Calendar E2E** | 1 | 26 Playwright Tests |
| **Pre-Commit** | 1 | eslint-config, type-check entfernt |
| **Auth** | 2 | 403 Unverified, Password Length |
| **Traces** | 2 | EAS Build, TestFlight |
| **Calendar Docs** | 1 | Settings Audit |
| **Bot Services** | 1 | Build Fix |
---
## Nächste Schritte
1. **Mukke Player** - Background Audio und Lock Screen Controls
2. **Calendar E2E** - Recurring Events Tests
3. **Traces TestFlight** - Erster interner Build
4. **Test Coverage** - Unit Tests für Contacts und Todo

View file

@ -0,0 +1,240 @@
---
title: 'Test Coverage Expansion: Contacts & Todo'
description: 'Umfassende Unit Tests für Contacts (62 Tests) und Todo (39 Tests) Web Apps. Cross-App Test Coverage mit Vitest erweitert und ungenutzten Code entfernt.'
date: 2026-03-18
author: 'Till Schneider'
category: 'update'
tags: ['testing', 'unit-tests', 'contacts', 'todo', 'calendar', 'vitest', 'coverage']
featured: false
commits: 5
readTime: 6
stats:
filesChanged: 42
linesAdded: 3200
linesRemoved: 890
contributors:
- name: 'Till Schneider'
handle: 'Till-JS'
commits: 5
workingHours:
start: '2026-03-18T11:00'
end: '2026-03-19T11:00'
---
Fokussierter Tag mit **5 Commits** für Test Coverage und Code Cleanup:
- **Contacts Web** - 62 Unit Tests für Stores, Utils und API Client
- **Todo Web** - 39 Unit Tests, d3-force entfernt, Default Title Fix
- **Cross-App Coverage** - Calendar, Contacts und Todo Test-Infrastruktur
- **Code Cleanup** - Ungenutzte Network View Remnants entfernt
---
## Contacts Web: 62 Unit Tests
Umfassende Test Coverage für die Contacts Web App mit Vitest.
### Test Suites
| Suite | Tests | Beschreibung |
| ----------------- | ----- | ------------------------------------ |
| **Contact Store** | 18 | CRUD Operationen, Filtering, Sorting |
| **Group Store** | 12 | Gruppenverwaltung, Mitglieder |
| **API Client** | 15 | HTTP Requests, Error Handling, Retry |
| **Utils** | 10 | Formatierung, Validierung, Search |
| **Types** | 7 | Type Guards, Transformations |
### Store Test Beispiel
```typescript
describe('contactStore', () => {
it('should filter contacts by search term', () => {
const store = createContactStore();
store.setContacts([
{ id: '1', name: 'Alice Schmidt', email: 'alice@example.com' },
{ id: '2', name: 'Bob Mueller', email: 'bob@example.com' },
{ id: '3', name: 'Charlie Schmidt', email: 'charlie@example.com' },
]);
store.setSearchTerm('Schmidt');
expect(store.filteredContacts).toHaveLength(2);
expect(store.filteredContacts.map((c) => c.name)).toEqual(['Alice Schmidt', 'Charlie Schmidt']);
});
it('should handle API errors gracefully', async () => {
vi.mocked(fetch).mockRejectedValueOnce(new Error('Network error'));
const store = createContactStore();
const result = await store.loadContacts();
expect(result.ok).toBe(false);
expect(result.error?.code).toBe('NETWORK_ERROR');
});
});
```
### API Client Tests
```typescript
describe('contactsApiClient', () => {
it('should retry on 503 errors', async () => {
vi.mocked(fetch)
.mockResolvedValueOnce(new Response(null, { status: 503 }))
.mockResolvedValueOnce(new Response(JSON.stringify({ data: [] })));
const result = await apiClient.getContacts();
expect(fetch).toHaveBeenCalledTimes(2);
expect(result.ok).toBe(true);
});
});
```
---
## Todo Web: 39 Unit Tests
Unit Tests für die Todo App mit zusätzlichem Code Cleanup.
### Test Suites
| Suite | Tests | Beschreibung |
| -------------- | ----- | ------------------------------- |
| **Todo Store** | 14 | CRUD, Completion, Reordering |
| **List Store** | 8 | Listen-Management, Default List |
| **Utils** | 9 | Date Helpers, Priority Sorting |
| **Components** | 8 | Render Tests, User Interactions |
### d3-force Entfernung
Die `d3-force` Dependency wurde entfernt. Sie war ursprünglich für eine Graph-Visualisierung geplant, die nie implementiert wurde.
```diff
"dependencies": {
- "d3-force": "^3.0.0",
- "@types/d3-force": "^3.0.0",
"svelte": "^5.0.0",
}
```
**Impact:** Bundle Size um ~45 KB reduziert.
### Default Title Fix
Neue Todos ohne Titel erhielten `undefined` statt einen leeren String. Das führte zu Darstellungsproblemen in der Liste.
```diff
function createTodo(input: Partial<Todo>): Todo {
return {
id: crypto.randomUUID(),
- title: input.title,
+ title: input.title ?? '',
completed: false,
priority: input.priority ?? 'medium',
createdAt: new Date().toISOString(),
};
}
```
---
## Cross-App Test Infrastructure
### Vitest Konfiguration
Einheitliche Vitest-Konfiguration für alle Web Apps:
```typescript
// vitest.config.ts (shared pattern)
export default defineConfig({
test: {
globals: true,
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{ts,js}'],
coverage: {
provider: 'v8',
reporter: ['text', 'html'],
include: ['src/lib/**/*.ts'],
exclude: ['**/*.d.ts', '**/*.test.ts'],
},
setupFiles: ['./src/test/setup.ts'],
},
});
```
### Coverage Übersicht
| App | Tests | Statements | Branches | Functions |
| ------------ | ----- | ---------- | -------- | --------- |
| **Contacts** | 62 | 78% | 72% | 81% |
| **Todo** | 39 | 74% | 68% | 76% |
| **Calendar** | 26 | 65% | 58% | 69% |
### Test Commands
```bash
# Einzelne App testen
pnpm --filter @contacts/web test
pnpm --filter @todo/web test
# Mit Coverage Report
pnpm --filter @contacts/web test -- --coverage
# Alle Web App Tests
pnpm turbo run test --filter="*/web"
```
---
## Contacts: Network View Cleanup
Ungenutzte Remnants der geplanten Network-View (Graph-Visualisierung von Kontakt-Beziehungen) wurden entfernt.
### Entfernte Dateien
- `src/lib/components/NetworkView.svelte`
- `src/lib/stores/networkStore.ts`
- `src/lib/utils/graphLayout.ts`
- `src/lib/types/network.ts`
### Entfernte Dependencies
```diff
- "d3-force": "^3.0.0",
- "@types/d3-force": "^3.0.10",
- "d3-selection": "^3.0.0",
```
---
## Contacts: Production Config Fix
Die `PUBLIC_TODO_BACKEND_URL` fehlte in der Production-Konfiguration der Contacts Web App. Das führte dazu, dass die Todo-Integration in Production nicht funktionierte.
```diff
# .env.production
PUBLIC_CONTACTS_BACKEND_URL=https://contacts-api.manacore.app
+ PUBLIC_TODO_BACKEND_URL=https://todo-api.manacore.app
```
---
## Zusammenfassung
| Bereich | Commits | Highlights |
| ------------------ | ------- | --------------------------- |
| **Contacts Tests** | 1 | 62 Unit Tests, Stores + API |
| **Todo Tests** | 1 | 39 Tests, d3-force entfernt |
| **Cross-App** | 1 | Vitest Config, Coverage |
| **Cleanup** | 1 | Network View Remnants |
| **Config** | 1 | Production URL Fix |
---
## Nächste Schritte
1. **Coverage > 80%** - Verbleibende Lücken in Stores schließen
2. **Calendar Tests** - Coverage auf 80% bringen
3. **CI Integration** - Test Coverage Reports in PR Checks
4. **E2E Tests** - Contacts und Todo Playwright Tests