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 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
| 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 |
cd server
cp .env.example .env
# Edit .env β set your provider type, base URL, and model nameSet 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 --buildThe server will be available at http://YOUR_LAN_IP:3000 (binds to 0.0.0.0).
TEXT_PROVIDER=openai-compatible
TEXT_BASE_URL=https://api.deepseek.com/v1
TEXT_MODEL=deepseek-chatNote: The API key goes in
secrets/TEXT_API_KEY, not in.env.
VISION_PROVIDER=gemini
VISION_MODEL=gemini-2.5-flashNote: Vision key goes in
secrets/VISION_API_KEY.
# Server
cd server
npm install
node index.js
# Mobile (in a separate terminal)
cd mobile
npm install
npx expo startScan 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.
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) |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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β
βββββββββββββββββββββββββ
| 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.
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
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
- 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
- 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.gitignoreand.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
- API keys in
expo-secure-store(Android Keystore) - Hardware-backed AES-256 encryption at rest
- In Expo Go, falls back to AsyncStorage (unencrypted)
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).
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
cd server
docker compose up --buildcd server
npm install
node index.jscd mobile
npx expo start # Expo Go for quick dev testing
npx expo run:android # Build and run on connected devicePush 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.)
| 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. |
Contributions are welcome! Here's how to get started:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- 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
This project is licensed under the GNU General Public License v3.0 β see the LICENSE file for details.
Enjoy cooking with Terry. π±










