refactor: rename nutriphi module to food (Essen)

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

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

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

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

View file

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

View file

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