dadaloop82 42149012a1 chore: remove deprecated scale-gateway app
The BLE scale gateway is fully integrated into the EverShelf Kiosk app
since v1.6.0. This standalone Android app is no longer needed or maintained.

Removal also resolves GitHub secret scanning alert #1 (legacy plain-text
GitHub PAT in ErrorReporter.kt — already revoked by GitHub automatically).
2026-05-16 08:35:36 +00:00
2026-04-10 05:24:27 +00:00

🏠 EverShelf

Self-hosted pantry management system — Track your food inventory, scan barcodes, get AI-powered recipe suggestions, and reduce waste.


🚀 Try the live demo — no installation required!

▶ Open Live Demo  ·  🌐 Project Website  ·  📖 Wiki

The demo runs with mock pantry data. AI features are fully enabled. All write operations are safely sandboxed.


License: MIT PHP SQLite Docker i18n Version GitHub stars Last commit Contributors GitHub Discussions CI


Features

📦 Inventory Management

  • Barcode scanning — Scan products with your phone camera using QuaggaJS
  • AI identification — Take a photo and let Google Gemini identify the product, with suggestions from your existing inventory; gracefully shows a friendly message when AI quota is exhausted instead of a raw API error
  • Smart locations — Track items across Pantry, Fridge, Freezer, and custom locations
  • Expiry tracking — Automatic shelf-life estimation based on product type and storage
  • Opened product tracking — Reduced shelf-life calculation when packages are opened; opened-product expiry is now also checked when building banner alerts (not just the dashboard section)
  • Vacuum-sealed support — Extended expiry dates for vacuum-sealed items
  • Anomaly detection — Banner alerts for suspicious quantities and consumption predictions with inline correction; dismiss button now shows the current inventory quantity so the action is unambiguous ("La quantità è giusta (2 pz)")

🤖 AI-Powered (Google Gemini)

  • Expiry date reading — Photograph a label and extract the expiry date automatically
  • Product identification — Point your camera at any product for instant recognition
  • Existing product matching — AI scan shows matching products already in your pantry before suggesting new ones
  • Storage & shelf-life hint — When adding a new product, Gemini suggests the optimal storage location and shelf-life in the background; shown as an inline AI badge next to the expiry estimate
  • Recipe generation — Get personalized recipes based on what's in your pantry; streams live via Server-Sent Events so results appear as they are generated
  • Smart chat assistant — Ask questions about your inventory, get cooking tips
  • Shopping suggestions with tips — AI-powered purchase recommendations, each enriched with a short practical buying/storing tip
  • Anomaly explanation — "🤖 Spiega" button on anomaly banners explains in plain language why a discrepancy likely occurred and what to do
  • Model fallback — All AI endpoints try gemini-2.5-flash first and fall back to gemini-2.0-flash automatically
  • Graceful no-key state — When no Gemini key is configured, AI entry points show a friendly message; the header button is visually greyed with an amber dot

🛒 Shopping List

  • Bring! integration — Sync with the Bring! shopping list app
  • Generic shopping names — Products are grouped by type ("Latte", "Affettato", "Panna da cucina") rather than brand, keeping the Bring! list clean and consolidated
  • Smart predictions — Know what you'll need before you run out
  • Auto-add on depletion — When a product reaches zero the app adds it to Bring! automatically, no confirmation needed
  • Auto-remove on scan — Products are removed from the shopping list when scanned in - Auto-migration — Items already on the Bring! list are silently renamed to their generic name in the background (throttled, runs on list load)
    • Catalog coverage — All product types resolve to a German Bring! catalog key for icon and category display in the Bring! app

🍳 Cooking Mode

  • Step-by-step guidance — Follow recipes with a hands-free cooking interface
  • Text-to-Speech — Voice readout of recipe steps; supports browser Web Speech API, native Android TTS (kiosk), or a custom REST endpoint (Home Assistant, etc.); retries voice loading for up to 10 seconds with a fallback refresh button; TTS activates automatically without requiring the global TTS setting to be enabled
  • Auto-read on navigate — Each step is read aloud automatically when you tap Next or Previous; the first step is read when entering cooking mode
  • Timer voice alerts — 10-second countdown warning spoken aloud before each timer expires; expiry announced vocally when time is up
  • Recipe completion — "Buon appetito!" spoken when the last step is confirmed
  • Built-in timer — Automatic timer suggestions based on recipe instructions
  • Ingredient tracking — Mark ingredients as used during cooking; leftover quantities prompt a "move to another location" flow

📊 Dashboard

  • Waste tracking — Monitor consumed vs. wasted products over 30 days
  • Anti-waste report — Personalised waste rate vs. national average with annual kg estimate; shown above the expiring-items list
  • Expiry alerts — Visual warnings for expired and soon-to-expire items
  • Opened products panel — Tracks partially-used items; expiry is recalculated from the opening date using AI (Gemini) + per-category rule fallback; whole sealed packages always keep their original manufacturer expiry; conf items with mixed whole + fractional units are shown as two separate entries
  • Freezer shelf-life — Granular per-product estimates (USDA/EFSA): fish 120 d, poultry 270 d, whole red-meat cuts 365 d, mince 120 d, vegetables/fruit 270 d, generic 180 d; AI + cache still take priority over rules
  • Safety ratings — Smart assessment of expired product safety (by category and location); expired unsafe items shown with a red danger banner and "L'ho buttato" as the primary action
  • Expired product banner — Products that have passed their effective shelf-life (including opened-product reduced expiry) appear in the top notification banner; icon, colour and title adapt to the actual safety level ( green for safe, 👀 amber to check, 🚫 red for danger); high-risk items get a prominent discard action
  • Quick recipe bar — One-tap recipe suggestion using expiring products
  • Anomaly banner — Scrollable banner with suspicious quantities and consumption prediction mismatches, with one-tap correction or inline edit
  • Expired/expiring alerts — Priority-sorted banner notifications for expired and soon-to-expire products with use, throw, edit, and dismiss actions
  • Swipe navigation — Touch swipe or tap arrows/dots to browse banner notifications
  • Quick-access buttons — Recently used and most popular products shown on the inventory page for fast access

📱 Progressive Web App

  • Mobile-first design — Optimized for phones, works on tablets and desktop
  • Installable — Add to home screen for a native app experience
  • Multi-device — Settings and data sync across devices on the same server

⚖️ Smart Scale Integration (Add-on)

  • Bluetooth gateway — Connects a BLE smart scale to EverShelf via local WebSocket
  • SSE relay — Server-side relay avoids mixed-content (HTTPS→WS) issues
  • Auto-discovery — Server scans LAN to find the gateway automatically
  • Auto weight reading — When adding/using a product with unit g/ml, weight fills automatically
  • 10g threshold — Ignores readings that haven't changed enough between products - Duplicate-reading prevention — Server-side 12-second dedup window rejects a second scale-triggered deduction of the same product, guarding against BLE multi-fire- ml conversion hint — Shows "weight in grams → will be converted to ml" when product unit is ml
  • Stability + auto-confirm — 10s stable wait + 5s countdown before confirming
  • Real-time status — Scale connection indicator always visible in the header
  • Multi-protocol — Supports Bluetooth SIG Weight Scale, Body Composition, Xiaomi Mi Scale 2 and 100+ models
  • Built into kiosk (v1.6.0+) — BLE gateway runs as an integrated foreground service inside the EverShelf Kiosk app; no separate APK needed. The standalone gateway app in evershelf-scale-gateway/ is deprecated but kept for non-kiosk use cases.

📺 Android Kiosk Mode (Add-on)

  • Dedicated tablet app — Full-screen WebView wrapper for wall-mounted kitchen tablets
  • True kiosk lock — Screen pinning blocks home/recent buttons
  • Setup wizard — 6-step guided configuration (language, welcome, permissions, server URL, BLE scale scan, screensaver, summary)
  • Smart auto-discovery — Scans the LAN in parallel (60 threads, TCP pre-check, ports 80/443/8080/8443) with real-time UI feedback; correctly identifies the device's Wi-Fi/Ethernet subnet (VPN and cellular interfaces are filtered out)
  • Built-in BLE scale gatewayGatewayService foreground service; BLE scanning + WebSocket server :8765 run directly inside the kiosk app. Select your scale in step 5 of the wizard — no external app required
  • Scale auto-configuration — After selecting the BLE device, the wizard writes scale_enabled and scale_gateway_url=ws://127.0.0.1:8765 to the server automatically
  • Camera & mic permissions — Full hardware access for barcode scanning and voice; grant button transforms to a green confirmation after granting
  • Native TTS bridge — Cooking mode voice readout uses the Android TextToSpeech engine directly, bypassing Web Speech API voice limitations; no offline voice packs required
  • Hard refresh — ↻ button clears WebView cache to pick up web app updates
  • Update notifications — Checks GitHub releases every 6h, shows banner when updates available
  • SSL support — Accepts self-signed certificates
  • Android kiosk appevershelf-kiosk/ — downloadable APK

🚀 Quick Start

Prerequisites

  • Web server with PHP 8.0+ (Apache or Nginx)
  • PHP extensions: pdo_sqlite, curl, mbstring, json
  • HTTPS recommended (required for camera access on mobile)

Installation

# 1. Clone the repository
git clone https://github.com/dadaloop82/EverShelf.git
cd EverShelf

# 2. Create configuration file
cp .env.example .env
nano .env

# 3. Start with Docker Compose
docker compose up -d

# → Open http://localhost:8080

Option B: Manual

# 1. Clone the repository
git clone https://github.com/dadaloop82/EverShelf.git
cd EverShelf

# 2. Create configuration file
cp .env.example .env

# 3. Set permissions
chmod 755 data/
chmod 664 data/.gitkeep
chown -R www-data:www-data data/

# 4. Edit your configuration
nano .env

Configuration (.env)

# Required for AI features (get a key at https://aistudio.google.com/app/apikey)
GEMINI_API_KEY=your_api_key_here

# Optional: Bring! shopping list integration
BRING_EMAIL=your_email@example.com
BRING_PASSWORD=your_password

# Optional: Text-to-Speech for cooking mode
TTS_URL=http://your-home-assistant:8123/api/events/tts_speak
TTS_TOKEN=your_long_lived_token
TTS_ENABLED=true

# Optional: Security — protect the save_settings endpoint
# Set a strong random string; the Settings UI will ask for it before saving
SETTINGS_TOKEN=

# Optional: Demo mode — block all write operations at the router level
DEMO_MODE=false

Web Server Configuration

Apache (.htaccess)

The app works out of the box with Apache if placed in the web root or a subdirectory. Make sure mod_rewrite is enabled and AllowOverride All is set.

<Directory /var/www/html/evershelf>
    AllowOverride All
    Require all granted
</Directory>
Nginx
server {
    listen 80;
    server_name your-server.local;
    root /var/www/html/evershelf;
    index index.html;

    location /api/ {
        try_files $uri $uri/ =404;
        location ~ \.php$ {
            fastcgi_pass unix:/run/php/php8.2-fpm.sock;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
    }

    # Deny access to sensitive files
    location ~ /\.env { deny all; }
    location ~ /data/ { deny all; }
    location ~ /backup\.sh { deny all; }
}

Camera access requires HTTPS on most mobile browsers. Options:

  • Let's Encrypt with Certbot (for public-facing servers)
  • Self-signed certificate (for local network only)
  • Reverse proxy (e.g., Caddy, Traefik) with automatic TLS

Cron Job (Optional)

Set up a cron job for smart shopping predictions:

# Run every 5 minutes
*/5 * * * * php /path/to/evershelf/api/cron_smart_shopping.php >> /path/to/evershelf/data/cron.log 2>&1

Backup (Optional)

The included backup.sh creates local daily backups of your database:

# Run daily at 3 AM
0 3 * * * /path/to/evershelf/backup.sh

🏗️ Architecture

evershelf/
├── index.html              # Single-page application (SPA)
├── manifest.json           # PWA manifest
├── .env.example            # Configuration template
├── backup.sh               # Local database backup script
├── LICENSE                 # MIT License
│
├── api/
│   ├── index.php           # Main API router (all endpoints)
│   ├── database.php        # SQLite schema, migrations, helpers
│   └── cron_smart_shopping.php  # Background job for predictions
│
├── assets/
│   ├── css/style.css       # All application styles
│   ├── js/app.js           # All application logic
│   └── img/                # Static images
│
└── data/                   # Runtime data (gitignored)
    ├── evershelf.db         # SQLite database (auto-created)
    ├── backups/            # Local DB backups
    └── *.json              # Token/cache files

evershelf-scale-gateway/    # ⚖️ Android BLE gateway [DEPRECATED — integrated into kiosk v1.6.0+]
    ├── README.md           # Deprecation notice + legacy docs
    └── app/src/            # Kotlin Android source (WebSocket + BLE)

evershelf-kiosk/            # 📺 Android kiosk app (add-on)
    ├── README.md           # Setup & feature docs
    └── app/src/            # Kotlin Android source (WebView wrapper)

API Endpoints

Category Action Method Description
Products search_barcode GET Find product by barcode
lookup_barcode GET Look up barcode on Open Food Facts
product_save POST Create or update a product
products_list GET List all products
Inventory inventory_list GET List inventory items
inventory_add POST Add product to inventory
inventory_use POST Use/consume from inventory
inventory_summary GET Count by location
AI gemini_identify POST Identify product from photo
gemini_expiry POST Read expiry date from photo
gemini_chat POST Chat with AI assistant
generate_recipe POST Generate recipe from inventory
gemini_product_hint POST Storage location + shelf-life hint
gemini_shopping_enrich POST Enrich shopping suggestions with tips
gemini_anomaly_explain POST Plain-language anomaly explanation
Shopping bring_list GET Get Bring! shopping list
bring_add POST Add items to Bring!
smart_shopping GET Smart shopping predictions
Settings get_settings GET Get server configuration
save_settings POST Update server configuration

🔒 Security Notes

  • Credentials are stored in .env (server-side, never committed to Git)
  • Database stays local — never pushed to remote repositories
  • API keys are never exposed to the browserget_settings returns only boolean flags (gemini_key_set, settings_token_set), never raw key values
  • Settings write protection — set SETTINGS_TOKEN in .env to require a secret token (X-Settings-Token header) for all save_settings calls; validated with hash_equals to prevent timing attacks
  • Demo / public mode — set DEMO_MODE=true to block all write operations at the PHP router level before any business logic runs
  • The API uses parameterized SQL queries (PDO prepared statements) against injection
  • Input validation on all inventory operations (quantity bounds, location whitelist)
  • Consider adding reverse-proxy authentication (e.g. Authelia, Nginx auth_basic) if the server is accessible from the internet

🛠️ Development

# Run PHP's built-in server for local development
php -S localhost:8080 -t /path/to/evershelf

# Check PHP syntax
php -l api/index.php
php -l api/database.php

The application uses no build tools — edit files directly and refresh.


📋 Roadmap

High Priority

  • Cooking mode — 3D wheel JS — swipe navigation, gyroscope tilt, haptic feedback
  • Cooking mode — step timers — auto-detect "X minutes" in recipe steps, countdown + alert
  • Push notifications — daily expiry alerts via PWA Service Worker + VAPID
  • Quick search / quick-add bar — always-visible search above the nav, PWA shortcuts

Medium Priority

  • Receipt OCR → bulk add — photo of receipt → Gemini Vision → auto-fill inventory
  • CSV/JSON export & import — download/upload inventory from Settings
  • Custom storage locations — user-defined locations beyond Fridge/Freezer/Pantry
  • Multi-user support — PIN-based user distinction, action log with user label
  • AI optimal purchase prediction — suggest "buy X units of Y within Z days"
  • Price history sparklines — per-product price chart from the AI cache data

Low Priority / Nice to Have

  • Dark mode — CSS custom properties are already structured to support it
  • Full offline mode — Service Worker cache to show inventory read-only when server is down
  • French & Spanish translations (fr.json, es.json)
  • Swipe actions on inventory rows — swipe left to use/discard, right to edit
  • PHP unit tests — PHPUnit coverage for shelf-life, price calc, and key helpers

Completed

  • AI price estimation in shopping list
  • Server heartbeat + offline banner
  • In-app bug reporter → automatic GitHub issue creation
  • Cooking mode (start, steps, 3D wheel CSS)
  • Kiosk ⚙️ Settings overlay button (replaces Android native button)
  • Adaptive consumption anomaly detection
  • CI/CD pipeline (PHP lint, JS lint, Docker build, Trivy security scan)

🌐 Translations

The app supports multiple languages via JSON translation files in the translations/ folder.

Language Status
🇮🇹 Italian (it) Complete (base)
🇬🇧 English (en) Complete
🇩🇪 German (de) Complete

Want to add your language? See the Translation Guide — just copy translations/it.json, translate the values, and submit a PR!


🤝 Contributing

Contributions are welcome! See CONTRIBUTING.md for detailed guidelines.

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

📄 License

This project is licensed under the MIT License — see the LICENSE file for details.


👨‍💻 Author

Stimpfl Danielevershelfproject@gmail.com


📸 Screenshots

For a live walkthrough with real data and full AI enabled, visit the live demo — no installation required.

Want to contribute a GIF or screenshots? See CONTRIBUTING.md — PRs welcome!

S
Description
EverShelf: Your pantry's best friend. A self-hosted, open source smart pantry manager with AI expiry tracking, barcode scanning, smart shopping lists, and Android Kiosk support.
Readme MIT 87 MiB
Languages
JavaScript 42.5%
PHP 33.8%
CSS 8.3%
Kotlin 8%
HTML 6.5%
Other 0.7%