refactor: rename nutriphi module to food (Essen)

Complete rename across the entire monorepo pre-launch:
- Module, routes, API, i18n, standalone landing app directories
- All code identifiers, display names, logo component
- German user-facing label: "Essen" (English brand stays "Food")
- Dexie table nutriFavorites -> foodFavorites
- Infra configs (docker-compose, cloudflared, nginx, wrangler)

Zero residue of nutriphi remains. No data migration needed (pre-launch).

Follow-up: run pnpm install, update Cloudflare DNS
(food.mana.how), rename Cloudflare Pages project.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-14 15:30:07 +02:00
parent f5cb833b04
commit 53b3746b98
196 changed files with 863 additions and 719 deletions

View file

@ -87,7 +87,7 @@ Only servers that need their own database use Drizzle. Most apps rely on mana-sy
**Servers with Drizzle:** chat, todo, moodlit, context, plants, presi, traces, uload, wisekeep, news
**Servers without Drizzle (mana-sync only):** calendar, contacts, cards, mukke, nutriphi, picture, questions, storage
**Servers without Drizzle (mana-sync only):** calendar, contacts, cards, mukke, food, picture, questions, storage
## Running Servers

View file

@ -1,11 +1,11 @@
# NutriPhi MVP-Plan
# Food MVP-Plan
> **Status:** Planung abgeschlossen
> **Letzte Aktualisierung:** 2026-01-24
## Vision
NutriPhi ist eine datenschutzorientierte, KI-gestützte Ernährungs-Tracking-Web-App für gesundheitsbewusste Menschen. Sie ermöglicht das Erfassen von Mahlzeiten per Foto oder Text und liefert vollständige Nährwertanalysen mit personalisierten Empfehlungen.
Food ist eine datenschutzorientierte, KI-gestützte Ernährungs-Tracking-Web-App für gesundheitsbewusste Menschen. Sie ermöglicht das Erfassen von Mahlzeiten per Foto oder Text und liefert vollständige Nährwertanalysen mit personalisierten Empfehlungen.
---
@ -113,7 +113,7 @@ NutriPhi ist eine datenschutzorientierte, KI-gestützte Ernährungs-Tracking-Web
### Projektstruktur
```
apps/nutriphi/
apps/food/
├── apps/
│ ├── web/ # SvelteKit (mobile-optimiert)
│ └── backend/ # NestJS API
@ -268,7 +268,7 @@ Output-Format: JSON mit strukturierten Nährwertdaten
```
┌─────────────────────────────┐
NutriPhi [+] [Profile] │
Food [+] [Profile] │
├─────────────────────────────┤
│ │
│ Heute: 1.450 / 2.000 kcal │
@ -378,7 +378,7 @@ Output-Format: JSON mit strukturierten Nährwertdaten
### Wiederverwendbare Shared Components
| Komponente | Verwendung in NutriPhi |
| Komponente | Verwendung in Food |
|------------|------------------------|
| `HeroSection` | "Fotografiere dein Essen, verstehe was du isst" |
| `FeatureSection` | KI-Analyse, Nährwerte, Tracking, Empfehlungen |
@ -392,14 +392,14 @@ Output-Format: JSON mit strukturierten Nährwertdaten
### Projektstruktur
```
apps/nutriphi/apps/landing/
apps/food/apps/landing/
├── src/
│ ├── pages/
│ │ └── index.astro
│ ├── layouts/
│ │ └── Layout.astro
│ ├── styles/
│ │ └── global.css # NutriPhi Theme (Grün)
│ │ └── global.css # Food Theme (Grün)
│ └── components/ # Custom falls nötig
├── astro.config.mjs
├── package.json
@ -409,7 +409,7 @@ apps/nutriphi/apps/landing/
### Farbschema (CSS Custom Properties)
```css
/* NutriPhi Theme - Gesundheit/Natur */
/* Food Theme - Gesundheit/Natur */
--color-primary: #22C55E; /* Green 500 */
--color-primary-hover: #16A34A; /* Green 600 */
--color-secondary: #F97316; /* Orange 500 */

View file

@ -1,8 +1,8 @@
# NutriPhi - App-Planung
# Food - App-Planung
## Vision
NutriPhi ist eine KI-gestützte Ernährungs-Tracking-App, die es Nutzern ermöglicht, ihre Mahlzeiten per Foto, Text oder Sprache zu erfassen und automatisch Nährwertinformationen zu erhalten.
Food ist eine KI-gestützte Ernährungs-Tracking-App, die es Nutzern ermöglicht, ihre Mahlzeiten per Foto, Text oder Sprache zu erfassen und automatisch Nährwertinformationen zu erhalten.
## Planungsdokumente

View file

@ -22,7 +22,7 @@
| 7 | **Presi** | decks, slides | Ja (Store + Pages umgeschrieben) |
| 8 | **Picture** | images, boards, boardItems, tags, imageTags | Ja (Gallery + Boards umgeschrieben) |
| 9 | **Inventar** | collections, items, locations, categories | Nein (local-store angelegt, Stores nutzen noch localStorage) |
| 10 | **NutriPhi** | meals, goals, favorites | Nein (local-store angelegt, Stores nutzen noch API) |
| 10 | **Food** | meals, goals, favorites | Nein (local-store angelegt, Stores nutzen noch API) |
| 11 | **Planta** | plants, plantPhotos, wateringSchedules, wateringLogs | Nein (local-store angelegt, Stores nutzen noch API) |
| 12 | **Storage** | files, folders, tags, fileTags | Nein (local-store angelegt, Stores nutzen noch API) |
| 13 | **Chat** | conversations, messages, templates | Nein (local-store angelegt, Stores nutzen noch API) |
@ -108,7 +108,7 @@ Fertige Endpoints: Better Auth nativ, Auth (Register/Login/Logout/Validate), Gui
```
# Local-First (Phase 3)
ce51fd5f feat(apps): migrate Presi, Picture, Inventar, NutriPhi, Planta, Storage
ce51fd5f feat(apps): migrate Presi, Picture, Inventar, Food, Planta, Storage
8d880f1f feat(apps): migrate Chat, Questions, Mukke, Context, Photos
a31ccc6c feat(apps): add local-store to SkilltTree and CityCorners
7754cf6e refactor(skilltree): replace custom idb → @manacore/local-store

View file

@ -333,7 +333,7 @@ Alle Web-Apps mit CRUD-Datenmodell wurden auf Local-First migriert:
| **Picture** | images, boards, boardItems, tags, imageTags | Replicate API, Upload, Explore |
| **Presi** | decks, slides | Share-Links |
| **Inventar** | collections, items, locations, categories | Nur Sync |
| **NutriPhi** | meals, goals, favorites | AI-Analyse (Gemini), Recommendations |
| **Food** | meals, goals, favorites | AI-Analyse (Gemini), Recommendations |
| **Planta** | plants, plantPhotos, wateringSchedules, wateringLogs | Foto-Upload, AI-Analyse (Gemini) |
| **Storage** | files, folders, tags, fileTags | Datei-Upload/Download, Shares, Versionen |
| **Chat** | conversations, messages, templates | LLM Streaming |

View file

@ -46,7 +46,7 @@ manacore-monorepo/
│ │ │ └── landing/
│ │ └── packages/
│ │
│ ├── nutriphi/
│ ├── food/
│ │ ├── apps/
│ │ │ ├── backend/
│ │ │ ├── mobile/
@ -134,7 +134,7 @@ mkdir -p services
| `cards/` | `apps/cards/` |
| `memoro/` | `apps/memoro/` |
| `picture/` | `apps/picture/` |
| `nutriphi/` | `apps/nutriphi/` |
| `food/` | `apps/food/` |
| `uload/` | `apps/uload/` |
| `news/` | `apps/news/` |
| `manacore/` | `apps/manacore/` |
@ -146,7 +146,7 @@ git mv maerchenzauber apps/maerchenzauber
git mv cards apps/cards
git mv memoro apps/memoro
git mv picture apps/picture
git mv nutriphi apps/nutriphi
git mv food apps/food
git mv uload apps/uload
git mv news apps/news
git mv manacore apps/manacore
@ -160,7 +160,7 @@ Projects with backends at root level need restructuring:
| ------------------------ | ----------------------------- |
| `apps/chat/backend/` | `apps/chat/apps/backend/` |
| `apps/cards/backend/` | `apps/cards/apps/backend/` |
| `apps/nutriphi/backend/` | `apps/nutriphi/apps/backend/` |
| `apps/food/backend/` | `apps/food/apps/backend/` |
```bash
# Chat: move backend into apps/
@ -171,9 +171,9 @@ git mv apps/chat/backend apps/chat/apps/backend
mkdir -p apps/cards/apps
git mv apps/cards/backend apps/cards/apps/backend
# Nutriphi: move backend into apps/
mkdir -p apps/nutriphi/apps
git mv apps/nutriphi/backend apps/nutriphi/apps/backend
# Food: move backend into apps/
mkdir -p apps/food/apps
git mv apps/food/backend apps/food/apps/backend
```
### 2.3 Move mana-core-auth to services/
@ -231,7 +231,7 @@ No changes needed - turbo.json uses task definitions, not paths.
"picture:dev": "turbo run dev --filter=@picture/*...",
"uload:dev": "turbo run dev --filter=@uload/*...",
"chat:dev": "turbo run dev --filter=@chat/*...",
"nutriphi:dev": "turbo run dev --filter=@nutriphi/*...",
"food:dev": "turbo run dev --filter=@food/*...",
"news:dev": "turbo run dev --filter=@news/*...",
"dev:maerchenzauber:web": "pnpm --filter @maerchenzauber/web dev",
@ -266,11 +266,11 @@ No changes needed - turbo.json uses task definitions, not paths.
"dev:chat:backend": "pnpm --filter @chat/backend start:dev",
"dev:chat:app": "turbo run dev --filter=@chat/web --filter=@chat/backend",
"dev:nutriphi:mobile": "pnpm --filter @nutriphi/mobile dev",
"dev:nutriphi:web": "pnpm --filter @nutriphi/web dev",
"dev:nutriphi:landing": "pnpm --filter @nutriphi/landing dev",
"dev:nutriphi:backend": "pnpm --filter @nutriphi/backend start:dev",
"dev:nutriphi:app": "turbo run dev --filter=@nutriphi/web --filter=@nutriphi/backend",
"dev:food:mobile": "pnpm --filter @food/mobile dev",
"dev:food:web": "pnpm --filter @food/web dev",
"dev:food:landing": "pnpm --filter @food/landing dev",
"dev:food:backend": "pnpm --filter @food/backend start:dev",
"dev:food:app": "turbo run dev --filter=@food/web --filter=@food/backend",
"dev:news:mobile": "pnpm --filter @news/mobile dev",
"dev:news:web": "pnpm --filter @news/web dev",

View file

@ -29,7 +29,7 @@
| 12 | **uload** | queries (umfangreich), types | 3 routes (dashboard, links, analytics) | **Done** |
| 13 | **context** | queries, types | 5 routes (dashboard, spaces, documents) | **Done** |
| 14 | **questions** | queries, types | 4 routes (list, collections, new, detail) | **Done** |
| 15 | **nutriphi** | queries, types, constants | 4 routes (dashboard, add, history, goals) | **Done** |
| 15 | **food** | queries, types, constants | 4 routes (dashboard, add, history, goals) | **Done** |
| 16 | **storage** | stores (2), queries, types | 7 routes (files, folders, favorites, search, trash) | **Done** |
| 17 | **cards** | stores (2), components (2), queries | 6 routes (decks, study, explore, progress) | **Done** |
| 18 | **contacts** | stores (3), queries, types | 3 routes (list, detail/edit) | **Done** |
@ -109,7 +109,7 @@ Alle Apps die zum ManaCore-Ökosystem gehören und von Shared IndexedDB, Dashboa
| **times** | Zeiterfassung, Dashboard-Widget |
| **context** | Dokument-Workspace |
| **questions** | Research-Assistant |
| **nutriphi** | Ernährung |
| **food** | Ernährung |
| **planta** | Pflanzenpflege |
| **uload** | URL-Shortener, Links |
| **calc** | Rechner |
@ -259,7 +259,7 @@ src/lib/modules/
├── times/
├── context/
├── questions/
├── nutriphi/
├── food/
├── planta/
├── uload/
├── calc/
@ -367,7 +367,7 @@ src/routes/
│ ├── times/+page.svelte
│ ├── context/+page.svelte
│ ├── questions/+page.svelte
│ ├── nutriphi/+page.svelte
│ ├── food/+page.svelte
│ ├── planta/+page.svelte
│ ├── uload/+page.svelte
│ ├── calc/+page.svelte
@ -475,7 +475,7 @@ import { CITYCORNERS_COLLECTIONS } from '$lib/modules/citycorners/collections';
import { TIMES_COLLECTIONS } from '$lib/modules/times/collections';
import { CONTEXT_COLLECTIONS } from '$lib/modules/context/collections';
import { QUESTIONS_COLLECTIONS } from '$lib/modules/questions/collections';
import { NUTRIPHI_COLLECTIONS } from '$lib/modules/nutriphi/collections';
import { FOOD_COLLECTIONS } from '$lib/modules/food/collections';
import { PLANTA_COLLECTIONS } from '$lib/modules/planta/collections';
import { ULOAD_COLLECTIONS } from '$lib/modules/uload/collections';
import { CALC_COLLECTIONS } from '$lib/modules/calc/collections';
@ -521,7 +521,7 @@ db.version(1).stores({
...TIMES_COLLECTIONS,
...CONTEXT_COLLECTIONS,
...QUESTIONS_COLLECTIONS,
...NUTRIPHI_COLLECTIONS,
...FOOD_COLLECTIONS,
...PLANTA_COLLECTIONS,
...ULOAD_COLLECTIONS,
...CALC_COLLECTIONS,
@ -578,7 +578,7 @@ export const SYNC_APP_MAP: Record<string, string[]> = {
times: ['clients', 'tProjects', 'timeEntries', 'tTags', 'tTemplates', 'tSettings'],
context: ['spaces', 'documents'],
questions: ['qCollections', 'questions', 'answers'],
nutriphi: ['meals', 'goals', 'nFavorites'],
food: ['meals', 'goals', 'nFavorites'],
planta: ['plants', 'plantPhotos', 'wateringSchedules', 'wateringLogs'],
uload: ['links', 'uTags', 'uFolders', 'linkTags'],
calc: ['calculations', 'savedFormulas'],
@ -769,7 +769,7 @@ Nach Komplexität sortiert — einfachste zuerst, um den Prozess einzuüben:
| 12 | **uload** | 12 | 10 | Mittel | Hat Backend-Server |
| 13 | **context** | 10 | 15 | Mittel | Mittlere Komplexität |
| 14 | **questions** | 10 | 14 | Mittel | Hat Backend-API |
| 15 | **nutriphi** | 12 | 10 | Mittel | Hat Backend-Server |
| 15 | **food** | 12 | 10 | Mittel | Hat Backend-Server |
| 16 | **storage** | 12 | 15 | Mittel | Hat Backend + MinIO |
| 17 | **cards** | 12 | 18 | Mittel | Hat Backend-Server |
| 18 | **contacts** | 23 | 39 | Komplex | Backend + Import/Export |

View file

@ -144,7 +144,7 @@ UMAMI_WEBSITE_ID_CALENDAR_LANDING=84862d98-727e-4e25-8645-639241dd1544
UMAMI_WEBSITE_ID_CLOCK_LANDING=0332b471-a022-46af-a726-0f45932bfd58
UMAMI_WEBSITE_ID_PICTURE_LANDING=d3ac98e6-0d1a-47a3-a218-2a81fff596bd
UMAMI_WEBSITE_ID_TODO_LANDING=538eb4b6-2241-45a3-994d-cdb9bdb0c250
UMAMI_WEBSITE_ID_NUTRIPHI_LANDING=15610d03-b280-4b92-9c71-0ef89c23202b
UMAMI_WEBSITE_ID_FOOD_LANDING=15610d03-b280-4b92-9c71-0ef89c23202b
UMAMI_WEBSITE_ID_PRESI_LANDING=dd485016-0077-47b9-9f59-ab2c6c1730ee
UMAMI_WEBSITE_ID_MUKKE_LANDING=b2c9ab34-3c53-4463-9dde-1ecf098886a5
@ -219,18 +219,18 @@ PICTURE_APP_ID=picture-app
PICTURE_MANA_SERVICE_KEY=
# ============================================
# NUTRIPHI PROJECT
# FOOD PROJECT
# ============================================
NUTRIPHI_BACKEND_PORT=3023
NUTRIPHI_DATABASE_URL=postgresql://mana:devpassword@localhost:5432/mana_platform
NUTRIPHI_APP_ID=nutriphi
FOOD_BACKEND_PORT=3023
FOOD_DATABASE_URL=postgresql://mana:devpassword@localhost:5432/mana_platform
FOOD_APP_ID=food
# Google Gemini API for food image analysis
GEMINI_API_KEY=AIzaSyBR9iP74hlo-mhI-Cl4QEvKprRzPPMb-GA
# S3 Storage (uses MinIO locally via shared S3_* variables)
NUTRIPHI_S3_PUBLIC_URL=http://localhost:9000/nutriphi-storage
FOOD_S3_PUBLIC_URL=http://localhost:9000/food-storage
# ============================================
# ZITARE PROJECT
@ -472,5 +472,5 @@ GPU_API_KEY=sk-gpu-cf483ede1e05e28fba5e56c94cd3c24e7c245e57816d3e86
GPU_SERVER_URL=https://gpu.mana.how
GPU_SERVER_LAN_URL=http://192.168.178.11
# Vision Model for NutriPhi + Planta (local, replaces Google Gemini)
# Vision Model for Food + Planta (local, replaces Google Gemini)
VISION_MODEL=ollama/gemma3:12b

View file

@ -110,7 +110,7 @@ AZURE_STORAGE_ACCOUNT_NAME=
AZURE_STORAGE_ACCOUNT_KEY=
# ─── Google Gemini ──────────────────────────────────────────
# Used by mana-llm + several Gemini-Vision modules (planta, nutriphi).
# Used by mana-llm + several Gemini-Vision modules (planta, food).
GEMINI_API_KEY=
# ─── Service-to-service auth keys ───────────────────────────

View file

@ -98,7 +98,7 @@ updates:
- "automated"
- package-ecosystem: "docker"
directory: "/apps/nutriphi/apps/backend"
directory: "/apps/food/apps/backend"
schedule:
interval: "weekly"
open-pull-requests-limit: 5

View file

@ -71,8 +71,8 @@ jobs:
storage-backend: ${{ steps.changes.outputs.storage-backend }}
storage-web: ${{ steps.changes.outputs.storage-web }}
telegram-stats-bot: ${{ steps.changes.outputs.telegram-stats-bot }}
nutriphi-backend: ${{ steps.changes.outputs.nutriphi-backend }}
nutriphi-web: ${{ steps.changes.outputs.nutriphi-web }}
food-backend: ${{ steps.changes.outputs.food-backend }}
food-web: ${{ steps.changes.outputs.food-web }}
skilltree-web: ${{ steps.changes.outputs.skilltree-web }}
any-changes: ${{ steps.changes.outputs.any-changes }}
steps:
@ -109,8 +109,8 @@ jobs:
echo "storage-backend=true" >> $GITHUB_OUTPUT
echo "storage-web=true" >> $GITHUB_OUTPUT
echo "telegram-stats-bot=true" >> $GITHUB_OUTPUT
echo "nutriphi-backend=true" >> $GITHUB_OUTPUT
echo "nutriphi-web=true" >> $GITHUB_OUTPUT
echo "food-backend=true" >> $GITHUB_OUTPUT
echo "food-web=true" >> $GITHUB_OUTPUT
echo "skilltree-web=true" >> $GITHUB_OUTPUT
echo "any-changes=true" >> $GITHUB_OUTPUT
exit 0
@ -151,8 +151,8 @@ jobs:
echo "storage-backend=true" >> $GITHUB_OUTPUT
echo "storage-web=true" >> $GITHUB_OUTPUT
echo "telegram-stats-bot=true" >> $GITHUB_OUTPUT
echo "nutriphi-backend=true" >> $GITHUB_OUTPUT
echo "nutriphi-web=true" >> $GITHUB_OUTPUT
echo "food-backend=true" >> $GITHUB_OUTPUT
echo "food-web=true" >> $GITHUB_OUTPUT
echo "skilltree-web=true" >> $GITHUB_OUTPUT
echo "any-changes=true" >> $GITHUB_OUTPUT
exit 0
@ -341,20 +341,20 @@ jobs:
echo "telegram-stats-bot=false" >> $GITHUB_OUTPUT
fi
# nutriphi-backend
NUTRIPHI_BACKEND_CHANGED=$(check_pattern "apps/nutriphi/apps/backend/|apps/nutriphi/packages/")
if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$NUTRIPHI_BACKEND_CHANGED" == "true" ]; then
echo "nutriphi-backend=true" >> $GITHUB_OUTPUT
# food-backend
FOOD_BACKEND_CHANGED=$(check_pattern "apps/food/apps/backend/|apps/food/packages/")
if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$FOOD_BACKEND_CHANGED" == "true" ]; then
echo "food-backend=true" >> $GITHUB_OUTPUT
else
echo "nutriphi-backend=false" >> $GITHUB_OUTPUT
echo "food-backend=false" >> $GITHUB_OUTPUT
fi
# nutriphi-web
NUTRIPHI_WEB_CHANGED=$(check_pattern "apps/nutriphi/apps/web/|apps/nutriphi/packages/")
if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SHARED_UI_CHANGED" == "true" ] || [ "$SHARED_WEB_CHANGED" == "true" ] || [ "$NUTRIPHI_WEB_CHANGED" == "true" ]; then
echo "nutriphi-web=true" >> $GITHUB_OUTPUT
# food-web
FOOD_WEB_CHANGED=$(check_pattern "apps/food/apps/web/|apps/food/packages/")
if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SHARED_UI_CHANGED" == "true" ] || [ "$SHARED_WEB_CHANGED" == "true" ] || [ "$FOOD_WEB_CHANGED" == "true" ]; then
echo "food-web=true" >> $GITHUB_OUTPUT
else
echo "nutriphi-web=false" >> $GITHUB_OUTPUT
echo "food-web=false" >> $GITHUB_OUTPUT
fi
# skilltree-backend: REMOVED — migrated to local-first
@ -406,8 +406,8 @@ jobs:
echo "| storage-backend | ${{ steps.changes.outputs.storage-backend }} |" >> $GITHUB_STEP_SUMMARY
echo "| storage-web | ${{ steps.changes.outputs.storage-web }} |" >> $GITHUB_STEP_SUMMARY
echo "| telegram-stats-bot | ${{ steps.changes.outputs.telegram-stats-bot }} |" >> $GITHUB_STEP_SUMMARY
echo "| nutriphi-backend | ${{ steps.changes.outputs.nutriphi-backend }} |" >> $GITHUB_STEP_SUMMARY
echo "| nutriphi-web | ${{ steps.changes.outputs.nutriphi-web }} |" >> $GITHUB_STEP_SUMMARY
echo "| food-backend | ${{ steps.changes.outputs.food-backend }} |" >> $GITHUB_STEP_SUMMARY
echo "| food-web | ${{ steps.changes.outputs.food-web }} |" >> $GITHUB_STEP_SUMMARY
echo "| skilltree-backend | removed |" >> $GITHUB_STEP_SUMMARY
echo "| skilltree-web | ${{ steps.changes.outputs.skilltree-web }} |" >> $GITHUB_STEP_SUMMARY
echo "| zitare-backend | removed |" >> $GITHUB_STEP_SUMMARY
@ -1173,11 +1173,11 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
build-nutriphi-backend:
name: Build nutriphi-backend
build-food-backend:
name: Build food-backend
runs-on: ubuntu-latest
needs: detect-changes
if: needs.detect-changes.outputs.nutriphi-backend == 'true'
if: needs.detect-changes.outputs.food-backend == 'true'
steps:
- uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3
@ -1190,23 +1190,23 @@ jobs:
- uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/${{ github.repository_owner }}/nutriphi-backend
images: ghcr.io/${{ github.repository_owner }}/food-backend
tags: type=raw,value=latest
- uses: docker/build-push-action@v5
with:
context: .
file: apps/nutriphi/apps/backend/Dockerfile
file: apps/food/apps/backend/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-nutriphi-web:
name: Build nutriphi-web
build-food-web:
name: Build food-web
runs-on: ubuntu-latest
needs: detect-changes
if: needs.detect-changes.outputs.nutriphi-web == 'true'
if: needs.detect-changes.outputs.food-web == 'true'
steps:
- uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3
@ -1219,12 +1219,12 @@ jobs:
- uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/${{ github.repository_owner }}/nutriphi-web
images: ghcr.io/${{ github.repository_owner }}/food-web
tags: type=raw,value=latest
- uses: docker/build-push-action@v5
with:
context: .
file: apps/nutriphi/apps/web/Dockerfile
file: apps/food/apps/web/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}

View file

@ -20,7 +20,7 @@ Monorepo containing all Mana projects — a self-hosted multi-app ecosystem with
| **storage** | Cloud storage | NestJS backend, SvelteKit web |
| **questions** | Q&A with web search | SvelteKit web |
| **skilltree** | Skill tree visualization | NestJS backend, SvelteKit web |
| **nutriphi** | Nutrition tracking | NestJS backend, SvelteKit web |
| **food** | Nutrition tracking | NestJS backend, SvelteKit web |
| **citycorners** | City guide | NestJS backend, SvelteKit web, Astro landing |
| **presi** | Presentation tool | NestJS backend, SvelteKit web |
| **photos** | Photo management | NestJS backend, SvelteKit web |

View file

@ -25,7 +25,7 @@ import { pictureRoutes } from './modules/picture/routes';
import { storageRoutes } from './modules/storage/routes';
import { todoRoutes } from './modules/todo/routes';
import { plantsRoutes } from './modules/plants/routes';
import { nutriphiRoutes } from './modules/nutriphi/routes';
import { foodRoutes } from './modules/food/routes';
import { guidesRoutes } from './modules/guides/routes';
import { moodlitRoutes } from './modules/moodlit/routes';
import { newsRoutes } from './modules/news/routes';
@ -57,7 +57,7 @@ app.route('/api/v1/picture', pictureRoutes);
app.route('/api/v1/storage', storageRoutes);
app.route('/api/v1/todo', todoRoutes);
app.route('/api/v1/plants', plantsRoutes);
app.route('/api/v1/nutriphi', nutriphiRoutes);
app.route('/api/v1/food', foodRoutes);
app.route('/api/v1/guides', guidesRoutes);
app.route('/api/v1/moodlit', moodlitRoutes);
app.route('/api/v1/news', newsRoutes);

View file

@ -1,5 +1,5 @@
/**
* NutriPhi module Meal analysis (Gemini Vision via mana-llm) + recommendations.
* Food module Meal analysis (Gemini Vision via mana-llm) + recommendations.
*
* CRUD for meals, goals, favorites is handled by mana-sync. This module
* owns the server-only operations: photo upload to mana-media, structured
@ -94,7 +94,7 @@ routes.post('/photos/upload', async (c) => {
try {
const { uploadImageToMedia } = await import('../../lib/media');
const buffer = await file.arrayBuffer();
const result = await uploadImageToMedia(buffer, file.name, { app: 'nutriphi', userId });
const result = await uploadImageToMedia(buffer, file.name, { app: 'food', userId });
return c.json(
{
@ -106,7 +106,7 @@ routes.post('/photos/upload', async (c) => {
201
);
} catch (err) {
logger.error('nutriphi.upload_failed', {
logger.error('food.upload_failed', {
error: err instanceof Error ? err.message : String(err),
});
return c.json({ error: 'Upload failed' }, 500);
@ -141,7 +141,7 @@ routes.post('/analysis/photo', async (c) => {
});
return c.json(envelope(object));
} catch (err) {
logger.error('nutriphi.photo_analysis_failed', {
logger.error('food.photo_analysis_failed', {
error: err instanceof Error ? err.message : String(err),
});
return c.json({ error: 'Analysis failed' }, 500);
@ -173,7 +173,7 @@ routes.post('/analysis/text', async (c) => {
});
return c.json(envelope(object));
} catch (err) {
logger.error('nutriphi.text_analysis_failed', {
logger.error('food.text_analysis_failed', {
error: err instanceof Error ? err.message : String(err),
});
return c.json({ error: 'Analysis failed' }, 500);
@ -218,4 +218,4 @@ routes.post('/recommendations/generate', async (c) => {
return c.json({ recommendations: hints });
});
export { routes as nutriphiRoutes };
export { routes as foodRoutes };

View file

@ -5,7 +5,7 @@
* module owns the server-only operations: photo upload to mana-media
* and structured plant identification via the Vercel AI SDK
* (`generateObject`) using the shared PlantIdentificationSchema in
* @mana/shared-types. See nutriphi/routes.ts for the rationale behind
* @mana/shared-types. See food/routes.ts for the rationale behind
* the AI SDK + Zod approach.
*/
@ -21,20 +21,20 @@ import {
import { logger, type AuthVariables } from '@mana/shared-hono';
const LLM_URL = process.env.MANA_LLM_URL || 'http://localhost:3025';
// See nutriphi/routes.ts for the rationale on the default model and
// See food/routes.ts for the rationale on the default model and
// the /v1 base URL.
const VISION_MODEL = process.env.VISION_MODEL || 'ollama/gemma3:4b';
const llm = createOpenAICompatible({
name: 'mana-llm',
baseURL: `${LLM_URL}/v1`,
// See nutriphi/routes.ts for the rationale on this flag.
// See food/routes.ts for the rationale on this flag.
supportsStructuredOutputs: true,
});
const IDENTIFICATION_PROMPT = `Du bist ein Pflanzenexperte. Analysiere das Pflanzenfoto und liefere eine strukturierte Identifikation mit lateinischem Namen, deutschen Trivialnamen, Pflegehinweisen und einer Gesundheitseinschätzung. Antworte auf Deutsch.`;
// See nutriphi/routes.ts for the rationale: this is a forward-compat
// See food/routes.ts for the rationale: this is a forward-compat
// hint for Anthropic prompt caching, ignored by Gemini today.
const SYSTEM_CACHE_HINT = {
anthropic: { cacheControl: { type: 'ephemeral' as const } },

View file

@ -37,7 +37,7 @@ open http://localhost:9001
| `picture-storage` | Picture | AI-generated images |
| `chat-storage` | Chat | User file uploads |
| `cards-storage` | Cards | Card/deck assets |
| `nutriphi-storage` | NutriPhi | Meal photos |
| `food-storage` | Food | Meal photos |
| `contacts-storage` | Contacts | Contact avatars |
| `calendar-storage` | Calendar | Event attachments |

17
apps/food/CLAUDE.md Normal file
View file

@ -0,0 +1,17 @@
# Food — consolidated into the unified Mana app
This product was migrated into the unified Mana monorepo. The legacy
per-product `apps/food/apps/backend/` and `apps/food/apps/web/`
directories have been removed. Active code now lives in:
- **Backend compute routes**: [`apps/api/src/modules/food/routes.ts`](../api/src/modules/food/routes.ts) (Gemini meal-photo analysis + text analysis + recommendations)
- **Frontend module** (local-first): [`apps/mana/apps/web/src/lib/modules/food/`](../mana/apps/web/src/lib/modules/food/)
- **Web route**: [`apps/mana/apps/web/src/routes/(app)/food/`](../mana/apps/web/src/routes/(app)/food/)
- **Landing page** (still standalone): [`apps/food/apps/landing/`](apps/landing/)
For monorepo-wide patterns (auth, sync, encryption, services), see the
[root `CLAUDE.md`](../../CLAUDE.md) and [`apps/mana/CLAUDE.md`](../mana/CLAUDE.md).
The previous standalone "Food Project Guide" was deleted in the
audit cleanup of 2026-04-09 — it had been inaccurate since the
consolidation. Pre-consolidation reference is in git history.

View file

@ -3,5 +3,5 @@ import tailwind from '@astrojs/tailwind';
export default defineConfig({
integrations: [tailwind()],
site: 'https://nutriphi.mana.how',
site: 'https://food.mana.how',
});

View file

@ -1,5 +1,5 @@
{
"name": "@nutriphi/landing",
"name": "@food/landing",
"version": "0.2.0",
"private": true,
"type": "module",

View file

@ -6,7 +6,7 @@ interface Props {
description?: string;
}
const { title, description = 'NutriPhi - KI-gestützte Ernährungsanalyse per Foto' } = Astro.props;
const { title, description = 'Food - KI-gestützte Ernährungsanalyse per Foto' } = Astro.props;
---
<!doctype html>

View file

@ -71,7 +71,7 @@ const faqs = [
{
question: 'Funktioniert die App mit allen Gerichten?',
answer:
'NutriPhi erkennt die meisten Gerichte weltweit, von klassischer deutscher Küche bis zu asiatischen Spezialitäten. Bei unbekannten Gerichten kannst du manuell nachhelfen.',
'Food erkennt die meisten Gerichte weltweit, von klassischer deutscher Küche bis zu asiatischen Spezialitäten. Bei unbekannten Gerichten kannst du manuell nachhelfen.',
},
{
question: 'Wie funktioniert das Credit-System?',
@ -81,12 +81,12 @@ const faqs = [
{
question: 'Gibt es eine kostenlose Version?',
answer:
'Ja! Du kannst NutriPhi kostenlos nutzen mit täglich 3 Foto-Analysen. Für mehr Analysen und Premium-Features gibt es Mana Credits.',
'Ja! Du kannst Food kostenlos nutzen mit täglich 3 Foto-Analysen. Für mehr Analysen und Premium-Features gibt es Mana Credits.',
},
];
---
<Layout title="NutriPhi - Ernährung verstehen per Foto">
<Layout title="Food - Ernährung verstehen per Foto">
<!-- Navigation -->
<nav
class="fixed top-0 left-0 right-0 z-50 bg-[#0F1F0F]/90 backdrop-blur border-b border-green-900/30"
@ -97,10 +97,10 @@ const faqs = [
<div class="w-8 h-8 rounded-lg bg-primary flex items-center justify-center">
<span class="text-white font-bold">N</span>
</div>
<span class="font-semibold text-white">NutriPhi</span>
<span class="font-semibold text-white">Food</span>
</div>
<a
href="https://nutriphi.mana.how"
href="https://food.mana.how"
class="px-4 py-2 bg-primary hover:bg-primary-hover text-white font-medium rounded-lg transition-colors"
>
Jetzt starten
@ -138,13 +138,13 @@ const faqs = [
</h1>
<p class="text-xl text-gray-300 mb-10 max-w-2xl mx-auto">
NutriPhi analysiert deine Mahlzeiten per Foto und liefert dir sofort alle Nährwerte. Mit
Food analysiert deine Mahlzeiten per Foto und liefert dir sofort alle Nährwerte. Mit
KI-Coaching erreichst du deine Gesundheitsziele.
</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<a
href="https://nutriphi.mana.how"
href="https://food.mana.how"
class="px-8 py-4 bg-primary hover:bg-primary-hover text-white font-semibold rounded-xl transition-colors text-lg"
>
Kostenlos starten
@ -165,7 +165,7 @@ const faqs = [
<div class="text-center mb-16">
<h2 class="text-3xl md:text-4xl font-bold text-white mb-4">Alles was du brauchst</h2>
<p class="text-gray-300 max-w-2xl mx-auto">
NutriPhi macht Ernährungstracking so einfach wie ein Foto.
Food macht Ernährungstracking so einfach wie ein Foto.
</p>
</div>
@ -235,12 +235,12 @@ const faqs = [
<!-- CTA Section -->
<section class="py-20 px-4">
<div class="container mx-auto max-w-4xl text-center">
<h2 class="text-3xl md:text-4xl font-bold text-white mb-6">Starte jetzt mit NutriPhi</h2>
<h2 class="text-3xl md:text-4xl font-bold text-white mb-6">Starte jetzt mit Food</h2>
<p class="text-xl text-gray-300 mb-10 max-w-2xl mx-auto">
Kostenlos. Ohne Kreditkarte. Sofort loslegen.
</p>
<a
href="https://nutriphi.mana.how"
href="https://food.mana.how"
class="inline-block px-10 py-4 bg-primary hover:bg-primary-hover text-white font-semibold rounded-xl transition-colors text-lg"
>
Jetzt kostenlos registrieren
@ -257,7 +257,7 @@ const faqs = [
<div class="w-6 h-6 rounded bg-primary flex items-center justify-center">
<span class="text-white font-bold text-xs">N</span>
</div>
<span class="text-sm text-gray-400">NutriPhi by Mana</span>
<span class="text-sm text-gray-400">Food by Mana</span>
</div>
<div class="flex gap-6 text-sm text-gray-400">
<a href="/privacy" class="hover:text-white transition-colors">Datenschutz</a>

View file

@ -1,3 +1,3 @@
name = "nutriphi-landing"
name = "food-landing"
compatibility_date = "2024-12-01"
pages_build_output_dir = "dist"

24
apps/food/package.json Normal file
View file

@ -0,0 +1,24 @@
{
"name": "food",
"version": "0.2.0",
"private": true,
"description": "Food - AI-powered nutrition tracking with photo analysis",
"scripts": {
"dev": "pnpm run --filter=@food/* --parallel dev",
"dev:server": "pnpm --filter @food/server dev",
"dev:web": "pnpm --filter @food/web dev",
"dev:landing": "pnpm --filter @food/landing dev",
"db:push": "pnpm --filter @food/server db:push",
"db:studio": "pnpm --filter @food/server db:studio",
"db:seed": "pnpm --filter @food/server db:seed",
"test": "pnpm --filter @food/server test && pnpm --filter @food/shared test && pnpm --filter @food/web test",
"test:backend": "pnpm --filter @food/server test",
"test:web": "pnpm --filter @food/web test",
"test:shared": "pnpm --filter @food/shared test",
"test:cov": "pnpm --filter @food/server test:cov"
},
"devDependencies": {
"typescript": "^5.9.3"
},
"packageManager": "pnpm@9.15.0"
}

View file

@ -1,5 +1,5 @@
{
"name": "@nutriphi/shared",
"name": "@food/shared",
"version": "0.2.0",
"type": "commonjs",
"main": "./src/index.ts",

View file

@ -110,7 +110,7 @@ export const CREDIT_COSTS = {
} as const;
// Theme colors
export const NUTRIPHI_COLORS = {
export const FOOD_COLORS = {
primary: '#22C55E', // Green 500
primaryHover: '#16A34A', // Green 600
primaryLight: '#86EFAC', // Green 300

View file

@ -1,5 +1,5 @@
---
title: Nutriphi
title: Food
description: Deine intelligente Ernährungs-App mit KI-Unterstützung. Tracke deine Mahlzeiten, analysiere Nährstoffe und erreiche deine Gesundheitsziele mit personalisierten Empfehlungen.
category: wellness
icon: 🥗
@ -20,22 +20,22 @@ features:
status: beta
releaseDate: Geplant Q3 2025
order: 8
website: https://nutriphi.ai
website: https://food.ai
---
## Was ist Nutriphi?
## Was ist Food?
Nutriphi ist dein persönlicher Ernährungs-Coach mit KI-Power. Statt mühsam jede Mahlzeit einzutippen, machst du einfach ein Foto - unsere KI erkennt automatisch die Lebensmittel und berechnet die Nährwerte. Mit personalisierten Empfehlungen und intelligenten Analysen erreichst du deine Gesundheitsziele einfacher als je zuvor.
Food ist dein persönlicher Ernährungs-Coach mit KI-Power. Statt mühsam jede Mahlzeit einzutippen, machst du einfach ein Foto - unsere KI erkennt automatisch die Lebensmittel und berechnet die Nährwerte. Mit personalisierten Empfehlungen und intelligenten Analysen erreichst du deine Gesundheitsziele einfacher als je zuvor.
## Hauptfunktionen
### 📸 Foto-Tracking
Fotografiere deine Mahlzeit und Nutriphi erkennt automatisch alle Lebensmittel und berechnet die Nährwerte. Kein manuelles Eingeben mehr!
Fotografiere deine Mahlzeit und Food erkennt automatisch alle Lebensmittel und berechnet die Nährwerte. Kein manuelles Eingeben mehr!
### 🎯 Personalisierte Ziele
Ob Gewichtsverlust, Muskelaufbau oder gesunde Ernährung - Nutriphi erstellt dir einen maßgeschneiderten Plan basierend auf deinen Zielen.
Ob Gewichtsverlust, Muskelaufbau oder gesunde Ernährung - Food erstellt dir einen maßgeschneiderten Plan basierend auf deinen Zielen.
### 🧪 Detaillierte Analysen
@ -45,7 +45,7 @@ Verfolge nicht nur Kalorien, sondern alle wichtigen Makro- und Mikronährstoffe.
Erhalte Rezeptvorschläge, die zu deinen Zielen passen und die Lebensmittel nutzen, die du bereits hast.
## Für wen ist Nutriphi?
## Für wen ist Food?
- **Fitness-Enthusiasten**: Optimale Ernährung für Training und Regeneration
- **Abnehmwillige**: Kaloriendefizit einfach im Blick behalten
@ -55,4 +55,4 @@ Erhalte Rezeptvorschläge, die zu deinen Zielen passen und die Lebensmittel nutz
## Preise
Nutriphi nutzt das Mana-Creditsystem. Foto-Erkennung und Nährwertanalyse kosten etwa 40 Mana pro Mahlzeit. Einfache Tracking-Funktionen sind günstiger.
Food nutzt das Mana-Creditsystem. Foto-Erkennung und Nährwertanalyse kosten etwa 40 Mana pro Mahlzeit. Einfache Tracking-Funktionen sind günstiger.

View file

@ -104,7 +104,7 @@ Dieses Dokument analysiert den aktuellen Zustand der Mana-Infrastruktur auf dem
| Clock | clock-backend | 3017 | clock | - |
| Todo | todo-backend | 3018 | todo | - |
| Storage | storage-backend | 3019 | storage | MinIO (Dateien) |
| NutriPhi | nutriphi-backend | 3023 | nutriphi | Gemini API |
| Food | food-backend | 3023 | food | Gemini API |
| SkillTree | skilltree-backend | 3024 | skilltree | - |
#### Tier 4: Web-Frontends (11 Services)
@ -120,7 +120,7 @@ Dieses Dokument analysiert den aktuellen Zustand der Mana-Infrastruktur auf dem
| Calendar | calendar-web | 5186 | 3016 |
| Clock | clock-web | 5187 | 3017 |
| Todo | todo-web | 5188 | 3018 |
| NutriPhi | nutriphi-web | 5189 | 3023 |
| Food | food-web | 5189 | 3023 |
| LLM Playground | llm-playground | 5190 | - |
| SkillTree | skilltree-web | 5195 | 3024 |
@ -137,7 +137,7 @@ Dieses Dokument analysiert den aktuellen Zustand der Mana-Infrastruktur auf dem
| Project Doc Bot | mana-matrix-project-doc-bot | 3313 | Dokumentation |
| Todo Bot | mana-matrix-todo-bot | 3314 | Task Management |
| Calendar Bot | mana-matrix-calendar-bot | 3315 | Termine |
| NutriPhi Bot | mana-matrix-nutriphi-bot | 3316 | Nutrition |
| Food Bot | mana-matrix-food-bot | 3316 | Nutrition |
| Zitare Bot | mana-matrix-zitare-bot | 3317 | Quotes |
| Clock Bot | mana-matrix-clock-bot | 3318 | Time Tracking |
| TTS Bot | mana-matrix-tts-bot | 3033 | Text-to-Speech |
@ -260,7 +260,7 @@ api-gateway:
Viele Matrix-Bots teilen ähnlichen Code:
- `matrix-todo-bot` und `matrix-calendar-bot` haben ähnliche Reminder-Logik
- `matrix-nutriphi-bot` und `matrix-zitare-bot` sind Wrapper für Backends
- `matrix-food-bot` und `matrix-zitare-bot` sind Wrapper für Backends
- `matrix-mana-bot` sollte theoretisch alle anderen ersetzen
### 5. Volume-Fragmentierung
@ -274,7 +274,7 @@ volumes:
matrix_project_doc_bot_data:
matrix_calendar_bot_data:
matrix_todo_bot_data:
matrix_nutriphi_bot_data:
matrix_food_bot_data:
matrix_zitare_bot_data:
matrix_clock_bot_data:
matrix_tts_bot_data:
@ -308,7 +308,7 @@ NEU (Strukturiert):
│ ├── 3034: contacts-backend │
│ ├── 3035: storage-backend │
│ ├── 3036: presi-backend │
│ ├── 3037: nutriphi-backend │
│ ├── 3037: food-backend │
│ └── 3038: skilltree-backend │
│ │
│ 4000-4099: Matrix Stack │
@ -330,7 +330,7 @@ NEU (Strukturiert):
│ ├── 5014: contacts-web │
│ ├── 5015: storage-web │
│ ├── 5016: presi-web │
│ ├── 5017: nutriphi-web │
│ ├── 5017: food-web │
│ ├── 5018: skilltree-web │
│ └── 5090: llm-playground │
│ │
@ -401,7 +401,7 @@ AKTUELL: 10 separate Bot-Container
│ matrix-mana-bot │ matrix-ollama-bot │ ... │
│ matrix-stats-bot │ matrix-project-doc │ │
│ matrix-todo-bot │ matrix-calendar-bot │ │
│ matrix-nutriphi-bot │ matrix-zitare-bot │ │
│ matrix-food-bot │ matrix-zitare-bot │ │
│ matrix-clock-bot │ matrix-tts-bot │ │
└────────────────────────────────────────────────────────────┘

View file

@ -1,12 +1,12 @@
---
title: 'NutriPhi App, Prometheus Monitoring & Watchtower Auto-Deploy'
title: 'Food App, Prometheus Monitoring & Watchtower Auto-Deploy'
description: 'AI-powered Nutrition Tracking App hinzugefügt, Prometheus Metriken für alle Backends, umfassende Grafana Dashboards, und Watchtower für automatisches Container-Deployment.'
date: 2026-01-25
author: 'Till Schneider'
category: 'feature'
tags:
[
'nutriphi',
'food',
'prometheus',
'grafana',
'watchtower',
@ -35,7 +35,7 @@ workingHours:
Massiver Tag mit **38 Commits** und Fokus auf neue App, Monitoring und Infrastructure:
- **NutriPhi** - AI-powered Nutrition Tracking App mit Gemini
- **Food** - AI-powered Nutrition Tracking App mit Gemini
- **Prometheus Metriken** - Für alle Backends implementiert
- **Grafana Dashboards** - Umfassende Visualisierung und Alerting
- **Watchtower** - Automatisches Docker-Image-Update auf Mac Mini
@ -43,7 +43,7 @@ Massiver Tag mit **38 Commits** und Fokus auf neue App, Monitoring und Infrastru
---
## NutriPhi - AI Nutrition Tracking
## Food - AI Nutrition Tracking
Neue App für intelligentes Ernährungs-Tracking mit AI-Analyse.
@ -60,7 +60,7 @@ Neue App für intelligentes Ernährungs-Tracking mit AI-Analyse.
```
┌─────────────────────────────────────────────────────┐
NutriPhi
Food
├──────────────┬──────────────┬───────────────────────┤
│ Mobile │ Web │ Backend │
│ (Expo) │ (SvelteKit) │ (NestJS) │
@ -141,7 +141,7 @@ export class AppModule {}
- cards-backend (Port 3009)
- contacts-backend (Port 3010)
- calendar-backend (Port 3016)
- nutriphi-backend (Port 3027)
- food-backend (Port 3027)
---
@ -294,7 +294,7 @@ export async function GET() {
- calendar-web, clock-web, contacts-web
- chat-web, picture-web, zitare-web
- todo-web, cards-web, manacore-web
- presi-web, storage-web, nutriphi-web
- presi-web, storage-web, food-web
---
@ -307,7 +307,7 @@ Docker Build Jobs für neue Apps hinzugefügt.
```yaml
# .github/workflows/docker-presi.yml
# .github/workflows/docker-storage.yml
# .github/workflows/docker-nutriphi.yml
# .github/workflows/docker-food.yml
```
### Health Check Fixes
@ -347,7 +347,7 @@ scripts/staging-deploy.sh
| Bereich | Commits | Highlights |
| ----------------- | ------- | ---------------------------- |
| **NutriPhi** | 2 | Neue AI Nutrition App |
| **Food** | 2 | Neue AI Nutrition App |
| **Monitoring** | 8 | Prometheus für alle Backends |
| **Grafana** | 3 | Dashboards & Alerting |
| **Watchtower** | 6 | Auto-Deploy eingerichtet |
@ -361,6 +361,6 @@ scripts/staging-deploy.sh
## Nächste Schritte
1. **Matrix Infrastructure** für GDPR-konforme Bots
2. **NutriPhi Mobile** App fertigstellen
2. **Food Mobile** App fertigstellen
3. **Alerting** in Grafana aktivieren
4. **User Statistics** Dashboard erweitern

View file

@ -42,7 +42,7 @@ Außergewöhnlich produktiver Tag (und Nacht!) mit **74 Commits** und mehreren g
- **mana-search Microservice** - SearXNG Meta-Search + Content Extraction
- **@manacore/bot-services** - Shared Business Logic Package
- **matrix-mana-bot** - Unified Gateway Bot für alle Features
- **4 neue Matrix Bots** - Todo, NutriPhi, Zitare, Clock
- **4 neue Matrix Bots** - Todo, Food, Zitare, Clock
- **OIDC Provider** - Matrix SSO via mana-core-auth
- **VictoriaMetrics** - Monitoring Upgrade mit DuckDB Analytics
- **App Cleanup** - Demo Mode für Calendar, Todo, Contacts
@ -365,7 +365,7 @@ Task-Management via Matrix:
**Syntax:** `!todo Einkaufen !p1 @morgen #haushalt`
### matrix-nutriphi-bot
### matrix-food-bot
Ernährungs-Tracking via Matrix:
@ -514,7 +514,7 @@ apps/calendar/apps/web/src/lib/services/
│ └── sync-manager.ts # Bidirektionale Sync
```
### NutriPhi: Production Ready
### Food: Production Ready
- 99 neue Tests (Backend, Web, Shared)
- Error Handling mit deutschen Meldungen
@ -561,18 +561,18 @@ apps/calendar/apps/web/src/lib/services/
## Neue Services
| Service | Port | Typ | Beschreibung |
| ------------------- | ---- | --------- | ---------------------- |
| skilltree-backend | 3024 | NestJS | Skill-Tracking API |
| skilltree-web | 5195 | SvelteKit | Skill-Tracking UI |
| questions-backend | 3111 | NestJS | Research Assistant API |
| questions-web | 5111 | SvelteKit | Research Assistant UI |
| mana-search | 3021 | NestJS | Such-Microservice |
| matrix-mana-bot | 3310 | NestJS | Gateway Bot |
| matrix-todo-bot | 3315 | NestJS | Todo Bot |
| matrix-nutriphi-bot | 3316 | NestJS | Nutrition Bot |
| matrix-zitare-bot | 3317 | NestJS | Quotes Bot |
| matrix-clock-bot | 3318 | NestJS | Timer Bot |
| Service | Port | Typ | Beschreibung |
| ----------------- | ---- | --------- | ---------------------- |
| skilltree-backend | 3024 | NestJS | Skill-Tracking API |
| skilltree-web | 5195 | SvelteKit | Skill-Tracking UI |
| questions-backend | 3111 | NestJS | Research Assistant API |
| questions-web | 5111 | SvelteKit | Research Assistant UI |
| mana-search | 3021 | NestJS | Such-Microservice |
| matrix-mana-bot | 3310 | NestJS | Gateway Bot |
| matrix-todo-bot | 3315 | NestJS | Todo Bot |
| matrix-food-bot | 3316 | NestJS | Nutrition Bot |
| matrix-zitare-bot | 3317 | NestJS | Quotes Bot |
| matrix-clock-bot | 3318 | NestJS | Timer Bot |
---
@ -585,12 +585,12 @@ apps/calendar/apps/web/src/lib/services/
| Matrix Client | 1 | Phase 2 Features |
| mana-search | 3 | SearXNG, Extraction, Cache |
| Bot Services | 2 | Shared Package + Gateway |
| Matrix Bots | 8 | Todo, NutriPhi, Zitare, Clock |
| Matrix Bots | 8 | Todo, Food, Zitare, Clock |
| OIDC | 6 | Matrix SSO Provider |
| App Cleanup | 8 | Demo Mode, Feature Removal |
| Monitoring | 2 | VictoriaMetrics, DuckDB |
| NutriPhi | 2 | Tests, Production Ready |
| Telegram Bots | 1 | NutriPhi, Todo, Zitare |
| Food | 2 | Tests, Production Ready |
| Telegram Bots | 1 | Food, Todo, Zitare |
| Bugfixes | 15+ | Auth, Matrix, Docker |
| Documentation | 5 | Monitoring, Services, DevLogs |

View file

@ -492,7 +492,7 @@ import { HealthModule } from '@manacore/shared-nestjs-health';
```
**Migrierte Backends (12):**
calendar, chat, clock, contacts, nutriphi, picture, planta, presi, skilltree, storage, todo, zitare
calendar, chat, clock, contacts, food, picture, planta, presi, skilltree, storage, todo, zitare
### @manacore/shared-nestjs-setup
@ -514,7 +514,7 @@ await app.listen(process.env.PORT || 3002);
```
**Migrierte Backends (8):**
chat, calendar, contacts, zitare, clock, planta, presi, nutriphi
chat, calendar, contacts, zitare, clock, planta, presi, food
### @manacore/shared-tsconfig
@ -641,15 +641,15 @@ Neues Dokument mit API-Übersicht aller Microservices:
## Bugfixes
| Fix | Beschreibung |
| -------------------------- | ----------------------------------------------------------- |
| **Docker Healthchecks** | Node-basierte Healthchecks für mana-core-auth, nutriphi-web |
| **Matrix Sidebar** | Gap und Scrolling-Layout gefixt |
| **Matrix Message Input** | Layout-Verbesserungen |
| **Matrix Shared Packages** | Fehlende Dependencies im Dockerfile |
| **Matrix Vite Config** | Inline Config für Docker-Kompatibilität |
| **TTS Bot** | MP3 Format, keine doppelten Nachrichten |
| **Matrix RoomItem** | lastMessageTime Validierung |
| Fix | Beschreibung |
| -------------------------- | ------------------------------------------------------- |
| **Docker Healthchecks** | Node-basierte Healthchecks für mana-core-auth, food-web |
| **Matrix Sidebar** | Gap und Scrolling-Layout gefixt |
| **Matrix Message Input** | Layout-Verbesserungen |
| **Matrix Shared Packages** | Fehlende Dependencies im Dockerfile |
| **Matrix Vite Config** | Inline Config für Docker-Kompatibilität |
| **TTS Bot** | MP3 Format, keine doppelten Nachrichten |
| **Matrix RoomItem** | lastMessageTime Validierung |
---

View file

@ -210,7 +210,7 @@ Strategische Entscheidung: Fokus auf Matrix als einzige Chat-Plattform.
services/
├── telegram-ollama-bot/ # ENTFERNT
├── telegram-project-doc-bot/ # ENTFERNT
├── telegram-nutriphi-bot/ # ENTFERNT
├── telegram-food-bot/ # ENTFERNT
├── telegram-todo-bot/ # ENTFERNT
└── telegram-zitare-bot/ # ENTFERNT
```
@ -379,5 +379,5 @@ Zahlreiche Fixes für das Monitoring-System.
1. **Matrix E2EE** aktivieren
2. **Voice Preferences UI** im Manalink Client
3. **mana-media** mit NutriPhi integrieren
3. **mana-media** mit Food integrieren
4. **Matrix Bots CI/CD** Pipeline

View file

@ -104,7 +104,7 @@ Alle Authentifizierungs-Seiten sind jetzt mehrsprachig.
- Chat Web
- Clock Web
- Contacts Web
- NutriPhi Web
- Food Web
- Picture Web
- Planta Web
- Questions Web

View file

@ -1,6 +1,6 @@
---
title: 'Cross-Domain SSO, mana-media Integration & Matrix Bots Page'
description: 'Cross-Subdomain SSO für alle .mana.how Apps, mana-media NutriPhi Integration, neue Bots-Übersichtsseite in Manalink, und mana-llm Production Deployment'
description: 'Cross-Subdomain SSO für alle .mana.how Apps, mana-media Food Integration, neue Bots-Übersichtsseite in Manalink, und mana-llm Production Deployment'
date: 2026-02-02
author: 'Till Schneider'
category: 'feature'
@ -13,7 +13,7 @@ tags:
'bots',
'mana-llm',
'production',
'nutriphi',
'food',
'calendar',
'ux',
]
@ -36,7 +36,7 @@ workingHours:
Produktiver Tag mit **40 Commits** und Fokus auf nahtlose Authentifizierung über alle Apps:
- **Cross-Domain SSO** - Single Sign-On für alle .mana.how Subdomains
- **mana-media Integration** - NutriPhi mit zentraler Medienverarbeitung
- **mana-media Integration** - Food mit zentraler Medienverarbeitung
- **Matrix Bots Page** - Übersicht aller 19 Bots in Manalink
- **mana-llm Production** - LLM Gateway auf Mac Mini deployed
- **i18n für Matrix Bots** - Mehrsprachige Bot-Antworten
@ -91,7 +91,7 @@ Single Sign-On über alle ManaCore Web Apps.
| Chat | chat.mana.how | ✅ |
| Clock | clock.mana.how | ✅ |
| Contacts | contacts.mana.how | ✅ |
| NutriPhi | nutriphi.mana.how | ✅ |
| Food | food.mana.how | ✅ |
| Picture | picture.mana.how | ✅ |
| Planta | planta.mana.how | ✅ |
| Questions | questions.mana.how | ✅ |
@ -120,13 +120,13 @@ const { user } = await response.json();
## mana-media Integration
Zentrale Medienverarbeitung mit NutriPhi als erster Integration.
Zentrale Medienverarbeitung mit Food als erster Integration.
### NutriPhi Integration
### Food Integration
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
NutriPhi │────>│ mana-media │────>│ MinIO │
Food │────>│ mana-media │────>│ MinIO │
│ (Upload) │ │ (Process) │ │ (Storage) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │
@ -202,7 +202,7 @@ Neue Übersichtsseite mit allen 19 Matrix Bots in Manalink.
| matrix-calendar-bot | Productivity | Termine & Erinnerungen |
| matrix-clock-bot | Utility | Timer & Weltzeit |
| matrix-contacts-bot | Productivity | Kontaktverwaltung |
| matrix-nutriphi-bot | Health | Ernährungs-Tracking |
| matrix-food-bot | Health | Ernährungs-Tracking |
| matrix-picture-bot | AI | Bildgenerierung |
| matrix-zitare-bot | Inspiration | Tägliche Zitate |
| matrix-skilltree-bot | Gamification | Skill-Tracking |
@ -382,14 +382,14 @@ CREATE INDEX idx_users_matrix_user_id ON users(matrix_user_id);
## Bugfixes
| Fix | Beschreibung |
| ----------------------- | ----------------------------- |
| **mana-llm SSE** | Double data prefix |
| **contacts-web** | Runtime URLs statt Build-time |
| **shared-ui** | calculateFadeOpacity Export |
| **nutriphi Dockerfile** | Fehlende shared packages |
| **SessionService** | Async Methods |
| **JWT Issuer** | Aligned mit Better Auth |
| Fix | Beschreibung |
| ------------------- | ----------------------------- |
| **mana-llm SSE** | Double data prefix |
| **contacts-web** | Runtime URLs statt Build-time |
| **shared-ui** | calculateFadeOpacity Export |
| **food Dockerfile** | Fehlende shared packages |
| **SessionService** | Async Methods |
| **JWT Issuer** | Aligned mit Better Auth |
---
@ -398,7 +398,7 @@ CREATE INDEX idx_users_matrix_user_id ON users(matrix_user_id);
| Bereich | Commits | Highlights |
| -------------------- | ------- | -------------------- |
| **Cross-Domain SSO** | 5 | 14 Apps mit SSO |
| **mana-media** | 4 | NutriPhi Integration |
| **mana-media** | 4 | Food Integration |
| **Matrix Bots Page** | 2 | 19 Bots Übersicht |
| **mana-llm** | 2 | Production + SSE Fix |
| **i18n Bots** | 2 | DE/EN Support |

View file

@ -247,7 +247,7 @@ Temporär deaktivierte Services (fehlende Deployments):
```yaml
# Auskommentiert bis Deployment fertig
# inventory-backend:
# nutriphi-backend:
# food-backend:
# wisekeep-backend:
```
@ -423,4 +423,4 @@ userId: text('user_id').notNull();
1. **GDPR Export UI** - Download-Button im mana.how Dashboard
2. **Matrix E2EE** - Ende-zu-Ende Verschlüsselung aktivieren
3. **Alertmanager** - Discord Webhook Integration
4. **Service Deployments** - Inventory, NutriPhi, WiseKeep
4. **Service Deployments** - Inventory, Food, WiseKeep

View file

@ -16,7 +16,7 @@ tags:
'tts',
'german-voice',
'emoji-picker',
'nutriphi',
'food',
'stats-bot',
]
featured: true
@ -320,7 +320,7 @@ POST / api / users / me / preferences / emojis;
---
## NutriPhi Bot Improvements
## Food Bot Improvements
### Auto-Analyze Text
@ -449,7 +449,7 @@ Tracking IDs für alle Web-Apps aktualisiert.
| **Clock Bot** | 4 | Timer Progress + Topic |
| **TTS** | 4 | German Voice + WAV |
| **Emoji Picker** | 3 | Recently Used + Sync |
| **NutriPhi** | 5 | Text-Analyse + Fixes |
| **Food** | 5 | Text-Analyse + Fixes |
| **Stats Bot** | 3 | Infra Monitoring |
| **Bot Fixes** | 8 | Loop Prevention + Auth |
| **Session** | 2 | Auto-Refresh |

View file

@ -186,7 +186,7 @@ export class TranscriptionService {
Alle Matrix Bots mit STT-Funktionalität:
- matrix-stt-bot
- matrix-nutriphi-bot
- matrix-food-bot
- matrix-chat-bot (Voice Messages)
### Environment Variable

View file

@ -106,7 +106,7 @@ Progressive Web App Dependencies wurden zu allen SvelteKit Web-Apps hinzugefügt
| LightWrite | ✅ Aktiviert |
| Cards | ✅ Aktiviert |
| Photos | ✅ Aktiviert |
| NutriPhi | ✅ Aktiviert |
| Food | ✅ Aktiviert |
| Mukke | ✅ Aktiviert |
| Reader | ✅ Aktiviert |
| Inventory | ✅ Aktiviert |

View file

@ -1,10 +1,10 @@
---
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.'
description: 'spiral-db Pixel-Visualisierung, Planta Bot für Pflanzenidentifikation, Food 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']
tags: ['spiral-db', 'planta', 'food', 'todo', 'mana-bot', 'wallpaper', 'documentation']
featured: false
commits: 26
readTime: 10
@ -25,7 +25,7 @@ Produktiver Tag mit **26 Commits** neue Packages, Bot-Features und Dokumenta
- **spiral-db** - Pixel-basierte Spiral-Datenbank-Visualisierung
- **Planta Bot** - KI-Pflanzenidentifikation per Bild-Upload
- **NutriPhi Bot** - Smartes Meal Feedback
- **Food Bot** - Smartes Meal Feedback
- **Mana Bot** - Tägliche Morgenzusammenfassung
- **Mana Values** - Manifest-Dokumentation
- **Wallpaper Generator** - Neues Package
@ -138,7 +138,7 @@ docker compose -f docker-compose.macmini.yml up -d planta-bot
---
## NutriPhi Bot Verbesserungen
## Food Bot Verbesserungen
Smartes Meal Feedback mit positiven Aspekten und Verbesserungsvorschlägen.
@ -283,7 +283,7 @@ Sidebar-Mode aus der PillNavigation entfernt nur noch Bottom-Navigation.
| ------------------ | ------- | --------------------------------- |
| **spiral-db** | 5 | Package + Todo Integration |
| **Planta Bot** | 4 | KI-Pflanzenidentifikation |
| **NutriPhi Bot** | 3 | Smartes Meal Feedback |
| **Food Bot** | 3 | Smartes Meal Feedback |
| **Mana Bot** | 3 | Morning Summary |
| **QR Code** | 2 | My-Data Export |
| **Wallpaper** | 2 | Generator Package |

View file

@ -102,7 +102,7 @@ const APPS_WITH_SSO = [
'cards',
'matrix',
'mukke',
'nutriphi',
'food',
'photos',
'picture',
'planta',
@ -264,7 +264,7 @@ GlitchTip (selbst-gehostete Sentry-Alternative) wurde für **alle 15 Backends**
| Contacts | 3034 | #6 |
| ManaCore Auth | 3001 | #2 |
| Mukke | 3010 | #9 |
| NutriPhi | 3037 | #11 |
| Food | 3037 | #11 |
| Photos | 3039 | #12 |
| Planta | 3022 | #13 |
| Presi | 3036 | #14 |
@ -300,7 +300,7 @@ Alle 20 aktiven Apps wurden bewertet nach 8 Kategorien (Backend, Frontend, Datab
| **Picture** | 81 | Production | Replicate Integration |
| **Mukke** | 80 | Beta | 113 Tests, Audio Editor |
| **Matrix** | 68 | Production | E2E Encryption |
| **NutriPhi** | 63 | Beta | Gemini AI Integration |
| **Food** | 63 | Beta | Gemini AI Integration |
| **Photos** | 62 | Beta | mana-media Integration |
| **Zitare** | 62 | Beta | Deployed auf mana.how |
| **Context** | 60 | Beta | Neuer Backend (Port 3020) |

View file

@ -201,9 +201,9 @@ export const handleError: HandleClientError = ({ error }) => {
### Alle 19 Web-Apps angebunden
| Apps |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Calendar, Chat, Clock, Contacts, Context, Manacore, Cards, Matrix, Mukke, NutriPhi, Photos, Picture, Planta, Presi, Questions, Skilltree, Storage, Todo, Zitare |
| Apps |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Calendar, Chat, Clock, Contacts, Context, Manacore, Cards, Matrix, Mukke, Food, Photos, Picture, Planta, Presi, Questions, Skilltree, Storage, Todo, Zitare |
### API

View file

@ -125,7 +125,7 @@ Neues monorepo-weites Package, das die LLM-Integration für alle Backends verein
- `@chat/backend` — Chat AI-Completions
- `@zitare/backend` — Zitat-Analyse (vorher eigener Ollama-Service)
- `@planta/backend` — Pflanzen-Vision-Analyse
- `@nutriphi/backend` — Ernährungs-Analyse (Gemini)
- `@food/backend` — Ernährungs-Analyse (Gemini)
- `mana-core-auth` — AI-Service für Auth-Features
### Google Gemini Fallback

View file

@ -53,7 +53,7 @@ Neuer `Analytics Maturity`-Metrik in ManaScore und Custom Event Tracking in 8+ A
| Storage | Upload, Download, Share, Preview |
| Photos | Upload, Edit, Album-Create |
| Context, SkillTree, Planta, Questions | App-spezifische Events |
| NutriPhi, Cards | Meal-Log, Card-Create |
| Food, Cards | Meal-Log, Card-Create |
### Commits
@ -61,7 +61,7 @@ Neuer `Analytics Maturity`-Metrik in ManaScore und Custom Event Tracking in 8+ A
- `bade0a17` — Storage Event Tracking
- `3075e515` — Photos Event Tracking
- `12b3c4f0` — Context, SkillTree, Planta, Questions
- `1fe8f890`NutriPhi, Cards
- `1fe8f890`Food, Cards
---

View file

@ -47,7 +47,7 @@ Jeder Matrix-Bot lief als eigenständiger NestJS-Service mit eigenem Docker-Cont
| matrix-project-doc-bot | Projekt-Dokumentation | 4013 |
| matrix-todo-bot | Aufgabenverwaltung | 4014 |
| matrix-calendar-bot | Kalender | 4015 |
| matrix-nutriphi-bot | Ernährungstracking | 4016 |
| matrix-food-bot | Ernährungstracking | 4016 |
| matrix-zitare-bot | Zitate & Inspiration | 4017 |
| matrix-clock-bot | Timer, Alarme, Weltuhren | 4018 |
| matrix-tts-bot | Text-to-Speech | 4019 |
@ -224,7 +224,7 @@ Neues Plugin hinzufügen = 3 Schritte:
### Skeleton (Grundgerüst mit !help, !status)
stats, chat, cards, nutriphi, picture, presi, questions, skilltree, storage, projectdoc, onboarding
stats, chat, cards, food, picture, presi, questions, skilltree, storage, projectdoc, onboarding
---

View file

@ -151,7 +151,7 @@ Für jede App ein minimaler Hono-Server der **nur** die server-seitigen Endpoint
| Chat | 137 | LLM Completions + SSE Streaming |
| Picture | 144 | Replicate Image Gen + S3 Upload |
| Calendar | 119 | RRULE Expansion + ICS Import |
| NutriPhi | 154 | Gemini Meal Analysis |
| Food | 154 | Gemini Meal Analysis |
| Planta | 104 | Gemini Plant Analysis + S3 Upload |
| Traces | 108 | AI Guide Generation |
| ... | ... | ... |

View file

@ -66,14 +66,14 @@ Der Legacy-Code ist eingecheckt als Referenz. Die aktiven Services werden in Sch
Die bestehende Web-App wurde vollständig auf den Monorepo-Stack portiert:
| Phase | Was passiert ist |
|-------|-----------------|
| 1 | Package-Struktur: `@memoro/web`, adapter-node, Tailwind v4 + `@manacore/shared-tailwind` |
| 2 | Auth: `createManaAuthStore()` aus `@manacore/shared-auth-stores`, Google/Apple OAuth entfernt |
| 3 | Local-First: `memoroStore` mit 7 Collections (memos, tags, spaces, invites, …) |
| 4 | Guest-Seed: Demo-Daten die sofort geladen werden ohne Login |
| 5 | Service Layer: `memoService` + `tagService` von Supabase direct auf local-store Collections |
| 6 | Workspace-Integration: `dev:memoro:*` Scripts, CLAUDE.md Eintrag |
| Phase | Was passiert ist |
| ----- | --------------------------------------------------------------------------------------------- |
| 1 | Package-Struktur: `@memoro/web`, adapter-node, Tailwind v4 + `@manacore/shared-tailwind` |
| 2 | Auth: `createManaAuthStore()` aus `@manacore/shared-auth-stores`, Google/Apple OAuth entfernt |
| 3 | Local-First: `memoroStore` mit 7 Collections (memos, tags, spaces, invites, …) |
| 4 | Guest-Seed: Demo-Daten die sofort geladen werden ohne Login |
| 5 | Service Layer: `memoService` + `tagService` von Supabase direct auf local-store Collections |
| 6 | Workspace-Integration: `dev:memoro:*` Scripts, CLAUDE.md Eintrag |
**Wichtig:** Google/Apple OAuth komplett entfernt — Memoro nutzt ausschließlich mana-auth JWT, wie alle anderen Apps im Ökosystem. Keine externen OAuth-Provider.
@ -113,15 +113,15 @@ Tier 4: Azure Batch Transcription
### Vergleich: Vorher vs. Nachher
| Aspekt | NestJS (alt) | Hono/Bun (neu) |
|--------|-------------|----------------|
| Services | 2 (Backend + Audio-Backend) | 2 (Server + Audio-Server) |
| LOC (gesamt) | ~12.000 | ~1.800 |
| Dependencies | 20+ (@nestjs/*, class-validator, …) | 4 (hono, zod, fluent-ffmpeg, …) |
| Cold Start | ~2-3s | ~50ms |
| RAM | ~400MB | ~80MB |
| Auth | Supabase JWT | mana-auth JWT |
| OAuth | Google + Apple | Keiner (self-sovereign) |
| Aspekt | NestJS (alt) | Hono/Bun (neu) |
| ------------ | ------------------------------------ | ------------------------------- |
| Services | 2 (Backend + Audio-Backend) | 2 (Server + Audio-Server) |
| LOC (gesamt) | ~12.000 | ~1.800 |
| Dependencies | 20+ (@nestjs/\*, class-validator, …) | 4 (hono, zod, fluent-ffmpeg, …) |
| Cold Start | ~2-3s | ~50ms |
| RAM | ~400MB | ~80MB |
| Auth | Supabase JWT | mana-auth JWT |
| OAuth | Google + Apple | Keiner (self-sovereign) |
---
@ -169,12 +169,12 @@ Nach dem Notepad-Redesign von gestern gab es heute mehrere Iteration-Loops auf D
Die Task-Cards wurden weiter bereinigt:
| Vorher | Nachher |
|--------|---------|
| Border + Hintergrundfarbe | Kein Border, kein Hintergrund |
| Checkbox vertikal zentriert | Checkbox am Anfang der ersten Zeile (flex-start) |
| Titel abgeschnitten (truncate) | Mehrzeilig (word-break) |
| Hover: translateY + Hintergrund | Kein Hover-Effekt |
| Vorher | Nachher |
| ------------------------------- | ------------------------------------------------ |
| Border + Hintergrundfarbe | Kein Border, kein Hintergrund |
| Checkbox vertikal zentriert | Checkbox am Anfang der ersten Zeile (flex-start) |
| Titel abgeschnitten (truncate) | Mehrzeilig (word-break) |
| Hover: translateY + Hintergrund | Kein Hover-Effekt |
**Resultat:** Die Task-Liste liest sich wie echtes Papier — nur der Text, keine UI-Noise.
@ -273,11 +273,11 @@ border: 1px solid var(--border);
Drei Komponenten die über viele Apps hinweg dupliziert waren:
| Komponente | Apps (vorher) | Lösung |
|-----------|--------------|--------|
| `LanguageSelector` | contacts, zitare: Custom-Dropdown mit eigenem State | → `PillDropdown` aus shared-ui (wie die anderen 8 Apps) |
| `ConfirmDialog` | context (4 Stellen), times (3 Stellen): lokale Kopien | → `ConfirmationModal` aus `@manacore/shared-ui` |
| `AppSlider` | todo, calendar, chat, contacts, presi: statisches `MANA_APPS` | → `getActiveManaApps()` (filtert inaktive Apps) |
| Komponente | Apps (vorher) | Lösung |
| ------------------ | ------------------------------------------------------------- | ------------------------------------------------------- |
| `LanguageSelector` | contacts, zitare: Custom-Dropdown mit eigenem State | → `PillDropdown` aus shared-ui (wie die anderen 8 Apps) |
| `ConfirmDialog` | context (4 Stellen), times (3 Stellen): lokale Kopien | → `ConfirmationModal` aus `@manacore/shared-ui` |
| `AppSlider` | todo, calendar, chat, contacts, presi: statisches `MANA_APPS` | → `getActiveManaApps()` (filtert inaktive Apps) |
**228 Zeilen Netto**, 2 lokale Komponenten gelöscht.
@ -289,12 +289,12 @@ Drei Komponenten die über viele Apps hinweg dupliziert waren:
Die letzten 4 Apps die noch GitHub Container Registry (GHCR) als Image-Quelle nutzten wurden auf das einheitliche lokale Build-Pattern umgestellt:
| App | Vorher | Nachher |
|-----|--------|---------|
| chat-web | `ghcr.io/...` | lokaler Build |
| App | Vorher | Nachher |
| --------- | ------------- | ------------- |
| chat-web | `ghcr.io/...` | lokaler Build |
| clock-web | `ghcr.io/...` | lokaler Build |
| presi-web | `ghcr.io/...` | lokaler Build |
| nutriphi-web | `ghcr.io/...` | lokaler Build |
| food-web | `ghcr.io/...` | lokaler Build |
**Einzige Ausnahme:** Umami (externes Projekt) bleibt bei GHCR.
@ -306,13 +306,13 @@ Das Arcade-Backend (AI Browser Games) war noch auf NestJS. Migration auf Hono/Bu
### Weitere Fixes
| Fix | Beschreibung |
|-----|-------------|
| Port-Konflikt | calc-web: Port 5026 → 5031 (kollidierte mit zitare-web) |
| Cloudflared | Config mit tatsächlichen Container-Ports synchronisiert |
| Fix | Beschreibung |
| -------------- | ------------------------------------------------------------ |
| Port-Konflikt | calc-web: Port 5026 → 5031 (kollidierte mit zitare-web) |
| Cloudflared | Config mit tatsächlichen Container-Ports synchronisiert |
| Landings Nginx | `mkdir snippets` vor Copy, status.mana.how vhost hinzugefügt |
| Prerender 404 | favicon.png 404s bei skilltree + nutriphi unterdrückt |
| inventar-web | Browser-Error-Tracking Import repariert |
| Prerender 404 | favicon.png 404s bei skilltree + food unterdrückt |
| inventar-web | Browser-Error-Tracking Import repariert |
---
@ -330,16 +330,16 @@ Drei neue Planungs-/Guidelines-Dokumente:
## Zusammenfassung
| Bereich | Commits | Highlights |
|---------|---------|-----------|
| Memoro Integration | ~25 | Web, Server, Audio-Server ins Monorepo |
| Status-Page | ~12 | status.mana.how live, Blackbox Exporter, ManaScore-Badges |
| Todo Polish | ~20 | Paper-Cards, Complete-Animation, Detail-Modal, Kanban-Subtasks |
| Auth | ~10 | EMAIL_NOT_VERIFIED robust, Resend-Panel, callbackURL Fix |
| Infra | ~15 | GHCR→lokal, Arcade, Port-Fix, Cloudflared |
| UI Unification | ~8 | Elevation-System, LanguageSelector, ConfirmDialog, AppSlider |
| Docs | ~5 | Auth UX Patterns, Bundle Format, Memoro Plan |
| Fixes | ~3 | Prerender, inventar-web, manacore-web Login-Redirect |
| Bereich | Commits | Highlights |
| ------------------ | ------- | -------------------------------------------------------------- |
| Memoro Integration | ~25 | Web, Server, Audio-Server ins Monorepo |
| Status-Page | ~12 | status.mana.how live, Blackbox Exporter, ManaScore-Badges |
| Todo Polish | ~20 | Paper-Cards, Complete-Animation, Detail-Modal, Kanban-Subtasks |
| Auth | ~10 | EMAIL_NOT_VERIFIED robust, Resend-Panel, callbackURL Fix |
| Infra | ~15 | GHCR→lokal, Arcade, Port-Fix, Cloudflared |
| UI Unification | ~8 | Elevation-System, LanguageSelector, ConfirmDialog, AppSlider |
| Docs | ~5 | Auth UX Patterns, Bundle Format, Memoro Plan |
| Fixes | ~3 | Prerender, inventar-web, manacore-web Login-Redirect |
---

View file

@ -68,7 +68,7 @@ Der Plan war seit Wochen klar — heute wurde er ausgeführt, in einer langen Se
```
Welle 1 (12 Module): skilltree, inventar, times, planta,
citycorners, photos, presi, uload,
context, questions, nutriphi, calc
context, questions, food, calc
Welle 2 (5 Module): storage, cards, playground, guides,
+ restliche Helper

View file

@ -24,7 +24,7 @@ workingHours:
## Highlights
- **mana-media** wird zentrale Bild-Pipeline: Picture, Contacts, Planta, Storage, NutriPhi laden Bilder darüber hoch
- **mana-media** wird zentrale Bild-Pipeline: Picture, Contacts, Planta, Storage, Food laden Bilder darüber hoch
- **CAS (SHA-256 Dedup)**, **Thumbnails**, **EXIF-Extraktion** automatisch
- Alle hochgeladenen Bilder erscheinen in der **Photos-Galerie**
- Fix: `effect_update_depth_exceeded` in 6 Dashboard-Modulen (Resultat des Unified-App-Switches)
@ -50,7 +50,7 @@ Picture → S3 direkt Picture ─┐
Contacts → S3 direkt Contacts ─┤
Planta → S3 direkt ───→ Planta ─┼─→ mana-media → S3 (CAS) + DB
Storage → S3 direkt Storage ─┤ ↓
NutriPhi → S3 direkt NutriPhi ─┘ Photos Gallery
Food → S3 direkt Food ─┘ Photos Gallery
```
### Implementierung
@ -72,7 +72,7 @@ mana-media liefert zurück:
### Nebeneffekt: Photos-Galerie wird automatisch befüllt
Die Photos-App liest aus `mana_media.media WHERE owner_id = ?`. Damit erscheinen jetzt alle Avatare aus Contacts, alle Pflanzen-Fotos aus Planta, alle Mahlzeit-Bilder aus NutriPhi etc. in der Galerie — ohne dass die Module davon wissen.
Die Photos-App liest aus `mana_media.media WHERE owner_id = ?`. Damit erscheinen jetzt alle Avatare aus Contacts, alle Pflanzen-Fotos aus Planta, alle Mahlzeit-Bilder aus Food etc. in der Galerie — ohne dass die Module davon wissen.
---

View file

@ -1,10 +1,10 @@
---
title: 'NutriPhi: Production Readiness Audit'
title: 'Food: Production Readiness Audit'
description: 'Ernährungstracking mit Gemini AI Food-Analyse, 8 Backend-Modulen und 1.457 Test-Zeilen - aber nicht deployed'
date: 2026-03-19
app: 'nutriphi'
app: 'food'
author: 'Till Schneider'
tags: ['audit', 'nutriphi', 'production-readiness', 'ai']
tags: ['audit', 'food', 'production-readiness', 'ai']
score: 63
scores:
backend: 78
@ -45,7 +45,7 @@ stats:
## Zusammenfassung
NutriPhi ist ein **AI-gestütztes Ernährungstracking** mit Google Gemini für Food-Analyse. Solides Backend mit guter Doku und Tests, aber nicht deployed und schwache Web-UI.
Food ist ein **AI-gestütztes Ernährungstracking** mit Google Gemini für Food-Analyse. Solides Backend mit guter Doku und Tests, aber nicht deployed und schwache Web-UI.
## Backend (78/100)

View file

@ -58,7 +58,7 @@ Die Architektur-Migration hat alle Apps gleichzeitig verbessert:
| **Zitare** | 88 | 93 | +5 | Local-First, war schon solide |
| **Clock** | 85 | 91 | +6 | Local-First + keine Backend-Dependency |
| **Storage** | 72 | 82 | +10 | Local-First + S3 Server |
| **NutriPhi** | 70 | 82 | +12 | Local-First + Gemini Server |
| **Food** | 70 | 82 | +12 | Local-First + Gemini Server |
| **Planta** | 65 | 78 | +13 | Local-First + Vision Server |
| **Mukke** | 68 | 80 | +12 | Local-First + S3 Server |
| **Questions** | 72 | 83 | +11 | Local-First + Search Server |

View file

@ -76,7 +76,7 @@ export const ui = {
'KI-gestützte Karteikarten-App für effektives Lernen und Wissensmanagement',
'app.pictus.description': 'Kreativer KI-Bildgenerator für beeindruckende Bilder und Kunstwerke',
'app.orakel.description': 'Intelligente KI-Chat-Assistentin für alle Lebenslagen',
'app.nutriphi.description': 'Intelligente Ernährungs-App mit KI-gestütztem Foto-Tracking',
'app.food.description': 'Intelligente Ernährungs-App mit KI-gestütztem Foto-Tracking',
'app.traces.description': 'Entdecke deine Stadt neu mit KI-gestütztem Bewegungs-Tracking',
// Footer
@ -156,7 +156,7 @@ export const ui = {
'AI-powered flashcard app for effective learning and knowledge management',
'app.pictus.description': 'Creative AI image generator for stunning pictures and artwork',
'app.orakel.description': 'Intelligent AI chat assistant for all aspects of life',
'app.nutriphi.description': 'Smart nutrition app with AI-powered photo tracking',
'app.food.description': 'Smart nutrition app with AI-powered photo tracking',
'app.traces.description': 'Rediscover your city with AI-powered movement tracking',
// Footer
@ -237,7 +237,7 @@ export const ui = {
'app.pictus.description':
"Generatore di immagini AI creativo per immagini e opere d'arte straordinarie",
'app.orakel.description': 'Assistente chat AI intelligente per tutti gli aspetti della vita',
'app.nutriphi.description':
'app.food.description':
'App di nutrizione intelligente con tracciamento fotografico basato su AI',
'app.traces.description':
'Riscopri la tua città con il tracciamento dei movimenti basato su AI',
@ -322,7 +322,7 @@ export const ui = {
'app.pictus.description':
"Générateur d'images IA créatif pour des images et œuvres d'art époustouflantes",
'app.orakel.description': 'Assistant de chat IA intelligent pour tous les aspects de la vie',
'app.nutriphi.description':
'app.food.description':
"Application de nutrition intelligente avec suivi photographique basé sur l'IA",
'app.traces.description':
"Redécouvrez votre ville avec le suivi des déplacements basé sur l'IA",
@ -405,8 +405,7 @@ export const ui = {
'app.pictus.description':
'Generador de imágenes IA creativo para imágenes y obras de arte impresionantes',
'app.orakel.description': 'Asistente de chat IA inteligente para todos los aspectos de la vida',
'app.nutriphi.description':
'App de nutrición inteligente con seguimiento fotográfico basado en IA',
'app.food.description': 'App de nutrición inteligente con seguimiento fotográfico basado en IA',
'app.traces.description': 'Redescubre tu ciudad con seguimiento de movimiento basado en IA',
// Footer

View file

@ -56,7 +56,7 @@ const sections: Section[] = [
label: 'Alltag & Gesundheit',
apps: [
{ name: 'ManaClock', icon: 'ph:clock-bold', tagline: 'Uhren & Timer', url: 'https://clock.mana.how' },
{ name: 'NutriPhi', icon: 'ph:bowl-food-bold', tagline: 'Ernährung', url: 'https://nutriphi.mana.how' },
{ name: 'Food', icon: 'ph:bowl-food-bold', tagline: 'Ernährung', url: 'https://food.mana.how' },
{ name: 'Planta', icon: 'ph:plant-bold', tagline: 'Pflanzenpflege', url: 'https://planta.mana.how' },
],
},

View file

@ -65,12 +65,12 @@ const apps = [
href: '/apps/orakel',
},
{
name: 'Nutriphi',
descriptionKey: 'app.nutriphi.description',
name: 'Food',
descriptionKey: 'app.food.description',
logo: '🥗',
categoryKey: 'app.category.wellness',
color: 'from-green-500 to-emerald-500',
href: '/apps/nutriphi',
href: '/apps/food',
},
{
name: 'Traces',

View file

@ -65,12 +65,12 @@ const apps = [
href: '/apps/orakel',
},
{
name: 'Nutriphi',
descriptionKey: 'app.nutriphi.description',
name: 'Food',
descriptionKey: 'app.food.description',
logo: '🥗',
categoryKey: 'app.category.wellness',
color: 'from-green-500 to-emerald-500',
href: '/apps/nutriphi',
href: '/apps/food',
},
{
name: 'Traces',

View file

@ -65,12 +65,12 @@ const apps = [
href: '/apps/orakel',
},
{
name: 'Nutriphi',
descriptionKey: 'app.nutriphi.description',
name: 'Food',
descriptionKey: 'app.food.description',
logo: '🥗',
categoryKey: 'app.category.wellness',
color: 'from-green-500 to-emerald-500',
href: '/apps/nutriphi',
href: '/apps/food',
},
{
name: 'Traces',

View file

@ -88,12 +88,12 @@ const apps = [
href: '/apps/orakel',
},
{
name: 'Nutriphi',
descriptionKey: 'app.nutriphi.description',
name: 'Food',
descriptionKey: 'app.food.description',
logo: '🥗',
categoryKey: 'app.category.wellness',
color: 'from-green-500 to-emerald-500',
href: '/apps/nutriphi',
href: '/apps/food',
},
{
name: 'Traces',

View file

@ -65,12 +65,12 @@ const apps = [
href: '/apps/orakel',
},
{
name: 'Nutriphi',
descriptionKey: 'app.nutriphi.description',
name: 'Food',
descriptionKey: 'app.food.description',
logo: '🥗',
categoryKey: 'app.category.wellness',
color: 'from-green-500 to-emerald-500',
href: '/apps/nutriphi',
href: '/apps/food',
},
{
name: 'Traces',

View file

@ -20,7 +20,7 @@ import { setSecurityHeaders } from '@mana/shared-utils/security-headers';
* - Glitchtip DSN client-side error reporting
*
* Per-app HTTP backends (todo-api, calendar-api, contacts-api, chat-api,
* storage-api, cards-api, mukke-api, nutriphi-api, picture-api, presi-api,
* storage-api, cards-api, mukke-api, food-api, picture-api, presi-api,
* zitare-api, clock-api, context-api) were removed in the pre-launch
* ghost-API cleanup every product module now talks to mana-sync directly.
*/
@ -60,7 +60,7 @@ const APP_SUBDOMAINS = new Set([
'cards',
'storage',
'presi',
'nutriphi',
'food',
'photos',
'music',
'picture',

View file

@ -604,12 +604,12 @@ registerApp({
});
registerApp({
id: 'nutriphi',
name: 'Nutriphi',
id: 'food',
name: 'Food',
color: '#22C55E',
icon: ForkKnife,
views: {
list: { load: () => import('$lib/modules/nutriphi/ListView.svelte') },
list: { load: () => import('$lib/modules/food/ListView.svelte') },
},
contextMenuActions: [
{
@ -618,7 +618,7 @@ registerApp({
icon: Plus,
action: () =>
window.dispatchEvent(
new CustomEvent('mana:quick-action', { detail: { app: 'nutriphi', action: 'new' } })
new CustomEvent('mana:quick-action', { detail: { app: 'food', action: 'new' } })
),
},
],

View file

@ -55,7 +55,7 @@ export const APP_CATEGORY_MAP: Record<string, AppCategory> = {
drink: 'life',
meditate: 'life',
journal: 'life',
nutriphi: 'life',
food: 'life',
recipes: 'life',
plants: 'life',
finance: 'life',

View file

@ -85,7 +85,7 @@ export const GOAL_TEMPLATES: GoalTemplate[] = [
id: 'tpl-meals-daily',
title: 'Alle Mahlzeiten tracken',
description: 'Mindestens 3 Mahlzeiten pro Tag erfassen',
moduleId: 'nutriphi',
moduleId: 'food',
metric: { source: 'event_count', eventType: 'MealLogged' },
target: { value: 3, period: 'day', comparison: 'gte' },
},
@ -93,7 +93,7 @@ export const GOAL_TEMPLATES: GoalTemplate[] = [
id: 'tpl-calories-daily',
title: 'Kalorien-Ziel einhalten',
description: 'Maximal 2000 kcal pro Tag',
moduleId: 'nutriphi',
moduleId: 'food',
metric: { source: 'event_sum', eventType: 'MealLogged', sumField: 'calories' },
target: { value: 2000, period: 'day', comparison: 'lte' },
},

View file

@ -206,9 +206,9 @@ export async function extractAllPatterns(): Promise<void> {
// Calendar patterns
extractDayOfWeekPattern('CalendarEventCreated', 'Termine erstellt', 'calendar'),
// Nutriphi patterns
extractTimePreference('MealLogged', 'Mahlzeiten geloggt', 'nutriphi'),
extractFrequencyPattern('MealLogged', 'Mahlzeiten', 'nutriphi'),
// Food patterns
extractTimePreference('MealLogged', 'Mahlzeiten geloggt', 'food'),
extractFrequencyPattern('MealLogged', 'Mahlzeiten', 'food'),
// Places patterns
extractDayOfWeekPattern('PlaceVisited', 'Orte besucht', 'places'),

View file

@ -122,7 +122,7 @@ export const mealReminderRule: PulseRule = {
body: 'Noch keine Mahlzeit heute erfasst.',
priority: 'low',
actionLabel: 'Mahlzeit loggen',
actionRoute: '/nutriphi',
actionRoute: '/food',
};
}
@ -135,7 +135,7 @@ export const mealReminderRule: PulseRule = {
body: `Erst ${meals} Mahlzeit(en) heute (${calories.actual} kcal).`,
priority: 'low',
actionLabel: 'Mahlzeit loggen',
actionRoute: '/nutriphi',
actionRoute: '/food',
};
}

View file

@ -154,7 +154,7 @@ export const APP_POSITIONS: Record<string, { x: number; y: number; lakeId: strin
zitare: { x: 640, y: 600, lakeId: 'db-center' },
music: { x: 850, y: 610, lakeId: 'db-center' },
clock: { x: 880, y: 680, lakeId: 'db-center' },
nutriphi: { x: 650, y: 720, lakeId: 'db-center' },
food: { x: 650, y: 720, lakeId: 'db-center' },
// Around Waldsee Ost (db-right)
photos: { x: 1110, y: 575, lakeId: 'db-right' },

View file

@ -170,8 +170,8 @@ const APP_DEFINITIONS: AppDefinition[] = [
},
},
{
id: 'nutriphi',
displayName: 'NutriPhi',
id: 'food',
displayName: 'Food',
score: 63,
status: 'beta',
categories: {

View file

@ -36,7 +36,7 @@
presi: 'https://presi.mana.how',
music: 'https://music.mana.how',
clock: 'https://clock.mana.how',
nutriphi: 'https://nutriphi.mana.how',
food: 'https://food.mana.how',
photos: 'https://photos.mana.how',
zitare: 'https://zitare.mana.how',
mana: 'https://mana.how',

View file

@ -29,7 +29,7 @@
redis: 'Schneller Cache-Speicher. Klein, kristallklar, sofort verfugbar.',
minio: 'Objekt-Speicher fur Dateien, Bilder und Medien aller Apps.',
'db-left': 'PostgreSQL-Datenbanken fur Calendar, Todo, Contacts, Storage.',
'db-center': 'PostgreSQL-Datenbanken fur Zitare, Music, Clock, NutriPhi.',
'db-center': 'PostgreSQL-Datenbanken fur Zitare, Music, Clock, Food.',
'db-right': 'PostgreSQL-Datenbanken fur Photos, SkillTree, Context, Plants.',
};

View file

@ -404,7 +404,7 @@ Unlock-Flow (Login auf neuem Gerät):
| | **`answers`** | **`content`** | **7.2** |
| **uload** | **`links`** | **`title`, `description`** (`originalUrl` plaintext — Public Redirect) | **7.2** |
| **context** | **`documents`** | **`title`, `content`** | **7.2** |
| **nutriphi** | **`meals`** | **`description`, `portionSize`** (Nutrition-Numbers plaintext für Aggregation) | **7.2** |
| **food** | **`meals`** | **`description`, `portionSize`** (Nutrition-Numbers plaintext für Aggregation) | **7.2** |
| **storage** | **`files`** | **`name`, `originalName`** (mimeType/size/path plaintext) | **8** |
| **picture** | **`images`** | **`prompt`, `negativePrompt`** (model/style/format plaintext) | **8** |
| **music** | **`songs`** | **`title`** (artist/album/genre plaintext für Browsing-Aggregation) | **8** |

View file

@ -129,7 +129,7 @@ export const ENCRYPTION_REGISTRY: Record<string, EncryptionConfig> = {
cycles: { enabled: true, fields: ['notes'] },
cycleDayLogs: { enabled: true, fields: ['notes', 'mood'] },
// ─── NutriPhi ────────────────────────────────────────────
// ─── Food ────────────────────────────────────────────
// LocalMeal user-typed / AI-generated content → encrypted:
// - description, portionSize: free-text, same sensitivity tier
// - foods: AI-identified food items (array of {name, quantity,
@ -414,7 +414,7 @@ export const ENCRYPTION_REGISTRY: Record<string, EncryptionConfig> = {
// ─── Recipes ─────────────────────────────────────────────
// User-typed content (title, description, ingredients list, steps)
// encrypted. `ingredients` is Ingredient[] and `steps` is string[] —
// aes.ts JSON-stringifies before wrap, same as nutriphi's `foods`.
// aes.ts JSON-stringifies before wrap, same as food's `foods`.
// Plaintext (intentional): difficulty, tags, servings, times,
// isFavorite, photo refs — needed for indexing and filtering.
recipes: { enabled: true, fields: ['title', 'description', 'ingredients', 'steps'] },

View file

@ -176,10 +176,10 @@ db.version(1).stores({
answers: 'id, questionId, isAccepted',
questionTags: 'id, questionId, tagId, [questionId+tagId]',
// ─── NutriPhi (appId: 'nutriphi') ───
// ─── Food (appId: 'food') ───
meals: 'id, date, mealType, [date+mealType]',
goals: 'id',
nutriFavorites: 'id, mealType, usageCount',
foodFavorites: 'id, mealType, usageCount',
mealTags: 'id, mealId, tagId, [mealId+tagId]',
// ─── Plants (appId: 'plants') ───

View file

@ -6,7 +6,7 @@
* possible event so the EventStore and Projection Engine can work
* with full type safety.
*
* Pilot modules: Todo, Calendar, Drink, Nutriphi, Places.
* Pilot modules: Todo, Calendar, Drink, Food, Places.
*/
import type { DomainEvent } from './types';
@ -141,7 +141,7 @@ export interface DrinkEntryUndonePayload {
export type DrinkEventType = 'DrinkLogged' | 'DrinkEntryDeleted' | 'DrinkEntryUndone';
// ── Nutriphi ────────────────────────────────────────
// ── Food ────────────────────────────────────────
export interface MealLoggedPayload {
mealId: string;
@ -174,7 +174,7 @@ export interface NutritionGoalSetPayload {
dailyFat?: number;
}
export type NutriphiEventType =
export type FoodEventType =
| 'MealLogged'
| 'MealFromPhotoLogged'
| 'MealDeleted'
@ -638,7 +638,7 @@ export type ManaEventType =
| TodoEventType
| CalendarEventType
| DrinkEventType
| NutriphiEventType
| FoodEventType
| PlacesEventType
| HabitsEventType
| JournalEventType
@ -693,7 +693,7 @@ export type ManaEvent =
| DomainEvent<'DrinkLogged', DrinkLoggedPayload>
| DomainEvent<'DrinkEntryDeleted', DrinkEntryDeletedPayload>
| DomainEvent<'DrinkEntryUndone', DrinkEntryUndonePayload>
// Nutriphi
// Food
| DomainEvent<'MealLogged', MealLoggedPayload>
| DomainEvent<'MealFromPhotoLogged', MealFromPhotoLoggedPayload>
| DomainEvent<'MealDeleted', MealDeletedPayload>

View file

@ -155,7 +155,7 @@ describe('module-registry — pre-refactor snapshot', () => {
],
context: ['contextSpaces', 'documents', 'documentTags'],
questions: ['qCollections', 'questions', 'answers', 'questionTags'],
nutriphi: ['meals', 'goals', 'nutriFavorites', 'mealTags'],
food: ['meals', 'goals', 'foodFavorites', 'mealTags'],
plants: ['plants', 'plantPhotos', 'wateringSchedules', 'wateringLogs', 'plantTags'],
uload: ['links', 'uloadTags', 'uloadFolders', 'linkTags'],
calc: ['calculations', 'savedFormulas'],
@ -203,7 +203,7 @@ describe('module-registry — pre-refactor snapshot', () => {
timeWorldClocks: 'worldClocks',
contextSpaces: 'spaces',
qCollections: 'collections',
nutriFavorites: 'favorites',
foodFavorites: 'favorites',
memoroSpaces: 'spaces',
uloadTags: 'tags',
uloadFolders: 'folders',

View file

@ -68,7 +68,7 @@ import { citycornersModuleConfig } from '$lib/modules/citycorners/module.config'
import { timesModuleConfig } from '$lib/modules/times/module.config';
import { contextModuleConfig } from '$lib/modules/context/module.config';
import { questionsModuleConfig } from '$lib/modules/questions/module.config';
import { nutriphiModuleConfig } from '$lib/modules/nutriphi/module.config';
import { foodModuleConfig } from '$lib/modules/food/module.config';
import { plantsModuleConfig } from '$lib/modules/plants/module.config';
import { uloadModuleConfig } from '$lib/modules/uload/module.config';
import { calcModuleConfig } from '$lib/modules/calc/module.config';
@ -118,7 +118,7 @@ export const MODULE_CONFIGS: readonly ModuleConfig[] = [
timesModuleConfig,
contextModuleConfig,
questionsModuleConfig,
nutriphiModuleConfig,
foodModuleConfig,
plantsModuleConfig,
uloadModuleConfig,
calcModuleConfig,

View file

@ -62,14 +62,14 @@ const METRICS: MetricDef[] = [
extract: (days) => countByType(days, 'DrinkLogged', (p) => p.drinkType === 'coffee'),
},
{
id: 'nutriphi:calories',
module: 'nutriphi',
id: 'food:calories',
module: 'food',
label: 'Kalorien',
extract: (days) => sumByTypeField(days, 'MealLogged', 'calories'),
},
{
id: 'nutriphi:meals',
module: 'nutriphi',
id: 'food:meals',
module: 'food',
label: 'Mahlzeiten',
extract: (days) => countByType(days, 'MealLogged'),
},

View file

@ -14,12 +14,12 @@ import { useLiveQueryWithDefault } from '@mana/local-store/svelte';
import { db } from '../database';
import { decryptRecords } from '../crypto';
import { DEFAULT_DAILY_GOAL_ML } from '$lib/modules/drink/types';
import { DEFAULT_DAILY_VALUES } from '$lib/modules/nutriphi/constants';
import { DEFAULT_DAILY_VALUES } from '$lib/modules/food/constants';
import { trackingStore } from '$lib/modules/places/stores/tracking.svelte';
import type { LocalTask } from '$lib/modules/todo/types';
import type { LocalEvent } from '$lib/modules/calendar/types';
import type { LocalDrinkEntry } from '$lib/modules/drink/types';
import type { LocalMeal, LocalGoal as NutriGoal } from '$lib/modules/nutriphi/types';
import type { LocalMeal, LocalGoal as NutriGoal } from '$lib/modules/food/types';
import type { LocalPlace } from '$lib/modules/places/types';
import type { LocalTimeBlock } from '../time-blocks/types';
import type { DaySnapshot, TaskSummary, EventSummary } from './types';
@ -54,7 +54,7 @@ async function buildSnapshot(): Promise<DaySnapshot> {
const todayEnd = `${today}T23:59:59`;
// ── Parallel queries — all 5 modules at once ────
const [allTasks, blocks, allDrinks, allMeals, nutriGoals, allPlaces] = await Promise.all([
const [allTasks, blocks, allDrinks, allMeals, foodGoals, allPlaces] = await Promise.all([
db.table<LocalTask>('tasks').toArray(),
db
.table<LocalTimeBlock>('timeBlocks')
@ -136,7 +136,7 @@ async function buildSnapshot(): Promise<DaySnapshot> {
totalProtein += n.protein ?? 0;
}
}
const activeGoal = nutriGoals.find((g) => !g.deletedAt);
const activeGoal = foodGoals.find((g) => !g.deletedAt);
const calorieGoal = activeGoal?.dailyCalories ?? DEFAULT_DAILY_VALUES.calories;
const proteinGoal = activeGoal?.dailyProtein;

View file

@ -153,7 +153,7 @@ describe('Streak Tracker', () => {
meta: {
id: '2',
timestamp: new Date().toISOString(),
appId: 'nutriphi',
appId: 'food',
collection: 'meals',
recordId: '2',
userId: 'u1',

View file

@ -71,7 +71,7 @@ const STREAK_DEFS: StreakDef[] = [
},
{
id: 'streak-meals-logged',
moduleId: 'nutriphi',
moduleId: 'food',
label: 'Mahlzeiten getrackt',
triggerEvents: ['MealLogged', 'MealFromPhotoLogged'],
},

View file

@ -7,7 +7,7 @@ import { registerTools } from './registry';
import { todoTools } from '$lib/modules/todo/tools';
import { calendarTools } from '$lib/modules/calendar/tools';
import { drinkTools } from '$lib/modules/drink/tools';
import { nutriphiTools } from '$lib/modules/nutriphi/tools';
import { foodTools } from '$lib/modules/food/tools';
import { placesTools } from '$lib/modules/places/tools';
import { habitsTools } from '$lib/modules/habits/tools';
import { journalTools } from '$lib/modules/journal/tools';
@ -42,7 +42,7 @@ export function initTools(): void {
registerTools(todoTools);
registerTools(calendarTools);
registerTools(drinkTools);
registerTools(nutriphiTools);
registerTools(foodTools);
registerTools(placesTools);
registerTools(habitsTools);
registerTools(journalTools);

View file

@ -40,7 +40,7 @@ function registerLocale(lang: SupportedLocale) {
times,
inventory,
photos,
nutriphi,
food,
plants,
skilltree,
citycorners,
@ -76,7 +76,7 @@ function registerLocale(lang: SupportedLocale) {
import(`./locales/times/${lang}.json`),
import(`./locales/inventory/${lang}.json`),
import(`./locales/photos/${lang}.json`),
import(`./locales/nutriphi/${lang}.json`),
import(`./locales/food/${lang}.json`),
import(`./locales/plants/${lang}.json`),
import(`./locales/skilltree/${lang}.json`),
import(`./locales/citycorners/${lang}.json`),
@ -114,7 +114,7 @@ function registerLocale(lang: SupportedLocale) {
times: times.default,
inventory: inventory.default,
photos: photos.default,
nutriphi: nutriphi.default,
food: food.default,
plants: plants.default,
skilltree: skilltree.default,
citycorners: citycorners.default,

View file

@ -15,7 +15,7 @@
"music": "Musik",
"photos": "Fotos",
"storage": "Speicher",
"nutriphi": "NutriPhi",
"food": "Essen",
"plants": "Pflanzen",
"presi": "Presi",
"inventory": "Inventar",

View file

@ -15,7 +15,7 @@
"music": "Music",
"photos": "Photos",
"storage": "Storage",
"nutriphi": "NutriPhi",
"food": "Food",
"plants": "Plants",
"presi": "Presi",
"inventory": "Inventory",

View file

@ -15,7 +15,7 @@
"music": "Música",
"photos": "Fotos",
"storage": "Almacén",
"nutriphi": "NutriPhi",
"food": "Food",
"plants": "Plantas",
"presi": "Presi",
"inventory": "Inventario",

View file

@ -15,7 +15,7 @@
"music": "Musique",
"photos": "Photos",
"storage": "Stockage",
"nutriphi": "NutriPhi",
"food": "Food",
"plants": "Plantes",
"presi": "Presi",
"inventory": "Inventaire",

View file

@ -15,7 +15,7 @@
"music": "Musica",
"photos": "Foto",
"storage": "Archivio",
"nutriphi": "NutriPhi",
"food": "Food",
"plants": "Piante",
"presi": "Presi",
"inventory": "Inventario",

View file

@ -1,6 +1,6 @@
{
"app": {
"name": "NutriPhi",
"name": "Food",
"loading": "Laden...",
"tagline": "Ernährung verstehen"
},

View file

@ -1,6 +1,6 @@
{
"app": {
"name": "NutriPhi",
"name": "Food",
"loading": "Loading...",
"tagline": "Understand nutrition"
},

View file

@ -1,6 +1,6 @@
{
"app": {
"name": "NutriPhi",
"name": "Food",
"loading": "Cargando...",
"tagline": "Entiende la nutrición"
},

View file

@ -1,6 +1,6 @@
{
"app": {
"name": "NutriPhi",
"name": "Food",
"loading": "Chargement...",
"tagline": "Comprendre la nutrition"
},

View file

@ -1,6 +1,6 @@
{
"app": {
"name": "NutriPhi",
"name": "Food",
"loading": "Caricamento...",
"tagline": "Comprendi la nutrizione"
},

View file

@ -15,7 +15,7 @@
useAllBodyMeasurements,
useAllBodyChecks,
useAllBodyPhases,
useNutriphiMealsSince,
useFoodMealsSince,
dateNDaysAgo,
getActiveWorkout,
getActivePhase,
@ -38,7 +38,7 @@
const measurementsQuery = useAllBodyMeasurements();
const checksQuery = useAllBodyChecks();
const phasesQuery = useAllBodyPhases();
const mealsQuery = useNutriphiMealsSince(dateNDaysAgo(56));
const mealsQuery = useFoodMealsSince(dateNDaysAgo(56));
let exercises = $derived(exercisesQuery.value);
let routines = $derived(routinesQuery.value);

View file

@ -1,7 +1,7 @@
<!--
CalorieWeightChart — Body × Nutriphi correlation view.
CalorieWeightChart — Body × Food correlation view.
Overlays daily calorie intake (from nutriphi `meals`) against
Overlays daily calorie intake (from food `meals`) against
bodyweight (from `bodyMeasurements`) for the last N days. The
whole point of having both modules in the same app is being
able to ask "did the cut work?" without exporting CSVs.
@ -22,7 +22,7 @@
-->
<script lang="ts">
import type { BodyMeasurement, BodyPhase } from '../types';
import type { MealWithNutrition } from '$lib/modules/nutriphi/types';
import type { MealWithNutrition } from '$lib/modules/food/types';
interface Props {
measurements: BodyMeasurement[];

View file

@ -17,7 +17,7 @@ import type {
BodyCheck,
BodyPhase,
} from './types';
import type { MealWithNutrition } from '$lib/modules/nutriphi/types';
import type { MealWithNutrition } from '$lib/modules/food/types';
export const bodyExercisesCtx = createModuleContext<BodyExercise[]>('bodyExercises');
export const bodyRoutinesCtx = createModuleContext<BodyRoutine[]>('bodyRoutines');
@ -26,4 +26,4 @@ export const bodySetsCtx = createModuleContext<BodySet[]>('bodySets');
export const bodyMeasurementsCtx = createModuleContext<BodyMeasurement[]>('bodyMeasurements');
export const bodyChecksCtx = createModuleContext<BodyCheck[]>('bodyChecks');
export const bodyPhasesCtx = createModuleContext<BodyPhase[]>('bodyPhases');
export const bodyNutriphiMealsCtx = createModuleContext<MealWithNutrition[]>('bodyNutriphiMeals');
export const bodyFoodMealsCtx = createModuleContext<MealWithNutrition[]>('bodyFoodMeals');

View file

@ -7,7 +7,7 @@
import { useLiveQueryWithDefault } from '@mana/local-store/svelte';
import { decryptRecords } from '$lib/data/crypto';
import { db } from '$lib/data/database';
import type { LocalMeal, MealWithNutrition } from '$lib/modules/nutriphi/types';
import type { LocalMeal, MealWithNutrition } from '$lib/modules/food/types';
import type {
LocalBodyExercise,
LocalBodyRoutine,
@ -206,11 +206,11 @@ export function useAllBodyPhases() {
}
/**
* Cross-module read into the nutriphi `meals` table for the calorie /
* Cross-module read into the food `meals` table for the calorie /
* weight correlation chart. Lives here (instead of consumers calling
* nutriphi/queries directly) because the body module owns the Body ×
* Nutriphi integration boundary, and putting the cross-table read in
* one place keeps the import graph from getting circular if nutriphi
* food/queries directly) because the body module owns the Body ×
* Food integration boundary, and putting the cross-table read in
* one place keeps the import graph from getting circular if food
* ever wants to reach back the other way.
*
* Returns a thinned MealWithNutrition shape only the fields the
@ -218,7 +218,7 @@ export function useAllBodyPhases() {
* `since` is a YYYY-MM-DD lower bound; the chart pulls 8 weeks but
* the helper is permissive so a future "year view" can extend it.
*/
export function useNutriphiMealsSince(since: string) {
export function useFoodMealsSince(since: string) {
return useLiveQueryWithDefault(async () => {
const locals = await db.table<LocalMeal>('meals').where('date').aboveOrEqual(since).toArray();
const visible = locals.filter((m) => !m.deletedAt);

Some files were not shown because too many files have changed in this diff Show more