mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:41:09 +02:00
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:
parent
f5cb833b04
commit
53b3746b98
196 changed files with 863 additions and 719 deletions
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 |
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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 |
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 ───────────────────────────
|
||||||
|
|
|
||||||
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
|
|
@ -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
|
||||||
|
|
|
||||||
56
.github/workflows/ci.yml
vendored
56
.github/workflows/ci.yml
vendored
|
|
@ -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 }}
|
||||||
|
|
|
||||||
|
|
@ -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 |
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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 };
|
||||||
|
|
@ -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 } },
|
||||||
|
|
|
||||||
|
|
@ -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
17
apps/food/CLAUDE.md
Normal 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.
|
||||||
|
|
@ -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',
|
||||||
});
|
});
|
||||||
|
|
@ -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",
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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
24
apps/food/package.json
Normal 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"
|
||||||
|
}
|
||||||
|
|
@ -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",
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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 │ │
|
||||||
└────────────────────────────────────────────────────────────┘
|
└────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -562,7 +562,7 @@ 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 |
|
||||||
|
|
@ -570,7 +570,7 @@ apps/calendar/apps/web/src/lib/services/
|
||||||
| 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 |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
@ -642,8 +642,8 @@ 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 |
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 |
|
||||||
|
|
@ -383,11 +383,11 @@ 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 |
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 |
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 |
|
||||||
|
|
|
||||||
|
|
@ -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 |
|
||||||
|
|
|
||||||
|
|
@ -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) |
|
||||||
|
|
|
||||||
|
|
@ -202,8 +202,8 @@ 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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 |
|
||||||
| ... | ... | ... |
|
| ... | ... | ... |
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ 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, …) |
|
||||||
|
|
@ -114,10 +114,10 @@ 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 |
|
||||||
|
|
@ -170,7 +170,7 @@ 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) |
|
||||||
|
|
@ -274,7 +274,7 @@ 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) |
|
||||||
|
|
@ -290,11 +290,11 @@ 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.
|
||||||
|
|
||||||
|
|
@ -307,11 +307,11 @@ 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 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -331,7 +331,7 @@ 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 |
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
@ -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 |
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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' } })
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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' },
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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'),
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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' },
|
||||||
|
|
|
||||||
|
|
@ -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: {
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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.',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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** |
|
||||||
|
|
|
||||||
|
|
@ -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'] },
|
||||||
|
|
|
||||||
|
|
@ -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') ───
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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'),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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'],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"app": {
|
"app": {
|
||||||
"name": "NutriPhi",
|
"name": "Food",
|
||||||
"loading": "Laden...",
|
"loading": "Laden...",
|
||||||
"tagline": "Ernährung verstehen"
|
"tagline": "Ernährung verstehen"
|
||||||
},
|
},
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"app": {
|
"app": {
|
||||||
"name": "NutriPhi",
|
"name": "Food",
|
||||||
"loading": "Loading...",
|
"loading": "Loading...",
|
||||||
"tagline": "Understand nutrition"
|
"tagline": "Understand nutrition"
|
||||||
},
|
},
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"app": {
|
"app": {
|
||||||
"name": "NutriPhi",
|
"name": "Food",
|
||||||
"loading": "Cargando...",
|
"loading": "Cargando...",
|
||||||
"tagline": "Entiende la nutrición"
|
"tagline": "Entiende la nutrición"
|
||||||
},
|
},
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"app": {
|
"app": {
|
||||||
"name": "NutriPhi",
|
"name": "Food",
|
||||||
"loading": "Chargement...",
|
"loading": "Chargement...",
|
||||||
"tagline": "Comprendre la nutrition"
|
"tagline": "Comprendre la nutrition"
|
||||||
},
|
},
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"app": {
|
"app": {
|
||||||
"name": "NutriPhi",
|
"name": "Food",
|
||||||
"loading": "Caricamento...",
|
"loading": "Caricamento...",
|
||||||
"tagline": "Comprendi la nutrizione"
|
"tagline": "Comprendi la nutrizione"
|
||||||
},
|
},
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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[];
|
||||||
|
|
|
||||||
|
|
@ -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');
|
||||||
|
|
|
||||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue