52cfbba663
- README.md: add anomaly banner, AI local matching, scale 10g threshold, ml conversion hint, auto-fill improvements, Android kiosk section, updated roadmap with completed items, architecture tree with kiosk - evershelf-kiosk/README.md: complete rewrite — now reflects pure WebView wrapper architecture (no BLE), setup wizard, kiosk lock, exit/refresh buttons, permissions, gateway auto-launch, update notifications - evershelf-scale-gateway/README.md: update architecture diagram to show SSE relay path, add kiosk integration note
371 lines
15 KiB
Markdown
371 lines
15 KiB
Markdown
# 🏠 EverShelf
|
|
|
|
> **Self-hosted pantry management system** — Track your food inventory, scan barcodes, get AI-powered recipe suggestions, and reduce waste.
|
|
|
|
🌐 **Website:** [evershelfproject.dadaloop.it](https://evershelfproject.dadaloop.it/)
|
|
|
|
[](LICENSE)
|
|
[](https://www.php.net/)
|
|
[](https://www.sqlite.org/)
|
|
[](Dockerfile)
|
|
[](translations/)
|
|
|
|
---
|
|
|
|
## ✨ 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
|
|
- **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
|
|
- **Vacuum-sealed support** — Extended expiry dates for vacuum-sealed items
|
|
- **Anomaly detection** — Banner alerts for suspicious quantities and consumption predictions with inline correction
|
|
|
|
### 🤖 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
|
|
- **Recipe generation** — Get personalized recipes based on what's in your pantry
|
|
- **Smart chat assistant** — Ask questions about your inventory, get cooking tips
|
|
- **Shopping suggestions** — AI-powered purchase recommendations
|
|
|
|
### 🛒 Shopping List
|
|
- **Bring! integration** — Sync with the [Bring!](https://www.getbring.com/) shopping list app
|
|
- **Smart predictions** — Know what you'll need before you run out
|
|
- **Auto-remove on scan** — Products are removed from the shopping list when scanned in
|
|
- **DupliClick integration** — Online grocery ordering (Gruppo Poli)
|
|
|
|
### 🍳 Cooking Mode
|
|
- **Step-by-step guidance** — Follow recipes with a hands-free cooking interface
|
|
- **Text-to-Speech** — Voice readout of recipe steps (configurable TTS endpoint)
|
|
- **Built-in timer** — Automatic timer suggestions based on recipe instructions
|
|
- **Ingredient tracking** — Mark ingredients as used during cooking
|
|
|
|
### 📊 Dashboard
|
|
- **Waste tracking** — Monitor consumed vs. wasted products over 30 days
|
|
- **Expiry alerts** — Visual warnings for expired and soon-to-expire items
|
|
- **Safety ratings** — Smart assessment of expired product safety (by category)
|
|
- **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
|
|
|
|
### 📱 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
|
|
- **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
|
|
- **Android gateway app** — [`evershelf-scale-gateway/`](evershelf-scale-gateway/) — open-source, downloadable APK
|
|
|
|
### 📺 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** — 3-step guided configuration (URL, connection test, gateway)
|
|
- **Gateway auto-launch** — Launches the Scale Gateway in the background on startup
|
|
- **Camera & mic permissions** — Full hardware access for barcode scanning and voice
|
|
- **Exit button** — Visible ✕ button with confirmation dialog
|
|
- **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 app** — [`evershelf-kiosk/`](evershelf-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
|
|
|
|
#### Option A: Docker (recommended)
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```ini
|
|
# 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
|
|
```
|
|
|
|
### Web Server Configuration
|
|
|
|
<details>
|
|
<summary><strong>Apache (.htaccess)</strong></summary>
|
|
|
|
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.
|
|
|
|
```apache
|
|
<Directory /var/www/html/evershelf>
|
|
AllowOverride All
|
|
Require all granted
|
|
</Directory>
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary><strong>Nginx</strong></summary>
|
|
|
|
```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; }
|
|
}
|
|
```
|
|
|
|
</details>
|
|
|
|
### HTTPS Setup (Recommended)
|
|
|
|
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:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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 (add-on)
|
|
├── README.md # Setup & protocol 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 |
|
|
| **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 passed server-side only — never exposed to the browser
|
|
- The API uses **parameterized SQL queries** (PDO prepared statements) against injection
|
|
- **Input validation** on all inventory operations (quantity bounds, location whitelist)
|
|
- Consider adding **authentication** if the server is accessible from the internet
|
|
|
|
---
|
|
|
|
## 🛠️ Development
|
|
|
|
```bash
|
|
# 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
|
|
|
|
- [x] Multi-language support (i18n) — 3 languages (it/en/de), 347 keys
|
|
- [ ] User authentication / multi-user support
|
|
- [x] Docker container for easy deployment — see [Dockerfile](Dockerfile) + [docker-compose.yml](docker-compose.yml)
|
|
- [x] REST API documentation (OpenAPI/Swagger) — see [docs/openapi.yaml](docs/openapi.yaml)
|
|
- [x] First-run setup wizard — 4-step guided configuration
|
|
- [x] API rate limiting — file-based, 3 tiers (120/15/5 req/min)
|
|
- [x] CI/CD pipeline — GitHub Actions (lint, Docker build, translation validation)
|
|
- [x] Android kiosk mode — dedicated tablet app with screen pinning
|
|
- [x] Anomaly detection banner — suspicious quantities + consumption predictions
|
|
- [x] AI scan local matching — suggest existing pantry products before OFF lookup
|
|
- [x] Scale auto-fill improvements — 10g threshold, ml conversion hints
|
|
- [x] Update notification system — kiosk checks GitHub releases
|
|
- [ ] Offline mode with service worker
|
|
- [ ] Export/import inventory data
|
|
- [ ] Notification system (Telegram, email) for expiring products
|
|
|
|
---
|
|
|
|
## 🌐 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](CONTRIBUTING.md#-adding-translations) — just copy `translations/it.json`, translate the values, and submit a PR!
|
|
|
|
---
|
|
|
|
## 🤝 Contributing
|
|
|
|
Contributions are welcome! See [CONTRIBUTING.md](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](LICENSE) file for details.
|
|
|
|
---
|
|
|
|
## 👨💻 Author
|
|
|
|
**Stimpfl Daniel** — [evershelfproject@gmail.com](mailto:evershelfproject@gmail.com)
|
|
|
|
- Website: [evershelfproject.dadaloop.it](https://evershelfproject.dadaloop.it/)
|
|
- GitHub: [@dadaloop82](https://github.com/dadaloop82)
|
|
|
|
---
|
|
|
|
## 📸 Screenshots
|
|
|
|
| | | |
|
|
|:---:|:---:|:---:|
|
|
|  |  |  |
|
|
| **Dashboard** — Inventory overview with counters by location (pantry, fridge, freezer), upcoming expiry alerts, and consumed vs. wasted tracking over the last 30 days. | **Inventory** — Full product list filterable by location (All / Pantry / Fridge / Freezer) and searchable by name, with category, quantity, and expiry date. | **Barcode Scanner** — Scan barcodes with the camera (QuaggaJS) or enter manually. Shopping mode lets you register purchased products in quick sequence. |
|
|
|  |  |  |
|
|
| **AI Recipe Detail** — Recipe generated by Gemini AI using expiring ingredients: each ingredient is matched to the real inventory with quantity and location, ready to scale. | **Recipes** — History of AI-generated recipes, organized by day and meal (lunch / dinner / other), with preparation and cooking time. | **Cooking Mode** — Fullscreen step-by-step guide with Text-to-Speech. Each step shows the ingredient to use from your pantry with an integrated "Use" button. |
|
|
|  |  |  |
|
|
| **Gemini Chat** — AI assistant that knows your pantry, your appliances, and your preferences. Suggests snacks, smoothies, or quick meals with a single tap. | **Shopping List** — List synced with Bring!, organized by product category, with urgency indicators and links to search for prices online. | **Smart Predictions** — AI analysis of historical consumption: shows what is running low, how much time is left, and why restocking is recommended (regular use, nearly empty, opened). |
|