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 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 ## Running Servers

View file

@ -1,11 +1,11 @@
# NutriPhi MVP-Plan # Food MVP-Plan
> **Status:** Planung abgeschlossen > **Status:** Planung abgeschlossen
> **Letzte Aktualisierung:** 2026-01-24 > **Letzte Aktualisierung:** 2026-01-24
## Vision ## 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 ### Projektstruktur
``` ```
apps/nutriphi/ apps/food/
├── apps/ ├── apps/
│ ├── web/ # SvelteKit (mobile-optimiert) │ ├── web/ # SvelteKit (mobile-optimiert)
│ └── backend/ # NestJS API │ └── backend/ # NestJS API
@ -268,7 +268,7 @@ Output-Format: JSON mit strukturierten Nährwertdaten
``` ```
┌─────────────────────────────┐ ┌─────────────────────────────┐
NutriPhi [+] [Profile] │ Food [+] [Profile] │
├─────────────────────────────┤ ├─────────────────────────────┤
│ │ │ │
│ Heute: 1.450 / 2.000 kcal │ │ Heute: 1.450 / 2.000 kcal │
@ -378,7 +378,7 @@ Output-Format: JSON mit strukturierten Nährwertdaten
### Wiederverwendbare Shared Components ### Wiederverwendbare Shared Components
| Komponente | Verwendung in NutriPhi | | Komponente | Verwendung in Food |
|------------|------------------------| |------------|------------------------|
| `HeroSection` | "Fotografiere dein Essen, verstehe was du isst" | | `HeroSection` | "Fotografiere dein Essen, verstehe was du isst" |
| `FeatureSection` | KI-Analyse, Nährwerte, Tracking, Empfehlungen | | `FeatureSection` | KI-Analyse, Nährwerte, Tracking, Empfehlungen |
@ -392,14 +392,14 @@ Output-Format: JSON mit strukturierten Nährwertdaten
### Projektstruktur ### Projektstruktur
``` ```
apps/nutriphi/apps/landing/ apps/food/apps/landing/
├── src/ ├── src/
│ ├── pages/ │ ├── pages/
│ │ └── index.astro │ │ └── index.astro
│ ├── layouts/ │ ├── layouts/
│ │ └── Layout.astro │ │ └── Layout.astro
│ ├── styles/ │ ├── styles/
│ │ └── global.css # NutriPhi Theme (Grün) │ │ └── global.css # Food Theme (Grün)
│ └── components/ # Custom falls nötig │ └── components/ # Custom falls nötig
├── astro.config.mjs ├── astro.config.mjs
├── package.json ├── package.json
@ -409,7 +409,7 @@ apps/nutriphi/apps/landing/
### Farbschema (CSS Custom Properties) ### Farbschema (CSS Custom Properties)
```css ```css
/* NutriPhi Theme - Gesundheit/Natur */ /* Food Theme - Gesundheit/Natur */
--color-primary: #22C55E; /* Green 500 */ --color-primary: #22C55E; /* Green 500 */
--color-primary-hover: #16A34A; /* Green 600 */ --color-primary-hover: #16A34A; /* Green 600 */
--color-secondary: #F97316; /* Orange 500 */ --color-secondary: #F97316; /* Orange 500 */

View file

@ -1,8 +1,8 @@
# NutriPhi - App-Planung # Food - App-Planung
## Vision ## 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 ## Planungsdokumente

View file

@ -22,7 +22,7 @@
| 7 | **Presi** | decks, slides | Ja (Store + Pages umgeschrieben) | | 7 | **Presi** | decks, slides | Ja (Store + Pages umgeschrieben) |
| 8 | **Picture** | images, boards, boardItems, tags, imageTags | Ja (Gallery + Boards 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) | | 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) | | 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) | | 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) | | 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) # 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 8d880f1f feat(apps): migrate Chat, Questions, Mukke, Context, Photos
a31ccc6c feat(apps): add local-store to SkilltTree and CityCorners a31ccc6c feat(apps): add local-store to SkilltTree and CityCorners
7754cf6e refactor(skilltree): replace custom idb → @manacore/local-store 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 | | **Picture** | images, boards, boardItems, tags, imageTags | Replicate API, Upload, Explore |
| **Presi** | decks, slides | Share-Links | | **Presi** | decks, slides | Share-Links |
| **Inventar** | collections, items, locations, categories | Nur Sync | | **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) | | **Planta** | plants, plantPhotos, wateringSchedules, wateringLogs | Foto-Upload, AI-Analyse (Gemini) |
| **Storage** | files, folders, tags, fileTags | Datei-Upload/Download, Shares, Versionen | | **Storage** | files, folders, tags, fileTags | Datei-Upload/Download, Shares, Versionen |
| **Chat** | conversations, messages, templates | LLM Streaming | | **Chat** | conversations, messages, templates | LLM Streaming |

View file

@ -46,7 +46,7 @@ manacore-monorepo/
│ │ │ └── landing/ │ │ │ └── landing/
│ │ └── packages/ │ │ └── packages/
│ │ │ │
│ ├── nutriphi/ │ ├── food/
│ │ ├── apps/ │ │ ├── apps/
│ │ │ ├── backend/ │ │ │ ├── backend/
│ │ │ ├── mobile/ │ │ │ ├── mobile/
@ -134,7 +134,7 @@ mkdir -p services
| `cards/` | `apps/cards/` | | `cards/` | `apps/cards/` |
| `memoro/` | `apps/memoro/` | | `memoro/` | `apps/memoro/` |
| `picture/` | `apps/picture/` | | `picture/` | `apps/picture/` |
| `nutriphi/` | `apps/nutriphi/` | | `food/` | `apps/food/` |
| `uload/` | `apps/uload/` | | `uload/` | `apps/uload/` |
| `news/` | `apps/news/` | | `news/` | `apps/news/` |
| `manacore/` | `apps/manacore/` | | `manacore/` | `apps/manacore/` |
@ -146,7 +146,7 @@ git mv maerchenzauber apps/maerchenzauber
git mv cards apps/cards git mv cards apps/cards
git mv memoro apps/memoro git mv memoro apps/memoro
git mv picture apps/picture git mv picture apps/picture
git mv nutriphi apps/nutriphi git mv food apps/food
git mv uload apps/uload git mv uload apps/uload
git mv news apps/news git mv news apps/news
git mv manacore apps/manacore 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/chat/backend/` | `apps/chat/apps/backend/` |
| `apps/cards/backend/` | `apps/cards/apps/backend/` | | `apps/cards/backend/` | `apps/cards/apps/backend/` |
| `apps/nutriphi/backend/` | `apps/nutriphi/apps/backend/` | | `apps/food/backend/` | `apps/food/apps/backend/` |
```bash ```bash
# Chat: move backend into apps/ # Chat: move backend into apps/
@ -171,9 +171,9 @@ git mv apps/chat/backend apps/chat/apps/backend
mkdir -p apps/cards/apps mkdir -p apps/cards/apps
git mv apps/cards/backend apps/cards/apps/backend git mv apps/cards/backend apps/cards/apps/backend
# Nutriphi: move backend into apps/ # Food: move backend into apps/
mkdir -p apps/nutriphi/apps mkdir -p apps/food/apps
git mv apps/nutriphi/backend apps/nutriphi/apps/backend git mv apps/food/backend apps/food/apps/backend
``` ```
### 2.3 Move mana-core-auth to services/ ### 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/*...", "picture:dev": "turbo run dev --filter=@picture/*...",
"uload:dev": "turbo run dev --filter=@uload/*...", "uload:dev": "turbo run dev --filter=@uload/*...",
"chat:dev": "turbo run dev --filter=@chat/*...", "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/*...", "news:dev": "turbo run dev --filter=@news/*...",
"dev:maerchenzauber:web": "pnpm --filter @maerchenzauber/web dev", "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:backend": "pnpm --filter @chat/backend start:dev",
"dev:chat:app": "turbo run dev --filter=@chat/web --filter=@chat/backend", "dev:chat:app": "turbo run dev --filter=@chat/web --filter=@chat/backend",
"dev:nutriphi:mobile": "pnpm --filter @nutriphi/mobile dev", "dev:food:mobile": "pnpm --filter @food/mobile dev",
"dev:nutriphi:web": "pnpm --filter @nutriphi/web dev", "dev:food:web": "pnpm --filter @food/web dev",
"dev:nutriphi:landing": "pnpm --filter @nutriphi/landing dev", "dev:food:landing": "pnpm --filter @food/landing dev",
"dev:nutriphi:backend": "pnpm --filter @nutriphi/backend start:dev", "dev:food:backend": "pnpm --filter @food/backend start:dev",
"dev:nutriphi:app": "turbo run dev --filter=@nutriphi/web --filter=@nutriphi/backend", "dev:food:app": "turbo run dev --filter=@food/web --filter=@food/backend",
"dev:news:mobile": "pnpm --filter @news/mobile dev", "dev:news:mobile": "pnpm --filter @news/mobile dev",
"dev:news:web": "pnpm --filter @news/web 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** | | 12 | **uload** | queries (umfangreich), types | 3 routes (dashboard, links, analytics) | **Done** |
| 13 | **context** | queries, types | 5 routes (dashboard, spaces, documents) | **Done** | | 13 | **context** | queries, types | 5 routes (dashboard, spaces, documents) | **Done** |
| 14 | **questions** | queries, types | 4 routes (list, collections, new, detail) | **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** | | 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** | | 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** | | 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 | | **times** | Zeiterfassung, Dashboard-Widget |
| **context** | Dokument-Workspace | | **context** | Dokument-Workspace |
| **questions** | Research-Assistant | | **questions** | Research-Assistant |
| **nutriphi** | Ernährung | | **food** | Ernährung |
| **planta** | Pflanzenpflege | | **planta** | Pflanzenpflege |
| **uload** | URL-Shortener, Links | | **uload** | URL-Shortener, Links |
| **calc** | Rechner | | **calc** | Rechner |
@ -259,7 +259,7 @@ src/lib/modules/
├── times/ ├── times/
├── context/ ├── context/
├── questions/ ├── questions/
├── nutriphi/ ├── food/
├── planta/ ├── planta/
├── uload/ ├── uload/
├── calc/ ├── calc/
@ -367,7 +367,7 @@ src/routes/
│ ├── times/+page.svelte │ ├── times/+page.svelte
│ ├── context/+page.svelte │ ├── context/+page.svelte
│ ├── questions/+page.svelte │ ├── questions/+page.svelte
│ ├── nutriphi/+page.svelte │ ├── food/+page.svelte
│ ├── planta/+page.svelte │ ├── planta/+page.svelte
│ ├── uload/+page.svelte │ ├── uload/+page.svelte
│ ├── calc/+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 { TIMES_COLLECTIONS } from '$lib/modules/times/collections';
import { CONTEXT_COLLECTIONS } from '$lib/modules/context/collections'; import { CONTEXT_COLLECTIONS } from '$lib/modules/context/collections';
import { QUESTIONS_COLLECTIONS } from '$lib/modules/questions/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 { PLANTA_COLLECTIONS } from '$lib/modules/planta/collections';
import { ULOAD_COLLECTIONS } from '$lib/modules/uload/collections'; import { ULOAD_COLLECTIONS } from '$lib/modules/uload/collections';
import { CALC_COLLECTIONS } from '$lib/modules/calc/collections'; import { CALC_COLLECTIONS } from '$lib/modules/calc/collections';
@ -521,7 +521,7 @@ db.version(1).stores({
...TIMES_COLLECTIONS, ...TIMES_COLLECTIONS,
...CONTEXT_COLLECTIONS, ...CONTEXT_COLLECTIONS,
...QUESTIONS_COLLECTIONS, ...QUESTIONS_COLLECTIONS,
...NUTRIPHI_COLLECTIONS, ...FOOD_COLLECTIONS,
...PLANTA_COLLECTIONS, ...PLANTA_COLLECTIONS,
...ULOAD_COLLECTIONS, ...ULOAD_COLLECTIONS,
...CALC_COLLECTIONS, ...CALC_COLLECTIONS,
@ -578,7 +578,7 @@ export const SYNC_APP_MAP: Record<string, string[]> = {
times: ['clients', 'tProjects', 'timeEntries', 'tTags', 'tTemplates', 'tSettings'], times: ['clients', 'tProjects', 'timeEntries', 'tTags', 'tTemplates', 'tSettings'],
context: ['spaces', 'documents'], context: ['spaces', 'documents'],
questions: ['qCollections', 'questions', 'answers'], questions: ['qCollections', 'questions', 'answers'],
nutriphi: ['meals', 'goals', 'nFavorites'], food: ['meals', 'goals', 'nFavorites'],
planta: ['plants', 'plantPhotos', 'wateringSchedules', 'wateringLogs'], planta: ['plants', 'plantPhotos', 'wateringSchedules', 'wateringLogs'],
uload: ['links', 'uTags', 'uFolders', 'linkTags'], uload: ['links', 'uTags', 'uFolders', 'linkTags'],
calc: ['calculations', 'savedFormulas'], 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 | | 12 | **uload** | 12 | 10 | Mittel | Hat Backend-Server |
| 13 | **context** | 10 | 15 | Mittel | Mittlere Komplexität | | 13 | **context** | 10 | 15 | Mittel | Mittlere Komplexität |
| 14 | **questions** | 10 | 14 | Mittel | Hat Backend-API | | 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 | | 16 | **storage** | 12 | 15 | Mittel | Hat Backend + MinIO |
| 17 | **cards** | 12 | 18 | Mittel | Hat Backend-Server | | 17 | **cards** | 12 | 18 | Mittel | Hat Backend-Server |
| 18 | **contacts** | 23 | 39 | Komplex | Backend + Import/Export | | 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_CLOCK_LANDING=0332b471-a022-46af-a726-0f45932bfd58
UMAMI_WEBSITE_ID_PICTURE_LANDING=d3ac98e6-0d1a-47a3-a218-2a81fff596bd UMAMI_WEBSITE_ID_PICTURE_LANDING=d3ac98e6-0d1a-47a3-a218-2a81fff596bd
UMAMI_WEBSITE_ID_TODO_LANDING=538eb4b6-2241-45a3-994d-cdb9bdb0c250 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_PRESI_LANDING=dd485016-0077-47b9-9f59-ab2c6c1730ee
UMAMI_WEBSITE_ID_MUKKE_LANDING=b2c9ab34-3c53-4463-9dde-1ecf098886a5 UMAMI_WEBSITE_ID_MUKKE_LANDING=b2c9ab34-3c53-4463-9dde-1ecf098886a5
@ -219,18 +219,18 @@ PICTURE_APP_ID=picture-app
PICTURE_MANA_SERVICE_KEY= PICTURE_MANA_SERVICE_KEY=
# ============================================ # ============================================
# NUTRIPHI PROJECT # FOOD PROJECT
# ============================================ # ============================================
NUTRIPHI_BACKEND_PORT=3023 FOOD_BACKEND_PORT=3023
NUTRIPHI_DATABASE_URL=postgresql://mana:devpassword@localhost:5432/mana_platform FOOD_DATABASE_URL=postgresql://mana:devpassword@localhost:5432/mana_platform
NUTRIPHI_APP_ID=nutriphi FOOD_APP_ID=food
# Google Gemini API for food image analysis # Google Gemini API for food image analysis
GEMINI_API_KEY=AIzaSyBR9iP74hlo-mhI-Cl4QEvKprRzPPMb-GA GEMINI_API_KEY=AIzaSyBR9iP74hlo-mhI-Cl4QEvKprRzPPMb-GA
# S3 Storage (uses MinIO locally via shared S3_* variables) # 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 # ZITARE PROJECT
@ -472,5 +472,5 @@ GPU_API_KEY=sk-gpu-cf483ede1e05e28fba5e56c94cd3c24e7c245e57816d3e86
GPU_SERVER_URL=https://gpu.mana.how GPU_SERVER_URL=https://gpu.mana.how
GPU_SERVER_LAN_URL=http://192.168.178.11 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 VISION_MODEL=ollama/gemma3:12b

View file

@ -110,7 +110,7 @@ AZURE_STORAGE_ACCOUNT_NAME=
AZURE_STORAGE_ACCOUNT_KEY= AZURE_STORAGE_ACCOUNT_KEY=
# ─── Google Gemini ────────────────────────────────────────── # ─── 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= GEMINI_API_KEY=
# ─── Service-to-service auth keys ─────────────────────────── # ─── Service-to-service auth keys ───────────────────────────

View file

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

View file

@ -71,8 +71,8 @@ jobs:
storage-backend: ${{ steps.changes.outputs.storage-backend }} storage-backend: ${{ steps.changes.outputs.storage-backend }}
storage-web: ${{ steps.changes.outputs.storage-web }} storage-web: ${{ steps.changes.outputs.storage-web }}
telegram-stats-bot: ${{ steps.changes.outputs.telegram-stats-bot }} telegram-stats-bot: ${{ steps.changes.outputs.telegram-stats-bot }}
nutriphi-backend: ${{ steps.changes.outputs.nutriphi-backend }} food-backend: ${{ steps.changes.outputs.food-backend }}
nutriphi-web: ${{ steps.changes.outputs.nutriphi-web }} food-web: ${{ steps.changes.outputs.food-web }}
skilltree-web: ${{ steps.changes.outputs.skilltree-web }} skilltree-web: ${{ steps.changes.outputs.skilltree-web }}
any-changes: ${{ steps.changes.outputs.any-changes }} any-changes: ${{ steps.changes.outputs.any-changes }}
steps: steps:
@ -109,8 +109,8 @@ jobs:
echo "storage-backend=true" >> $GITHUB_OUTPUT echo "storage-backend=true" >> $GITHUB_OUTPUT
echo "storage-web=true" >> $GITHUB_OUTPUT echo "storage-web=true" >> $GITHUB_OUTPUT
echo "telegram-stats-bot=true" >> $GITHUB_OUTPUT echo "telegram-stats-bot=true" >> $GITHUB_OUTPUT
echo "nutriphi-backend=true" >> $GITHUB_OUTPUT echo "food-backend=true" >> $GITHUB_OUTPUT
echo "nutriphi-web=true" >> $GITHUB_OUTPUT echo "food-web=true" >> $GITHUB_OUTPUT
echo "skilltree-web=true" >> $GITHUB_OUTPUT echo "skilltree-web=true" >> $GITHUB_OUTPUT
echo "any-changes=true" >> $GITHUB_OUTPUT echo "any-changes=true" >> $GITHUB_OUTPUT
exit 0 exit 0
@ -151,8 +151,8 @@ jobs:
echo "storage-backend=true" >> $GITHUB_OUTPUT echo "storage-backend=true" >> $GITHUB_OUTPUT
echo "storage-web=true" >> $GITHUB_OUTPUT echo "storage-web=true" >> $GITHUB_OUTPUT
echo "telegram-stats-bot=true" >> $GITHUB_OUTPUT echo "telegram-stats-bot=true" >> $GITHUB_OUTPUT
echo "nutriphi-backend=true" >> $GITHUB_OUTPUT echo "food-backend=true" >> $GITHUB_OUTPUT
echo "nutriphi-web=true" >> $GITHUB_OUTPUT echo "food-web=true" >> $GITHUB_OUTPUT
echo "skilltree-web=true" >> $GITHUB_OUTPUT echo "skilltree-web=true" >> $GITHUB_OUTPUT
echo "any-changes=true" >> $GITHUB_OUTPUT echo "any-changes=true" >> $GITHUB_OUTPUT
exit 0 exit 0
@ -341,20 +341,20 @@ jobs:
echo "telegram-stats-bot=false" >> $GITHUB_OUTPUT echo "telegram-stats-bot=false" >> $GITHUB_OUTPUT
fi fi
# nutriphi-backend # food-backend
NUTRIPHI_BACKEND_CHANGED=$(check_pattern "apps/nutriphi/apps/backend/|apps/nutriphi/packages/") FOOD_BACKEND_CHANGED=$(check_pattern "apps/food/apps/backend/|apps/food/packages/")
if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$NUTRIPHI_BACKEND_CHANGED" == "true" ]; then if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$FOOD_BACKEND_CHANGED" == "true" ]; then
echo "nutriphi-backend=true" >> $GITHUB_OUTPUT echo "food-backend=true" >> $GITHUB_OUTPUT
else else
echo "nutriphi-backend=false" >> $GITHUB_OUTPUT echo "food-backend=false" >> $GITHUB_OUTPUT
fi fi
# nutriphi-web # food-web
NUTRIPHI_WEB_CHANGED=$(check_pattern "apps/nutriphi/apps/web/|apps/nutriphi/packages/") 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" ] || [ "$NUTRIPHI_WEB_CHANGED" == "true" ]; then if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$SHARED_UI_CHANGED" == "true" ] || [ "$SHARED_WEB_CHANGED" == "true" ] || [ "$FOOD_WEB_CHANGED" == "true" ]; then
echo "nutriphi-web=true" >> $GITHUB_OUTPUT echo "food-web=true" >> $GITHUB_OUTPUT
else else
echo "nutriphi-web=false" >> $GITHUB_OUTPUT echo "food-web=false" >> $GITHUB_OUTPUT
fi fi
# skilltree-backend: REMOVED — migrated to local-first # 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-backend | ${{ steps.changes.outputs.storage-backend }} |" >> $GITHUB_STEP_SUMMARY
echo "| storage-web | ${{ steps.changes.outputs.storage-web }} |" >> $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 "| telegram-stats-bot | ${{ steps.changes.outputs.telegram-stats-bot }} |" >> $GITHUB_STEP_SUMMARY
echo "| nutriphi-backend | ${{ steps.changes.outputs.nutriphi-backend }} |" >> $GITHUB_STEP_SUMMARY echo "| food-backend | ${{ steps.changes.outputs.food-backend }} |" >> $GITHUB_STEP_SUMMARY
echo "| nutriphi-web | ${{ steps.changes.outputs.nutriphi-web }} |" >> $GITHUB_STEP_SUMMARY echo "| food-web | ${{ steps.changes.outputs.food-web }} |" >> $GITHUB_STEP_SUMMARY
echo "| skilltree-backend | removed |" >> $GITHUB_STEP_SUMMARY echo "| skilltree-backend | removed |" >> $GITHUB_STEP_SUMMARY
echo "| skilltree-web | ${{ steps.changes.outputs.skilltree-web }} |" >> $GITHUB_STEP_SUMMARY echo "| skilltree-web | ${{ steps.changes.outputs.skilltree-web }} |" >> $GITHUB_STEP_SUMMARY
echo "| zitare-backend | removed |" >> $GITHUB_STEP_SUMMARY echo "| zitare-backend | removed |" >> $GITHUB_STEP_SUMMARY
@ -1173,11 +1173,11 @@ jobs:
cache-from: type=gha cache-from: type=gha
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
build-nutriphi-backend: build-food-backend:
name: Build nutriphi-backend name: Build food-backend
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: detect-changes needs: detect-changes
if: needs.detect-changes.outputs.nutriphi-backend == 'true' if: needs.detect-changes.outputs.food-backend == 'true'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3 - uses: docker/setup-qemu-action@v3
@ -1190,23 +1190,23 @@ jobs:
- uses: docker/metadata-action@v5 - uses: docker/metadata-action@v5
id: meta id: meta
with: with:
images: ghcr.io/${{ github.repository_owner }}/nutriphi-backend images: ghcr.io/${{ github.repository_owner }}/food-backend
tags: type=raw,value=latest tags: type=raw,value=latest
- uses: docker/build-push-action@v5 - uses: docker/build-push-action@v5
with: with:
context: . context: .
file: apps/nutriphi/apps/backend/Dockerfile file: apps/food/apps/backend/Dockerfile
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha cache-from: type=gha
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
build-nutriphi-web: build-food-web:
name: Build nutriphi-web name: Build food-web
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: detect-changes needs: detect-changes
if: needs.detect-changes.outputs.nutriphi-web == 'true' if: needs.detect-changes.outputs.food-web == 'true'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3 - uses: docker/setup-qemu-action@v3
@ -1219,12 +1219,12 @@ jobs:
- uses: docker/metadata-action@v5 - uses: docker/metadata-action@v5
id: meta id: meta
with: with:
images: ghcr.io/${{ github.repository_owner }}/nutriphi-web images: ghcr.io/${{ github.repository_owner }}/food-web
tags: type=raw,value=latest tags: type=raw,value=latest
- uses: docker/build-push-action@v5 - uses: docker/build-push-action@v5
with: with:
context: . context: .
file: apps/nutriphi/apps/web/Dockerfile file: apps/food/apps/web/Dockerfile
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
push: true push: true
tags: ${{ steps.meta.outputs.tags }} 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 | | **storage** | Cloud storage | NestJS backend, SvelteKit web |
| **questions** | Q&A with web search | SvelteKit web | | **questions** | Q&A with web search | SvelteKit web |
| **skilltree** | Skill tree visualization | NestJS backend, 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 | | **citycorners** | City guide | NestJS backend, SvelteKit web, Astro landing |
| **presi** | Presentation tool | NestJS backend, SvelteKit web | | **presi** | Presentation tool | NestJS backend, SvelteKit web |
| **photos** | Photo management | 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 { storageRoutes } from './modules/storage/routes';
import { todoRoutes } from './modules/todo/routes'; import { todoRoutes } from './modules/todo/routes';
import { plantsRoutes } from './modules/plants/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 { guidesRoutes } from './modules/guides/routes';
import { moodlitRoutes } from './modules/moodlit/routes'; import { moodlitRoutes } from './modules/moodlit/routes';
import { newsRoutes } from './modules/news/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/storage', storageRoutes);
app.route('/api/v1/todo', todoRoutes); app.route('/api/v1/todo', todoRoutes);
app.route('/api/v1/plants', plantsRoutes); 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/guides', guidesRoutes);
app.route('/api/v1/moodlit', moodlitRoutes); app.route('/api/v1/moodlit', moodlitRoutes);
app.route('/api/v1/news', newsRoutes); 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 * CRUD for meals, goals, favorites is handled by mana-sync. This module
* owns the server-only operations: photo upload to mana-media, structured * owns the server-only operations: photo upload to mana-media, structured
@ -94,7 +94,7 @@ routes.post('/photos/upload', async (c) => {
try { try {
const { uploadImageToMedia } = await import('../../lib/media'); const { uploadImageToMedia } = await import('../../lib/media');
const buffer = await file.arrayBuffer(); 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( return c.json(
{ {
@ -106,7 +106,7 @@ routes.post('/photos/upload', async (c) => {
201 201
); );
} catch (err) { } catch (err) {
logger.error('nutriphi.upload_failed', { logger.error('food.upload_failed', {
error: err instanceof Error ? err.message : String(err), error: err instanceof Error ? err.message : String(err),
}); });
return c.json({ error: 'Upload failed' }, 500); return c.json({ error: 'Upload failed' }, 500);
@ -141,7 +141,7 @@ routes.post('/analysis/photo', async (c) => {
}); });
return c.json(envelope(object)); return c.json(envelope(object));
} catch (err) { } catch (err) {
logger.error('nutriphi.photo_analysis_failed', { logger.error('food.photo_analysis_failed', {
error: err instanceof Error ? err.message : String(err), error: err instanceof Error ? err.message : String(err),
}); });
return c.json({ error: 'Analysis failed' }, 500); return c.json({ error: 'Analysis failed' }, 500);
@ -173,7 +173,7 @@ routes.post('/analysis/text', async (c) => {
}); });
return c.json(envelope(object)); return c.json(envelope(object));
} catch (err) { } catch (err) {
logger.error('nutriphi.text_analysis_failed', { logger.error('food.text_analysis_failed', {
error: err instanceof Error ? err.message : String(err), error: err instanceof Error ? err.message : String(err),
}); });
return c.json({ error: 'Analysis failed' }, 500); return c.json({ error: 'Analysis failed' }, 500);
@ -218,4 +218,4 @@ routes.post('/recommendations/generate', async (c) => {
return c.json({ recommendations: hints }); 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 * module owns the server-only operations: photo upload to mana-media
* and structured plant identification via the Vercel AI SDK * and structured plant identification via the Vercel AI SDK
* (`generateObject`) using the shared PlantIdentificationSchema in * (`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. * the AI SDK + Zod approach.
*/ */
@ -21,20 +21,20 @@ import {
import { logger, type AuthVariables } from '@mana/shared-hono'; import { logger, type AuthVariables } from '@mana/shared-hono';
const LLM_URL = process.env.MANA_LLM_URL || 'http://localhost:3025'; 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. // the /v1 base URL.
const VISION_MODEL = process.env.VISION_MODEL || 'ollama/gemma3:4b'; const VISION_MODEL = process.env.VISION_MODEL || 'ollama/gemma3:4b';
const llm = createOpenAICompatible({ const llm = createOpenAICompatible({
name: 'mana-llm', name: 'mana-llm',
baseURL: `${LLM_URL}/v1`, 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, 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.`; 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. // hint for Anthropic prompt caching, ignored by Gemini today.
const SYSTEM_CACHE_HINT = { const SYSTEM_CACHE_HINT = {
anthropic: { cacheControl: { type: 'ephemeral' as const } }, anthropic: { cacheControl: { type: 'ephemeral' as const } },

View file

@ -37,7 +37,7 @@ open http://localhost:9001
| `picture-storage` | Picture | AI-generated images | | `picture-storage` | Picture | AI-generated images |
| `chat-storage` | Chat | User file uploads | | `chat-storage` | Chat | User file uploads |
| `cards-storage` | Cards | Card/deck assets | | `cards-storage` | Cards | Card/deck assets |
| `nutriphi-storage` | NutriPhi | Meal photos | | `food-storage` | Food | Meal photos |
| `contacts-storage` | Contacts | Contact avatars | | `contacts-storage` | Contacts | Contact avatars |
| `calendar-storage` | Calendar | Event attachments | | `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({ export default defineConfig({
integrations: [tailwind()], 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", "version": "0.2.0",
"private": true, "private": true,
"type": "module", "type": "module",

View file

@ -6,7 +6,7 @@ interface Props {
description?: string; 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> <!doctype html>

View file

@ -71,7 +71,7 @@ const faqs = [
{ {
question: 'Funktioniert die App mit allen Gerichten?', question: 'Funktioniert die App mit allen Gerichten?',
answer: 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?', question: 'Wie funktioniert das Credit-System?',
@ -81,12 +81,12 @@ const faqs = [
{ {
question: 'Gibt es eine kostenlose Version?', question: 'Gibt es eine kostenlose Version?',
answer: 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 --> <!-- Navigation -->
<nav <nav
class="fixed top-0 left-0 right-0 z-50 bg-[#0F1F0F]/90 backdrop-blur border-b border-green-900/30" 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"> <div class="w-8 h-8 rounded-lg bg-primary flex items-center justify-center">
<span class="text-white font-bold">N</span> <span class="text-white font-bold">N</span>
</div> </div>
<span class="font-semibold text-white">NutriPhi</span> <span class="font-semibold text-white">Food</span>
</div> </div>
<a <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" class="px-4 py-2 bg-primary hover:bg-primary-hover text-white font-medium rounded-lg transition-colors"
> >
Jetzt starten Jetzt starten
@ -138,13 +138,13 @@ const faqs = [
</h1> </h1>
<p class="text-xl text-gray-300 mb-10 max-w-2xl mx-auto"> <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. KI-Coaching erreichst du deine Gesundheitsziele.
</p> </p>
<div class="flex flex-col sm:flex-row gap-4 justify-center"> <div class="flex flex-col sm:flex-row gap-4 justify-center">
<a <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" class="px-8 py-4 bg-primary hover:bg-primary-hover text-white font-semibold rounded-xl transition-colors text-lg"
> >
Kostenlos starten Kostenlos starten
@ -165,7 +165,7 @@ const faqs = [
<div class="text-center mb-16"> <div class="text-center mb-16">
<h2 class="text-3xl md:text-4xl font-bold text-white mb-4">Alles was du brauchst</h2> <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"> <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> </p>
</div> </div>
@ -235,12 +235,12 @@ const faqs = [
<!-- CTA Section --> <!-- CTA Section -->
<section class="py-20 px-4"> <section class="py-20 px-4">
<div class="container mx-auto max-w-4xl text-center"> <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"> <p class="text-xl text-gray-300 mb-10 max-w-2xl mx-auto">
Kostenlos. Ohne Kreditkarte. Sofort loslegen. Kostenlos. Ohne Kreditkarte. Sofort loslegen.
</p> </p>
<a <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" 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 Jetzt kostenlos registrieren
@ -257,7 +257,7 @@ const faqs = [
<div class="w-6 h-6 rounded bg-primary flex items-center justify-center"> <div class="w-6 h-6 rounded bg-primary flex items-center justify-center">
<span class="text-white font-bold text-xs">N</span> <span class="text-white font-bold text-xs">N</span>
</div> </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>
<div class="flex gap-6 text-sm text-gray-400"> <div class="flex gap-6 text-sm text-gray-400">
<a href="/privacy" class="hover:text-white transition-colors">Datenschutz</a> <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" compatibility_date = "2024-12-01"
pages_build_output_dir = "dist" 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", "version": "0.2.0",
"type": "commonjs", "type": "commonjs",
"main": "./src/index.ts", "main": "./src/index.ts",

View file

@ -110,7 +110,7 @@ export const CREDIT_COSTS = {
} as const; } as const;
// Theme colors // Theme colors
export const NUTRIPHI_COLORS = { export const FOOD_COLORS = {
primary: '#22C55E', // Green 500 primary: '#22C55E', // Green 500
primaryHover: '#16A34A', // Green 600 primaryHover: '#16A34A', // Green 600
primaryLight: '#86EFAC', // Green 300 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. 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 category: wellness
icon: 🥗 icon: 🥗
@ -20,22 +20,22 @@ features:
status: beta status: beta
releaseDate: Geplant Q3 2025 releaseDate: Geplant Q3 2025
order: 8 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 ## Hauptfunktionen
### 📸 Foto-Tracking ### 📸 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 ### 🎯 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 ### 🧪 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. 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 - **Fitness-Enthusiasten**: Optimale Ernährung für Training und Regeneration
- **Abnehmwillige**: Kaloriendefizit einfach im Blick behalten - **Abnehmwillige**: Kaloriendefizit einfach im Blick behalten
@ -55,4 +55,4 @@ Erhalte Rezeptvorschläge, die zu deinen Zielen passen und die Lebensmittel nutz
## Preise ## 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 | - | | Clock | clock-backend | 3017 | clock | - |
| Todo | todo-backend | 3018 | todo | - | | Todo | todo-backend | 3018 | todo | - |
| Storage | storage-backend | 3019 | storage | MinIO (Dateien) | | 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 | - | | SkillTree | skilltree-backend | 3024 | skilltree | - |
#### Tier 4: Web-Frontends (11 Services) #### 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 | | Calendar | calendar-web | 5186 | 3016 |
| Clock | clock-web | 5187 | 3017 | | Clock | clock-web | 5187 | 3017 |
| Todo | todo-web | 5188 | 3018 | | Todo | todo-web | 5188 | 3018 |
| NutriPhi | nutriphi-web | 5189 | 3023 | | Food | food-web | 5189 | 3023 |
| LLM Playground | llm-playground | 5190 | - | | LLM Playground | llm-playground | 5190 | - |
| SkillTree | skilltree-web | 5195 | 3024 | | 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 | | Project Doc Bot | mana-matrix-project-doc-bot | 3313 | Dokumentation |
| Todo Bot | mana-matrix-todo-bot | 3314 | Task Management | | Todo Bot | mana-matrix-todo-bot | 3314 | Task Management |
| Calendar Bot | mana-matrix-calendar-bot | 3315 | Termine | | 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 | | Zitare Bot | mana-matrix-zitare-bot | 3317 | Quotes |
| Clock Bot | mana-matrix-clock-bot | 3318 | Time Tracking | | Clock Bot | mana-matrix-clock-bot | 3318 | Time Tracking |
| TTS Bot | mana-matrix-tts-bot | 3033 | Text-to-Speech | | TTS Bot | mana-matrix-tts-bot | 3033 | Text-to-Speech |
@ -260,7 +260,7 @@ api-gateway:
Viele Matrix-Bots teilen ähnlichen Code: Viele Matrix-Bots teilen ähnlichen Code:
- `matrix-todo-bot` und `matrix-calendar-bot` haben ähnliche Reminder-Logik - `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 - `matrix-mana-bot` sollte theoretisch alle anderen ersetzen
### 5. Volume-Fragmentierung ### 5. Volume-Fragmentierung
@ -274,7 +274,7 @@ volumes:
matrix_project_doc_bot_data: matrix_project_doc_bot_data:
matrix_calendar_bot_data: matrix_calendar_bot_data:
matrix_todo_bot_data: matrix_todo_bot_data:
matrix_nutriphi_bot_data: matrix_food_bot_data:
matrix_zitare_bot_data: matrix_zitare_bot_data:
matrix_clock_bot_data: matrix_clock_bot_data:
matrix_tts_bot_data: matrix_tts_bot_data:
@ -308,7 +308,7 @@ NEU (Strukturiert):
│ ├── 3034: contacts-backend │ │ ├── 3034: contacts-backend │
│ ├── 3035: storage-backend │ │ ├── 3035: storage-backend │
│ ├── 3036: presi-backend │ │ ├── 3036: presi-backend │
│ ├── 3037: nutriphi-backend │ │ ├── 3037: food-backend │
│ └── 3038: skilltree-backend │ │ └── 3038: skilltree-backend │
│ │ │ │
│ 4000-4099: Matrix Stack │ │ 4000-4099: Matrix Stack │
@ -330,7 +330,7 @@ NEU (Strukturiert):
│ ├── 5014: contacts-web │ │ ├── 5014: contacts-web │
│ ├── 5015: storage-web │ │ ├── 5015: storage-web │
│ ├── 5016: presi-web │ │ ├── 5016: presi-web │
│ ├── 5017: nutriphi-web │ │ ├── 5017: food-web │
│ ├── 5018: skilltree-web │ │ ├── 5018: skilltree-web │
│ └── 5090: llm-playground │ │ └── 5090: llm-playground │
│ │ │ │
@ -401,7 +401,7 @@ AKTUELL: 10 separate Bot-Container
│ matrix-mana-bot │ matrix-ollama-bot │ ... │ │ matrix-mana-bot │ matrix-ollama-bot │ ... │
│ matrix-stats-bot │ matrix-project-doc │ │ │ matrix-stats-bot │ matrix-project-doc │ │
│ matrix-todo-bot │ matrix-calendar-bot │ │ │ matrix-todo-bot │ matrix-calendar-bot │ │
│ matrix-nutriphi-bot │ matrix-zitare-bot │ │ │ matrix-food-bot │ matrix-zitare-bot │ │
│ matrix-clock-bot │ matrix-tts-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.' 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 date: 2026-01-25
author: 'Till Schneider' author: 'Till Schneider'
category: 'feature' category: 'feature'
tags: tags:
[ [
'nutriphi', 'food',
'prometheus', 'prometheus',
'grafana', 'grafana',
'watchtower', 'watchtower',
@ -35,7 +35,7 @@ workingHours:
Massiver Tag mit **38 Commits** und Fokus auf neue App, Monitoring und Infrastructure: 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 - **Prometheus Metriken** - Für alle Backends implementiert
- **Grafana Dashboards** - Umfassende Visualisierung und Alerting - **Grafana Dashboards** - Umfassende Visualisierung und Alerting
- **Watchtower** - Automatisches Docker-Image-Update auf Mac Mini - **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. 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 │ │ Mobile │ Web │ Backend │
│ (Expo) │ (SvelteKit) │ (NestJS) │ │ (Expo) │ (SvelteKit) │ (NestJS) │
@ -141,7 +141,7 @@ export class AppModule {}
- cards-backend (Port 3009) - cards-backend (Port 3009)
- contacts-backend (Port 3010) - contacts-backend (Port 3010)
- calendar-backend (Port 3016) - 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 - calendar-web, clock-web, contacts-web
- chat-web, picture-web, zitare-web - chat-web, picture-web, zitare-web
- todo-web, cards-web, manacore-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 ```yaml
# .github/workflows/docker-presi.yml # .github/workflows/docker-presi.yml
# .github/workflows/docker-storage.yml # .github/workflows/docker-storage.yml
# .github/workflows/docker-nutriphi.yml # .github/workflows/docker-food.yml
``` ```
### Health Check Fixes ### Health Check Fixes
@ -347,7 +347,7 @@ scripts/staging-deploy.sh
| Bereich | Commits | Highlights | | Bereich | Commits | Highlights |
| ----------------- | ------- | ---------------------------- | | ----------------- | ------- | ---------------------------- |
| **NutriPhi** | 2 | Neue AI Nutrition App | | **Food** | 2 | Neue AI Nutrition App |
| **Monitoring** | 8 | Prometheus für alle Backends | | **Monitoring** | 8 | Prometheus für alle Backends |
| **Grafana** | 3 | Dashboards & Alerting | | **Grafana** | 3 | Dashboards & Alerting |
| **Watchtower** | 6 | Auto-Deploy eingerichtet | | **Watchtower** | 6 | Auto-Deploy eingerichtet |
@ -361,6 +361,6 @@ scripts/staging-deploy.sh
## Nächste Schritte ## Nächste Schritte
1. **Matrix Infrastructure** für GDPR-konforme Bots 1. **Matrix Infrastructure** für GDPR-konforme Bots
2. **NutriPhi Mobile** App fertigstellen 2. **Food Mobile** App fertigstellen
3. **Alerting** in Grafana aktivieren 3. **Alerting** in Grafana aktivieren
4. **User Statistics** Dashboard erweitern 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 - **mana-search Microservice** - SearXNG Meta-Search + Content Extraction
- **@manacore/bot-services** - Shared Business Logic Package - **@manacore/bot-services** - Shared Business Logic Package
- **matrix-mana-bot** - Unified Gateway Bot für alle Features - **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 - **OIDC Provider** - Matrix SSO via mana-core-auth
- **VictoriaMetrics** - Monitoring Upgrade mit DuckDB Analytics - **VictoriaMetrics** - Monitoring Upgrade mit DuckDB Analytics
- **App Cleanup** - Demo Mode für Calendar, Todo, Contacts - **App Cleanup** - Demo Mode für Calendar, Todo, Contacts
@ -365,7 +365,7 @@ Task-Management via Matrix:
**Syntax:** `!todo Einkaufen !p1 @morgen #haushalt` **Syntax:** `!todo Einkaufen !p1 @morgen #haushalt`
### matrix-nutriphi-bot ### matrix-food-bot
Ernährungs-Tracking via Matrix: Ernährungs-Tracking via Matrix:
@ -514,7 +514,7 @@ apps/calendar/apps/web/src/lib/services/
│ └── sync-manager.ts # Bidirektionale Sync │ └── sync-manager.ts # Bidirektionale Sync
``` ```
### NutriPhi: Production Ready ### Food: Production Ready
- 99 neue Tests (Backend, Web, Shared) - 99 neue Tests (Backend, Web, Shared)
- Error Handling mit deutschen Meldungen - Error Handling mit deutschen Meldungen
@ -561,18 +561,18 @@ apps/calendar/apps/web/src/lib/services/
## Neue Services ## Neue Services
| Service | Port | Typ | Beschreibung | | Service | Port | Typ | Beschreibung |
| ------------------- | ---- | --------- | ---------------------- | | ----------------- | ---- | --------- | ---------------------- |
| skilltree-backend | 3024 | NestJS | Skill-Tracking API | | skilltree-backend | 3024 | NestJS | Skill-Tracking API |
| skilltree-web | 5195 | SvelteKit | Skill-Tracking UI | | skilltree-web | 5195 | SvelteKit | Skill-Tracking UI |
| questions-backend | 3111 | NestJS | Research Assistant API | | questions-backend | 3111 | NestJS | Research Assistant API |
| questions-web | 5111 | SvelteKit | Research Assistant UI | | questions-web | 5111 | SvelteKit | Research Assistant UI |
| mana-search | 3021 | NestJS | Such-Microservice | | mana-search | 3021 | NestJS | Such-Microservice |
| matrix-mana-bot | 3310 | NestJS | Gateway Bot | | matrix-mana-bot | 3310 | NestJS | Gateway Bot |
| matrix-todo-bot | 3315 | NestJS | Todo Bot | | matrix-todo-bot | 3315 | NestJS | Todo Bot |
| matrix-nutriphi-bot | 3316 | NestJS | Nutrition Bot | | matrix-food-bot | 3316 | NestJS | Nutrition Bot |
| matrix-zitare-bot | 3317 | NestJS | Quotes Bot | | matrix-zitare-bot | 3317 | NestJS | Quotes Bot |
| matrix-clock-bot | 3318 | NestJS | Timer 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 | | Matrix Client | 1 | Phase 2 Features |
| mana-search | 3 | SearXNG, Extraction, Cache | | mana-search | 3 | SearXNG, Extraction, Cache |
| Bot Services | 2 | Shared Package + Gateway | | 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 | | OIDC | 6 | Matrix SSO Provider |
| App Cleanup | 8 | Demo Mode, Feature Removal | | App Cleanup | 8 | Demo Mode, Feature Removal |
| Monitoring | 2 | VictoriaMetrics, DuckDB | | Monitoring | 2 | VictoriaMetrics, DuckDB |
| NutriPhi | 2 | Tests, Production Ready | | Food | 2 | Tests, Production Ready |
| Telegram Bots | 1 | NutriPhi, Todo, Zitare | | Telegram Bots | 1 | Food, Todo, Zitare |
| Bugfixes | 15+ | Auth, Matrix, Docker | | Bugfixes | 15+ | Auth, Matrix, Docker |
| Documentation | 5 | Monitoring, Services, DevLogs | | Documentation | 5 | Monitoring, Services, DevLogs |

View file

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

View file

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

View file

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

View file

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

View file

@ -247,7 +247,7 @@ Temporär deaktivierte Services (fehlende Deployments):
```yaml ```yaml
# Auskommentiert bis Deployment fertig # Auskommentiert bis Deployment fertig
# inventory-backend: # inventory-backend:
# nutriphi-backend: # food-backend:
# wisekeep-backend: # wisekeep-backend:
``` ```
@ -423,4 +423,4 @@ userId: text('user_id').notNull();
1. **GDPR Export UI** - Download-Button im mana.how Dashboard 1. **GDPR Export UI** - Download-Button im mana.how Dashboard
2. **Matrix E2EE** - Ende-zu-Ende Verschlüsselung aktivieren 2. **Matrix E2EE** - Ende-zu-Ende Verschlüsselung aktivieren
3. **Alertmanager** - Discord Webhook Integration 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', 'tts',
'german-voice', 'german-voice',
'emoji-picker', 'emoji-picker',
'nutriphi', 'food',
'stats-bot', 'stats-bot',
] ]
featured: true featured: true
@ -320,7 +320,7 @@ POST / api / users / me / preferences / emojis;
--- ---
## NutriPhi Bot Improvements ## Food Bot Improvements
### Auto-Analyze Text ### Auto-Analyze Text
@ -449,7 +449,7 @@ Tracking IDs für alle Web-Apps aktualisiert.
| **Clock Bot** | 4 | Timer Progress + Topic | | **Clock Bot** | 4 | Timer Progress + Topic |
| **TTS** | 4 | German Voice + WAV | | **TTS** | 4 | German Voice + WAV |
| **Emoji Picker** | 3 | Recently Used + Sync | | **Emoji Picker** | 3 | Recently Used + Sync |
| **NutriPhi** | 5 | Text-Analyse + Fixes | | **Food** | 5 | Text-Analyse + Fixes |
| **Stats Bot** | 3 | Infra Monitoring | | **Stats Bot** | 3 | Infra Monitoring |
| **Bot Fixes** | 8 | Loop Prevention + Auth | | **Bot Fixes** | 8 | Loop Prevention + Auth |
| **Session** | 2 | Auto-Refresh | | **Session** | 2 | Auto-Refresh |

View file

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

View file

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

View file

@ -1,10 +1,10 @@
--- ---
title: 'spiral-db, Planta Bot & Mana Values' 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 date: 2026-02-17
author: 'Till Schneider' author: 'Till Schneider'
category: 'feature' category: 'feature'
tags: ['spiral-db', 'planta', 'nutriphi', 'todo', 'mana-bot', 'wallpaper', 'documentation'] tags: ['spiral-db', 'planta', 'food', 'todo', 'mana-bot', 'wallpaper', 'documentation']
featured: false featured: false
commits: 26 commits: 26
readTime: 10 readTime: 10
@ -25,7 +25,7 @@ Produktiver Tag mit **26 Commits** neue Packages, Bot-Features und Dokumenta
- **spiral-db** - Pixel-basierte Spiral-Datenbank-Visualisierung - **spiral-db** - Pixel-basierte Spiral-Datenbank-Visualisierung
- **Planta Bot** - KI-Pflanzenidentifikation per Bild-Upload - **Planta Bot** - KI-Pflanzenidentifikation per Bild-Upload
- **NutriPhi Bot** - Smartes Meal Feedback - **Food Bot** - Smartes Meal Feedback
- **Mana Bot** - Tägliche Morgenzusammenfassung - **Mana Bot** - Tägliche Morgenzusammenfassung
- **Mana Values** - Manifest-Dokumentation - **Mana Values** - Manifest-Dokumentation
- **Wallpaper Generator** - Neues Package - **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. 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 | | **spiral-db** | 5 | Package + Todo Integration |
| **Planta Bot** | 4 | KI-Pflanzenidentifikation | | **Planta Bot** | 4 | KI-Pflanzenidentifikation |
| **NutriPhi Bot** | 3 | Smartes Meal Feedback | | **Food Bot** | 3 | Smartes Meal Feedback |
| **Mana Bot** | 3 | Morning Summary | | **Mana Bot** | 3 | Morning Summary |
| **QR Code** | 2 | My-Data Export | | **QR Code** | 2 | My-Data Export |
| **Wallpaper** | 2 | Generator Package | | **Wallpaper** | 2 | Generator Package |

View file

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

View file

@ -201,9 +201,9 @@ export const handleError: HandleClientError = ({ error }) => {
### Alle 19 Web-Apps angebunden ### Alle 19 Web-Apps angebunden
| Apps | | Apps |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Calendar, Chat, Clock, Contacts, Context, Manacore, Cards, Matrix, Mukke, NutriPhi, Photos, Picture, Planta, Presi, Questions, Skilltree, Storage, Todo, Zitare | | Calendar, Chat, Clock, Contacts, Context, Manacore, Cards, Matrix, Mukke, Food, Photos, Picture, Planta, Presi, Questions, Skilltree, Storage, Todo, Zitare |
### API ### 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 - `@chat/backend` — Chat AI-Completions
- `@zitare/backend` — Zitat-Analyse (vorher eigener Ollama-Service) - `@zitare/backend` — Zitat-Analyse (vorher eigener Ollama-Service)
- `@planta/backend` — Pflanzen-Vision-Analyse - `@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 - `mana-core-auth` — AI-Service für Auth-Features
### Google Gemini Fallback ### 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 | | Storage | Upload, Download, Share, Preview |
| Photos | Upload, Edit, Album-Create | | Photos | Upload, Edit, Album-Create |
| Context, SkillTree, Planta, Questions | App-spezifische Events | | Context, SkillTree, Planta, Questions | App-spezifische Events |
| NutriPhi, Cards | Meal-Log, Card-Create | | Food, Cards | Meal-Log, Card-Create |
### Commits ### Commits
@ -61,7 +61,7 @@ Neuer `Analytics Maturity`-Metrik in ManaScore und Custom Event Tracking in 8+ A
- `bade0a17` — Storage Event Tracking - `bade0a17` — Storage Event Tracking
- `3075e515` — Photos Event Tracking - `3075e515` — Photos Event Tracking
- `12b3c4f0` — Context, SkillTree, Planta, Questions - `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-project-doc-bot | Projekt-Dokumentation | 4013 |
| matrix-todo-bot | Aufgabenverwaltung | 4014 | | matrix-todo-bot | Aufgabenverwaltung | 4014 |
| matrix-calendar-bot | Kalender | 4015 | | matrix-calendar-bot | Kalender | 4015 |
| matrix-nutriphi-bot | Ernährungstracking | 4016 | | matrix-food-bot | Ernährungstracking | 4016 |
| matrix-zitare-bot | Zitate & Inspiration | 4017 | | matrix-zitare-bot | Zitate & Inspiration | 4017 |
| matrix-clock-bot | Timer, Alarme, Weltuhren | 4018 | | matrix-clock-bot | Timer, Alarme, Weltuhren | 4018 |
| matrix-tts-bot | Text-to-Speech | 4019 | | matrix-tts-bot | Text-to-Speech | 4019 |
@ -224,7 +224,7 @@ Neues Plugin hinzufügen = 3 Schritte:
### Skeleton (Grundgerüst mit !help, !status) ### 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 | | Chat | 137 | LLM Completions + SSE Streaming |
| Picture | 144 | Replicate Image Gen + S3 Upload | | Picture | 144 | Replicate Image Gen + S3 Upload |
| Calendar | 119 | RRULE Expansion + ICS Import | | Calendar | 119 | RRULE Expansion + ICS Import |
| NutriPhi | 154 | Gemini Meal Analysis | | Food | 154 | Gemini Meal Analysis |
| Planta | 104 | Gemini Plant Analysis + S3 Upload | | Planta | 104 | Gemini Plant Analysis + S3 Upload |
| Traces | 108 | AI Guide Generation | | 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: Die bestehende Web-App wurde vollständig auf den Monorepo-Stack portiert:
| Phase | Was passiert ist | | Phase | Was passiert ist |
|-------|-----------------| | ----- | --------------------------------------------------------------------------------------------- |
| 1 | Package-Struktur: `@memoro/web`, adapter-node, Tailwind v4 + `@manacore/shared-tailwind` | | 1 | Package-Struktur: `@memoro/web`, adapter-node, Tailwind v4 + `@manacore/shared-tailwind` |
| 2 | Auth: `createManaAuthStore()` aus `@manacore/shared-auth-stores`, Google/Apple OAuth entfernt | | 2 | Auth: `createManaAuthStore()` aus `@manacore/shared-auth-stores`, Google/Apple OAuth entfernt |
| 3 | Local-First: `memoroStore` mit 7 Collections (memos, tags, spaces, invites, …) | | 3 | Local-First: `memoroStore` mit 7 Collections (memos, tags, spaces, invites, …) |
| 4 | Guest-Seed: Demo-Daten die sofort geladen werden ohne Login | | 4 | Guest-Seed: Demo-Daten die sofort geladen werden ohne Login |
| 5 | Service Layer: `memoService` + `tagService` von Supabase direct auf local-store Collections | | 5 | Service Layer: `memoService` + `tagService` von Supabase direct auf local-store Collections |
| 6 | Workspace-Integration: `dev:memoro:*` Scripts, CLAUDE.md Eintrag | | 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. **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 ### Vergleich: Vorher vs. Nachher
| Aspekt | NestJS (alt) | Hono/Bun (neu) | | Aspekt | NestJS (alt) | Hono/Bun (neu) |
|--------|-------------|----------------| | ------------ | ------------------------------------ | ------------------------------- |
| Services | 2 (Backend + Audio-Backend) | 2 (Server + Audio-Server) | | Services | 2 (Backend + Audio-Backend) | 2 (Server + Audio-Server) |
| LOC (gesamt) | ~12.000 | ~1.800 | | LOC (gesamt) | ~12.000 | ~1.800 |
| Dependencies | 20+ (@nestjs/*, class-validator, …) | 4 (hono, zod, fluent-ffmpeg, …) | | Dependencies | 20+ (@nestjs/\*, class-validator, …) | 4 (hono, zod, fluent-ffmpeg, …) |
| Cold Start | ~2-3s | ~50ms | | Cold Start | ~2-3s | ~50ms |
| RAM | ~400MB | ~80MB | | RAM | ~400MB | ~80MB |
| Auth | Supabase JWT | mana-auth JWT | | Auth | Supabase JWT | mana-auth JWT |
| OAuth | Google + Apple | Keiner (self-sovereign) | | 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: Die Task-Cards wurden weiter bereinigt:
| Vorher | Nachher | | Vorher | Nachher |
|--------|---------| | ------------------------------- | ------------------------------------------------ |
| Border + Hintergrundfarbe | Kein Border, kein Hintergrund | | Border + Hintergrundfarbe | Kein Border, kein Hintergrund |
| Checkbox vertikal zentriert | Checkbox am Anfang der ersten Zeile (flex-start) | | Checkbox vertikal zentriert | Checkbox am Anfang der ersten Zeile (flex-start) |
| Titel abgeschnitten (truncate) | Mehrzeilig (word-break) | | Titel abgeschnitten (truncate) | Mehrzeilig (word-break) |
| Hover: translateY + Hintergrund | Kein Hover-Effekt | | Hover: translateY + Hintergrund | Kein Hover-Effekt |
**Resultat:** Die Task-Liste liest sich wie echtes Papier — nur der Text, keine UI-Noise. **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: Drei Komponenten die über viele Apps hinweg dupliziert waren:
| Komponente | Apps (vorher) | Lösung | | Komponente | Apps (vorher) | Lösung |
|-----------|--------------|--------| | ------------------ | ------------------------------------------------------------- | ------------------------------------------------------- |
| `LanguageSelector` | contacts, zitare: Custom-Dropdown mit eigenem State | → `PillDropdown` aus shared-ui (wie die anderen 8 Apps) | | `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` | | `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) | | `AppSlider` | todo, calendar, chat, contacts, presi: statisches `MANA_APPS` | → `getActiveManaApps()` (filtert inaktive Apps) |
**228 Zeilen Netto**, 2 lokale Komponenten gelöscht. **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: 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 | | App | Vorher | Nachher |
|-----|--------|---------| | --------- | ------------- | ------------- |
| chat-web | `ghcr.io/...` | lokaler Build | | chat-web | `ghcr.io/...` | lokaler Build |
| clock-web | `ghcr.io/...` | lokaler Build | | clock-web | `ghcr.io/...` | lokaler Build |
| presi-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. **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 ### Weitere Fixes
| Fix | Beschreibung | | Fix | Beschreibung |
|-----|-------------| | -------------- | ------------------------------------------------------------ |
| Port-Konflikt | calc-web: Port 5026 → 5031 (kollidierte mit zitare-web) | | Port-Konflikt | calc-web: Port 5026 → 5031 (kollidierte mit zitare-web) |
| Cloudflared | Config mit tatsächlichen Container-Ports synchronisiert | | Cloudflared | Config mit tatsächlichen Container-Ports synchronisiert |
| Landings Nginx | `mkdir snippets` vor Copy, status.mana.how vhost hinzugefügt | | Landings Nginx | `mkdir snippets` vor Copy, status.mana.how vhost hinzugefügt |
| Prerender 404 | favicon.png 404s bei skilltree + nutriphi unterdrückt | | Prerender 404 | favicon.png 404s bei skilltree + food unterdrückt |
| inventar-web | Browser-Error-Tracking Import repariert | | inventar-web | Browser-Error-Tracking Import repariert |
--- ---
@ -330,16 +330,16 @@ Drei neue Planungs-/Guidelines-Dokumente:
## Zusammenfassung ## Zusammenfassung
| Bereich | Commits | Highlights | | Bereich | Commits | Highlights |
|---------|---------|-----------| | ------------------ | ------- | -------------------------------------------------------------- |
| Memoro Integration | ~25 | Web, Server, Audio-Server ins Monorepo | | Memoro Integration | ~25 | Web, Server, Audio-Server ins Monorepo |
| Status-Page | ~12 | status.mana.how live, Blackbox Exporter, ManaScore-Badges | | Status-Page | ~12 | status.mana.how live, Blackbox Exporter, ManaScore-Badges |
| Todo Polish | ~20 | Paper-Cards, Complete-Animation, Detail-Modal, Kanban-Subtasks | | Todo Polish | ~20 | Paper-Cards, Complete-Animation, Detail-Modal, Kanban-Subtasks |
| Auth | ~10 | EMAIL_NOT_VERIFIED robust, Resend-Panel, callbackURL Fix | | Auth | ~10 | EMAIL_NOT_VERIFIED robust, Resend-Panel, callbackURL Fix |
| Infra | ~15 | GHCR→lokal, Arcade, Port-Fix, Cloudflared | | Infra | ~15 | GHCR→lokal, Arcade, Port-Fix, Cloudflared |
| UI Unification | ~8 | Elevation-System, LanguageSelector, ConfirmDialog, AppSlider | | UI Unification | ~8 | Elevation-System, LanguageSelector, ConfirmDialog, AppSlider |
| Docs | ~5 | Auth UX Patterns, Bundle Format, Memoro Plan | | Docs | ~5 | Auth UX Patterns, Bundle Format, Memoro Plan |
| Fixes | ~3 | Prerender, inventar-web, manacore-web Login-Redirect | | 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, Welle 1 (12 Module): skilltree, inventar, times, planta,
citycorners, photos, presi, uload, citycorners, photos, presi, uload,
context, questions, nutriphi, calc context, questions, food, calc
Welle 2 (5 Module): storage, cards, playground, guides, Welle 2 (5 Module): storage, cards, playground, guides,
+ restliche Helper + restliche Helper

View file

@ -24,7 +24,7 @@ workingHours:
## Highlights ## 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 - **CAS (SHA-256 Dedup)**, **Thumbnails**, **EXIF-Extraktion** automatisch
- Alle hochgeladenen Bilder erscheinen in der **Photos-Galerie** - Alle hochgeladenen Bilder erscheinen in der **Photos-Galerie**
- Fix: `effect_update_depth_exceeded` in 6 Dashboard-Modulen (Resultat des Unified-App-Switches) - 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 ─┤ Contacts → S3 direkt Contacts ─┤
Planta → S3 direkt ───→ Planta ─┼─→ mana-media → S3 (CAS) + DB Planta → S3 direkt ───→ Planta ─┼─→ mana-media → S3 (CAS) + DB
Storage → S3 direkt Storage ─┤ ↓ Storage → S3 direkt Storage ─┤ ↓
NutriPhi → S3 direkt NutriPhi ─┘ Photos Gallery Food → S3 direkt Food ─┘ Photos Gallery
``` ```
### Implementierung ### Implementierung
@ -72,7 +72,7 @@ mana-media liefert zurück:
### Nebeneffekt: Photos-Galerie wird automatisch befüllt ### 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' description: 'Ernährungstracking mit Gemini AI Food-Analyse, 8 Backend-Modulen und 1.457 Test-Zeilen - aber nicht deployed'
date: 2026-03-19 date: 2026-03-19
app: 'nutriphi' app: 'food'
author: 'Till Schneider' author: 'Till Schneider'
tags: ['audit', 'nutriphi', 'production-readiness', 'ai'] tags: ['audit', 'food', 'production-readiness', 'ai']
score: 63 score: 63
scores: scores:
backend: 78 backend: 78
@ -45,7 +45,7 @@ stats:
## Zusammenfassung ## 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) ## 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 | | **Zitare** | 88 | 93 | +5 | Local-First, war schon solide |
| **Clock** | 85 | 91 | +6 | Local-First + keine Backend-Dependency | | **Clock** | 85 | 91 | +6 | Local-First + keine Backend-Dependency |
| **Storage** | 72 | 82 | +10 | Local-First + S3 Server | | **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 | | **Planta** | 65 | 78 | +13 | Local-First + Vision Server |
| **Mukke** | 68 | 80 | +12 | Local-First + S3 Server | | **Mukke** | 68 | 80 | +12 | Local-First + S3 Server |
| **Questions** | 72 | 83 | +11 | Local-First + Search 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', 'KI-gestützte Karteikarten-App für effektives Lernen und Wissensmanagement',
'app.pictus.description': 'Kreativer KI-Bildgenerator für beeindruckende Bilder und Kunstwerke', 'app.pictus.description': 'Kreativer KI-Bildgenerator für beeindruckende Bilder und Kunstwerke',
'app.orakel.description': 'Intelligente KI-Chat-Assistentin für alle Lebenslagen', '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', 'app.traces.description': 'Entdecke deine Stadt neu mit KI-gestütztem Bewegungs-Tracking',
// Footer // Footer
@ -156,7 +156,7 @@ export const ui = {
'AI-powered flashcard app for effective learning and knowledge management', 'AI-powered flashcard app for effective learning and knowledge management',
'app.pictus.description': 'Creative AI image generator for stunning pictures and artwork', '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.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', 'app.traces.description': 'Rediscover your city with AI-powered movement tracking',
// Footer // Footer
@ -237,7 +237,7 @@ export const ui = {
'app.pictus.description': 'app.pictus.description':
"Generatore di immagini AI creativo per immagini e opere d'arte straordinarie", "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.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 di nutrizione intelligente con tracciamento fotografico basato su AI',
'app.traces.description': 'app.traces.description':
'Riscopri la tua città con il tracciamento dei movimenti basato su AI', 'Riscopri la tua città con il tracciamento dei movimenti basato su AI',
@ -322,7 +322,7 @@ export const ui = {
'app.pictus.description': 'app.pictus.description':
"Générateur d'images IA créatif pour des images et œuvres d'art époustouflantes", "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.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", "Application de nutrition intelligente avec suivi photographique basé sur l'IA",
'app.traces.description': 'app.traces.description':
"Redécouvrez votre ville avec le suivi des déplacements basé sur l'IA", "Redécouvrez votre ville avec le suivi des déplacements basé sur l'IA",
@ -405,8 +405,7 @@ export const ui = {
'app.pictus.description': 'app.pictus.description':
'Generador de imágenes IA creativo para imágenes y obras de arte impresionantes', '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.orakel.description': 'Asistente de chat IA inteligente para todos los aspectos de la vida',
'app.nutriphi.description': 'app.food.description': 'App de nutrición inteligente con seguimiento fotográfico basado en IA',
'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', 'app.traces.description': 'Redescubre tu ciudad con seguimiento de movimiento basado en IA',
// Footer // Footer

View file

@ -56,7 +56,7 @@ const sections: Section[] = [
label: 'Alltag & Gesundheit', label: 'Alltag & Gesundheit',
apps: [ apps: [
{ name: 'ManaClock', icon: 'ph:clock-bold', tagline: 'Uhren & Timer', url: 'https://clock.mana.how' }, { 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' }, { name: 'Planta', icon: 'ph:plant-bold', tagline: 'Pflanzenpflege', url: 'https://planta.mana.how' },
], ],
}, },

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -604,12 +604,12 @@ registerApp({
}); });
registerApp({ registerApp({
id: 'nutriphi', id: 'food',
name: 'Nutriphi', name: 'Food',
color: '#22C55E', color: '#22C55E',
icon: ForkKnife, icon: ForkKnife,
views: { views: {
list: { load: () => import('$lib/modules/nutriphi/ListView.svelte') }, list: { load: () => import('$lib/modules/food/ListView.svelte') },
}, },
contextMenuActions: [ contextMenuActions: [
{ {
@ -618,7 +618,7 @@ registerApp({
icon: Plus, icon: Plus,
action: () => action: () =>
window.dispatchEvent( 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', drink: 'life',
meditate: 'life', meditate: 'life',
journal: 'life', journal: 'life',
nutriphi: 'life', food: 'life',
recipes: 'life', recipes: 'life',
plants: 'life', plants: 'life',
finance: 'life', finance: 'life',

View file

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

View file

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

View file

@ -122,7 +122,7 @@ export const mealReminderRule: PulseRule = {
body: 'Noch keine Mahlzeit heute erfasst.', body: 'Noch keine Mahlzeit heute erfasst.',
priority: 'low', priority: 'low',
actionLabel: 'Mahlzeit loggen', actionLabel: 'Mahlzeit loggen',
actionRoute: '/nutriphi', actionRoute: '/food',
}; };
} }
@ -135,7 +135,7 @@ export const mealReminderRule: PulseRule = {
body: `Erst ${meals} Mahlzeit(en) heute (${calories.actual} kcal).`, body: `Erst ${meals} Mahlzeit(en) heute (${calories.actual} kcal).`,
priority: 'low', priority: 'low',
actionLabel: 'Mahlzeit loggen', 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' }, zitare: { x: 640, y: 600, lakeId: 'db-center' },
music: { x: 850, y: 610, lakeId: 'db-center' }, music: { x: 850, y: 610, lakeId: 'db-center' },
clock: { x: 880, y: 680, 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) // Around Waldsee Ost (db-right)
photos: { x: 1110, y: 575, lakeId: 'db-right' }, photos: { x: 1110, y: 575, lakeId: 'db-right' },

View file

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

View file

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

View file

@ -29,7 +29,7 @@
redis: 'Schneller Cache-Speicher. Klein, kristallklar, sofort verfugbar.', redis: 'Schneller Cache-Speicher. Klein, kristallklar, sofort verfugbar.',
minio: 'Objekt-Speicher fur Dateien, Bilder und Medien aller Apps.', minio: 'Objekt-Speicher fur Dateien, Bilder und Medien aller Apps.',
'db-left': 'PostgreSQL-Datenbanken fur Calendar, Todo, Contacts, Storage.', '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.', '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** | | | **`answers`** | **`content`** | **7.2** |
| **uload** | **`links`** | **`title`, `description`** (`originalUrl` plaintext — Public Redirect) | **7.2** | | **uload** | **`links`** | **`title`, `description`** (`originalUrl` plaintext — Public Redirect) | **7.2** |
| **context** | **`documents`** | **`title`, `content`** | **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** | | **storage** | **`files`** | **`name`, `originalName`** (mimeType/size/path plaintext) | **8** |
| **picture** | **`images`** | **`prompt`, `negativePrompt`** (model/style/format plaintext) | **8** | | **picture** | **`images`** | **`prompt`, `negativePrompt`** (model/style/format plaintext) | **8** |
| **music** | **`songs`** | **`title`** (artist/album/genre plaintext für Browsing-Aggregation) | **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'] }, cycles: { enabled: true, fields: ['notes'] },
cycleDayLogs: { enabled: true, fields: ['notes', 'mood'] }, cycleDayLogs: { enabled: true, fields: ['notes', 'mood'] },
// ─── NutriPhi ──────────────────────────────────────────── // ─── Food ────────────────────────────────────────────
// LocalMeal user-typed / AI-generated content → encrypted: // LocalMeal user-typed / AI-generated content → encrypted:
// - description, portionSize: free-text, same sensitivity tier // - description, portionSize: free-text, same sensitivity tier
// - foods: AI-identified food items (array of {name, quantity, // - foods: AI-identified food items (array of {name, quantity,
@ -414,7 +414,7 @@ export const ENCRYPTION_REGISTRY: Record<string, EncryptionConfig> = {
// ─── Recipes ───────────────────────────────────────────── // ─── Recipes ─────────────────────────────────────────────
// User-typed content (title, description, ingredients list, steps) // User-typed content (title, description, ingredients list, steps)
// encrypted. `ingredients` is Ingredient[] and `steps` is string[] — // 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, // Plaintext (intentional): difficulty, tags, servings, times,
// isFavorite, photo refs — needed for indexing and filtering. // isFavorite, photo refs — needed for indexing and filtering.
recipes: { enabled: true, fields: ['title', 'description', 'ingredients', 'steps'] }, recipes: { enabled: true, fields: ['title', 'description', 'ingredients', 'steps'] },

View file

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

View file

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

View file

@ -155,7 +155,7 @@ describe('module-registry — pre-refactor snapshot', () => {
], ],
context: ['contextSpaces', 'documents', 'documentTags'], context: ['contextSpaces', 'documents', 'documentTags'],
questions: ['qCollections', 'questions', 'answers', 'questionTags'], questions: ['qCollections', 'questions', 'answers', 'questionTags'],
nutriphi: ['meals', 'goals', 'nutriFavorites', 'mealTags'], food: ['meals', 'goals', 'foodFavorites', 'mealTags'],
plants: ['plants', 'plantPhotos', 'wateringSchedules', 'wateringLogs', 'plantTags'], plants: ['plants', 'plantPhotos', 'wateringSchedules', 'wateringLogs', 'plantTags'],
uload: ['links', 'uloadTags', 'uloadFolders', 'linkTags'], uload: ['links', 'uloadTags', 'uloadFolders', 'linkTags'],
calc: ['calculations', 'savedFormulas'], calc: ['calculations', 'savedFormulas'],
@ -203,7 +203,7 @@ describe('module-registry — pre-refactor snapshot', () => {
timeWorldClocks: 'worldClocks', timeWorldClocks: 'worldClocks',
contextSpaces: 'spaces', contextSpaces: 'spaces',
qCollections: 'collections', qCollections: 'collections',
nutriFavorites: 'favorites', foodFavorites: 'favorites',
memoroSpaces: 'spaces', memoroSpaces: 'spaces',
uloadTags: 'tags', uloadTags: 'tags',
uloadFolders: 'folders', 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 { timesModuleConfig } from '$lib/modules/times/module.config';
import { contextModuleConfig } from '$lib/modules/context/module.config'; import { contextModuleConfig } from '$lib/modules/context/module.config';
import { questionsModuleConfig } from '$lib/modules/questions/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 { plantsModuleConfig } from '$lib/modules/plants/module.config';
import { uloadModuleConfig } from '$lib/modules/uload/module.config'; import { uloadModuleConfig } from '$lib/modules/uload/module.config';
import { calcModuleConfig } from '$lib/modules/calc/module.config'; import { calcModuleConfig } from '$lib/modules/calc/module.config';
@ -118,7 +118,7 @@ export const MODULE_CONFIGS: readonly ModuleConfig[] = [
timesModuleConfig, timesModuleConfig,
contextModuleConfig, contextModuleConfig,
questionsModuleConfig, questionsModuleConfig,
nutriphiModuleConfig, foodModuleConfig,
plantsModuleConfig, plantsModuleConfig,
uloadModuleConfig, uloadModuleConfig,
calcModuleConfig, calcModuleConfig,

View file

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

View file

@ -14,12 +14,12 @@ import { useLiveQueryWithDefault } from '@mana/local-store/svelte';
import { db } from '../database'; import { db } from '../database';
import { decryptRecords } from '../crypto'; import { decryptRecords } from '../crypto';
import { DEFAULT_DAILY_GOAL_ML } from '$lib/modules/drink/types'; 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 { trackingStore } from '$lib/modules/places/stores/tracking.svelte';
import type { LocalTask } from '$lib/modules/todo/types'; import type { LocalTask } from '$lib/modules/todo/types';
import type { LocalEvent } from '$lib/modules/calendar/types'; import type { LocalEvent } from '$lib/modules/calendar/types';
import type { LocalDrinkEntry } from '$lib/modules/drink/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 { LocalPlace } from '$lib/modules/places/types';
import type { LocalTimeBlock } from '../time-blocks/types'; import type { LocalTimeBlock } from '../time-blocks/types';
import type { DaySnapshot, TaskSummary, EventSummary } from './types'; import type { DaySnapshot, TaskSummary, EventSummary } from './types';
@ -54,7 +54,7 @@ async function buildSnapshot(): Promise<DaySnapshot> {
const todayEnd = `${today}T23:59:59`; const todayEnd = `${today}T23:59:59`;
// ── Parallel queries — all 5 modules at once ──── // ── 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<LocalTask>('tasks').toArray(),
db db
.table<LocalTimeBlock>('timeBlocks') .table<LocalTimeBlock>('timeBlocks')
@ -136,7 +136,7 @@ async function buildSnapshot(): Promise<DaySnapshot> {
totalProtein += n.protein ?? 0; 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 calorieGoal = activeGoal?.dailyCalories ?? DEFAULT_DAILY_VALUES.calories;
const proteinGoal = activeGoal?.dailyProtein; const proteinGoal = activeGoal?.dailyProtein;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -15,7 +15,7 @@
useAllBodyMeasurements, useAllBodyMeasurements,
useAllBodyChecks, useAllBodyChecks,
useAllBodyPhases, useAllBodyPhases,
useNutriphiMealsSince, useFoodMealsSince,
dateNDaysAgo, dateNDaysAgo,
getActiveWorkout, getActiveWorkout,
getActivePhase, getActivePhase,
@ -38,7 +38,7 @@
const measurementsQuery = useAllBodyMeasurements(); const measurementsQuery = useAllBodyMeasurements();
const checksQuery = useAllBodyChecks(); const checksQuery = useAllBodyChecks();
const phasesQuery = useAllBodyPhases(); const phasesQuery = useAllBodyPhases();
const mealsQuery = useNutriphiMealsSince(dateNDaysAgo(56)); const mealsQuery = useFoodMealsSince(dateNDaysAgo(56));
let exercises = $derived(exercisesQuery.value); let exercises = $derived(exercisesQuery.value);
let routines = $derived(routinesQuery.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 bodyweight (from `bodyMeasurements`) for the last N days. The
whole point of having both modules in the same app is being whole point of having both modules in the same app is being
able to ask "did the cut work?" without exporting CSVs. able to ask "did the cut work?" without exporting CSVs.
@ -22,7 +22,7 @@
--> -->
<script lang="ts"> <script lang="ts">
import type { BodyMeasurement, BodyPhase } from '../types'; import type { BodyMeasurement, BodyPhase } from '../types';
import type { MealWithNutrition } from '$lib/modules/nutriphi/types'; import type { MealWithNutrition } from '$lib/modules/food/types';
interface Props { interface Props {
measurements: BodyMeasurement[]; measurements: BodyMeasurement[];

View file

@ -17,7 +17,7 @@ import type {
BodyCheck, BodyCheck,
BodyPhase, BodyPhase,
} from './types'; } 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 bodyExercisesCtx = createModuleContext<BodyExercise[]>('bodyExercises');
export const bodyRoutinesCtx = createModuleContext<BodyRoutine[]>('bodyRoutines'); export const bodyRoutinesCtx = createModuleContext<BodyRoutine[]>('bodyRoutines');
@ -26,4 +26,4 @@ export const bodySetsCtx = createModuleContext<BodySet[]>('bodySets');
export const bodyMeasurementsCtx = createModuleContext<BodyMeasurement[]>('bodyMeasurements'); export const bodyMeasurementsCtx = createModuleContext<BodyMeasurement[]>('bodyMeasurements');
export const bodyChecksCtx = createModuleContext<BodyCheck[]>('bodyChecks'); export const bodyChecksCtx = createModuleContext<BodyCheck[]>('bodyChecks');
export const bodyPhasesCtx = createModuleContext<BodyPhase[]>('bodyPhases'); 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 { useLiveQueryWithDefault } from '@mana/local-store/svelte';
import { decryptRecords } from '$lib/data/crypto'; import { decryptRecords } from '$lib/data/crypto';
import { db } from '$lib/data/database'; 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 { import type {
LocalBodyExercise, LocalBodyExercise,
LocalBodyRoutine, 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 * weight correlation chart. Lives here (instead of consumers calling
* nutriphi/queries directly) because the body module owns the Body × * food/queries directly) because the body module owns the Body ×
* Nutriphi integration boundary, and putting the cross-table read in * Food integration boundary, and putting the cross-table read in
* one place keeps the import graph from getting circular if nutriphi * one place keeps the import graph from getting circular if food
* ever wants to reach back the other way. * ever wants to reach back the other way.
* *
* Returns a thinned MealWithNutrition shape only the fields the * 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 * `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. * 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 () => { return useLiveQueryWithDefault(async () => {
const locals = await db.table<LocalMeal>('meals').where('date').aboveOrEqual(since).toArray(); const locals = await db.table<LocalMeal>('meals').where('date').aboveOrEqual(since).toArray();
const visible = locals.filter((m) => !m.deletedAt); const visible = locals.filter((m) => !m.deletedAt);

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