Skip to content

cmadzz/cegin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

106 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🍳 Cegin

Your personal AI-powered recipe companion

License: GPL-3.0 Docker Image GitHub Release Node.js Expo GitHub Stars

cegin.kitchen Β· Documentation Β· Report a Bug


Cegin is a self-hosted recipe management app with an AI cooking assistant named Chef Terry. Store and organize your recipes, plan weekly meals, generate smart shopping lists, and get real-time cooking help β€” all running on your own hardware with no cloud dependency.

Recipe Library Chef Terry Chat Meal Planner Cook Mode

Recipe Detail Mid-Cook Fix Shopping List Terry Vision

Chef Terry Home Vision Recipe Kitchen Log

✨ Features

  • Recipe Management β€” store, search, import from any URL, and organize recipes into collections
  • Smart Meal Planning β€” AI-powered weekly meal plans based on your saved recipes and dietary needs
  • Shopping Lists β€” auto-consolidate ingredients from multiple recipes, check items off as you shop
  • Chef Terry β€” context-aware AI assistant that knows your recipes, pantry, and cooking history
  • Mid-Cook Panic Fix β€” tell Terry what went wrong and get instant recovery suggestions
  • Terry Vision β€” scan your fridge/pantry with your camera, get recipe suggestions from what you have
  • Cook Mode β€” step-by-step cooking with built-in timers and keep-awake
  • USDA Nutrition β€” look up nutritional data from the USDA database
  • Allergen Flags β€” audit recipes against dietary profiles and allergen restrictions
  • Push Notifications β€” morning meal prep reminders and perishable ingredient alerts
  • Offline-First β€” works in local mode with zero server, or syncs with a self-hosted backend
  • Multi-Device Sync β€” real-time WebSocket sync between all your devices
  • Multi-Image Recipes β€” attach multiple photos to any recipe
  • Kitchen Log β€” track your cooking history, streaks, and top recipes

πŸ—οΈ Tech Stack

Layer Technology
Server Node.js, Express 5, better-sqlite3, WebSocket
Mobile React Native, Expo SDK 56
AI (text) OpenAI-compatible API (DeepSeek, Groq, OpenAI, OpenRouter, Ollama)
AI (vision) Gemini Vision (fridge scanning, photo import)
Auth JWT (bcryptjs password hashing)
Images sharp (on-the-fly resizing, JPEG optimisation)
Deployment Docker (~100 MB image), Docker Compose secrets
Security Helmet, rate limiting, SSRF protection, per-user data scoping

πŸš€ Quick Start

Option 1: Docker (recommended)

cd server
cp .env.example .env
# Edit .env β€” set your provider type, base URL, and model name

Set up secrets (API keys and JWT secret β€” never in .env):

mkdir -p secrets && chmod 700 secrets
echo "sk-your-text-key"        > secrets/TEXT_API_KEY
echo "AIza-your-vision-key"    > secrets/VISION_API_KEY
echo "your-jwt-secret"         > secrets/JWT_SECRET
chmod 600 secrets/*

Start the server:

docker compose up -d --build

The server will be available at http://YOUR_LAN_IP:3000 (binds to 0.0.0.0).

Minimum .env for AI features:

TEXT_PROVIDER=openai-compatible
TEXT_BASE_URL=https://api.deepseek.com/v1
TEXT_MODEL=deepseek-chat

Note: The API key goes in secrets/TEXT_API_KEY, not in .env.

Optional β€” vision (fridge scanning, photo import):

VISION_PROVIDER=gemini
VISION_MODEL=gemini-2.5-flash

Note: Vision key goes in secrets/VISION_API_KEY.

Option 2: Local Development (no Docker)

# Server
cd server
npm install
node index.js

# Mobile (in a separate terminal)
cd mobile
npm install
npx expo start

Scan the QR code in Expo Go for quick testing. For push notifications and full native features, build a dev client or APK:

npx expo run:android     # Build and run on connected device
EXPO_GO=1 npx expo start # Expo Go mode (blocks expo-notifications)

Important: Phone and server must be on the same Wi-Fi. The phone talks directly to your Docker container over LAN. No cloud.

πŸ“– API Documentation

Full REST API documentation is available in docs/API.md.

Quick reference:

Base URL http://YOUR_LAN_IP:3000/api
Auth JWT Bearer token in Authorization header
Health check GET /api/health (no auth required)
AI status GET /api/ai/status (no auth required)

πŸ›οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Mobile App                           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Screens  β”‚  β”‚  Offline β”‚  β”‚  Local   β”‚  β”‚  Push    β”‚   β”‚
β”‚  β”‚  (RN)     β”‚  β”‚  Cache   β”‚  β”‚  AI      β”‚  β”‚  Notifs  β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜   β”‚
β”‚        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
β”‚                          β”‚  HTTP / WebSocket                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Server (Docker)                           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Express  β”‚  β”‚  SQLite  β”‚  β”‚  AI      β”‚  β”‚  Cron    β”‚   β”‚
β”‚  β”‚  API      β”‚  β”‚  (WAL)   β”‚  β”‚  Bridge  β”‚  β”‚  Jobs    β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜   β”‚
β”‚        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
β”‚                          β”‚                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”‚
β”‚  β”‚  Sharp    β”‚  β”‚  Helmet  β”‚  β”‚  JWT     β”‚                   β”‚
β”‚  β”‚  (images) β”‚  β”‚  (sec)   β”‚  β”‚  (auth)  β”‚                   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚
               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
               β”‚    AI Providers       β”‚
               β”‚  DeepSeek β”‚ Gemini    β”‚
               β”‚  Groq     β”‚ Ollama    β”‚
               β”‚  OpenAI   β”‚ OpenRouterβ”‚
               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Two Modes

Server Mode Local Mode
Storage SQLite on server (Docker volume) SQLite on phone
AI Server-side via configured provider Direct device-to-provider
Sync Multi-device via WebSocket Single device
Auth JWT login required None
Push βœ… (native builds) ❌

Switch modes anytime from Settings.

πŸ€– Chef Terry

Terry is a context-aware AI cooking assistant with personality. He knows your recipes, meal plan, shopping list, dietary profiles, and cooking history.

  • Chat β€” ask about recipes, get suggestions, convert units, troubleshoot cooking problems
  • Mid-cook panic β€” "Something went wrong at step 3" and Terry recalculates on the fly
  • Meal planning β€” AI-powered weekly meal plans based on your saved recipes and dietary needs
  • Terry Vision β€” snap a photo of your fridge, Terry identifies ingredients and suggests recipes
  • Recipe generation β€” describe what you want and Terry creates a structured recipe
  • URL import β€” paste a recipe URL and Terry extracts and formats it

AI Providers

You're not locked into any provider. Change TEXT_BASE_URL and TEXT_MODEL in .env:

Provider Base URL Example Model
DeepSeek https://api.deepseek.com/v1 deepseek-chat
Groq https://api.groq.com/openai/v1 llama-3.1-70b-versatile
OpenAI https://api.openai.com/v1 gpt-4o-mini
OpenRouter https://openrouter.ai/api/v1 anthropic/claude-sonnet-4
Ollama (local) http://host.docker.internal:11434/v1 llama3.1
  • Vision can be configured independently (e.g. Gemini for vision, local model for chat)
  • The mobile app also supports Custom AI Providers (Settings β†’ AI PROVIDERS) for direct device-to-provider calls

Push Notifications (native builds)

  • Morning Digest β€” 8:00 AM, Terry tells you what's for dinner and what to prep
  • Perishable Alerts β€” every 6 hours, warns about expiring scanned items

πŸ”’ Security

Server (Docker)

  • API keys and JWT secret stored as Docker Compose secrets β€” mounted at /run/secrets/
  • Never visible via docker inspect, docker exec env, or image layers
  • secrets/ is in .gitignore and .dockerignore
  • Container runs as non-root user
  • Resource limits: 512 MB RAM, 1 CPU
  • Rate limiting on auth (10/min) and AI routes (60/min)
  • SSRF protection on image proxy (blocks private IPs)
  • Helmet security headers
  • Per-user data scoping on all endpoints

Mobile (Local Mode)

  • API keys in expo-secure-store (Android Keystore)
  • Hardware-backed AES-256 encryption at rest
  • In Expo Go, falls back to AsyncStorage (unencrypted)

πŸ’Ύ Backups & Data

Recipes are in a plain SQLite file on a Docker volume.

# Backup
docker run --rm -v cegin-data:/data -v "$PWD":/backup \
  alpine cp /data/recipes.db /backup/recipes.db.bak

# Restore β€” reverse the cp direction
  • Local mode: data lives in the phone's SQLite (backed up with normal phone backups).

πŸ“ Project Structure

cegin/
β”œβ”€β”€ server/
β”‚   β”œβ”€β”€ Dockerfile
β”‚   β”œβ”€β”€ docker-compose.yml
β”‚   β”œβ”€β”€ .env.example
β”‚   β”œβ”€β”€ index.js          # Express API (routes, auth, endpoints)
β”‚   β”œβ”€β”€ db.js             # SQLite schema + CRUD (recipes, meals, scans, tokens)
β”‚   β”œβ”€β”€ ai.js             # AI provider integration (DeepSeek, Gemini, etc.)
β”‚   β”œβ”€β”€ auth.js           # JWT auth + password hashing
β”‚   β”œβ”€β”€ notifications.js  # Expo Push notification sender
β”‚   β”œβ”€β”€ cron.js           # Scheduled jobs (morning digest, perishable alerts)
β”‚   └── secrets.js        # Secret loading (Docker secrets > ./secrets/ > env vars)
β”œβ”€β”€ mobile/
β”‚   β”œβ”€β”€ App.js
β”‚   └── src/
β”‚       β”œβ”€β”€ api.js              # Server API client + offline cache
β”‚       β”œβ”€β”€ mealPlan.js         # Meal planner (syncs to server)
β”‚       β”œβ”€β”€ notifications.js    # Push notification registration
β”‚       β”œβ”€β”€ offlineCache.js     # Offline-first recipe cache
β”‚       β”œβ”€β”€ localAi.js          # Local mode AI providers
β”‚       β”œβ”€β”€ usdaNutrition.js    # USDA nutrition database
β”‚       β”œβ”€β”€ config.js           # Key storage (secure store)
β”‚       └── screens/
β”‚           β”œβ”€β”€ AssistantScreen.js    # Chef Terry chat
β”‚           β”œβ”€β”€ TerryVisionScreen.js  # Fridge scanning
β”‚           β”œβ”€β”€ MealPlannerScreen.js  # Weekly meal planning
β”‚           β”œβ”€β”€ CookModeScreen.js     # Step-by-step cooking
β”‚           β”œβ”€β”€ ShoppingListScreen.js
β”‚           β”œβ”€β”€ RecipeListScreen.js
β”‚           β”œβ”€β”€ RecipeDetailScreen.js
β”‚           β”œβ”€β”€ EditRecipeScreen.js
β”‚           β”œβ”€β”€ SettingsScreen.js
β”‚           β”œβ”€β”€ CookbookScreen.js
β”‚           β”œβ”€β”€ StatsScreen.js
β”‚           └── SetupScreen.js
β”œβ”€β”€ docs/                 # cegin.kitchen landing page (GitHub Pages)
β”œβ”€β”€ docs/API.md           # REST API documentation
β”œβ”€β”€ LICENSE
└── README.md

πŸ› οΈ Development

Server (Docker β€” recommended)

cd server
docker compose up --build

Server (without Docker)

cd server
npm install
node index.js

Mobile

cd mobile
npx expo start           # Expo Go for quick dev testing
npx expo run:android     # Build and run on connected device

Push notifications require a native build β€” they don't work in Expo Go. Start Metro for Expo Go with:

EXPO_GO=1 npx expo start

(This blocks expo-notifications from the bundle to prevent SDK 53+ crashes.)

πŸ› Troubleshooting

Problem Solution
Can't reach server from phone Use the machine's LAN IP, not localhost. Check firewall.
AI not working Check TEXT_* / VISION_* in .env and that secrets/ files exist. Test at /api/health and /api/ai/status.
Database disappears Make sure the cegin-data Docker volume exists.
Secrets not loading Check ls -la secrets/ β€” files need mode 600.
After changing .env or Dockerfile Use docker compose up -d --build.
better-sqlite3 build errors docker compose build --no-cache.

🀝 Contributing

Contributions are welcome! Here's how to get started:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Guidelines

  • Follow existing code style and conventions
  • Test your changes locally before submitting
  • Keep PRs focused β€” one feature or fix per PR
  • Update documentation if you change public APIs
  • All contributions are licensed under GPL-3.0

πŸ“„ License

This project is licensed under the GNU General Public License v3.0 β€” see the LICENSE file for details.


Enjoy cooking with Terry. 🐱

About

🐱 A self-hosted recipe app with an AI cooking assistant named Chef Terry. Plan meals, scan your fridge, get push notifications, and cook with personality.

Resources

License

Stars

1 star

Watchers

1 watching

Forks

Packages

 
 
 

Contributors