# dadaloop82/evershelf architecture

> Architecture diagram of the GitHub repository dadaloop82/evershelf, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-14). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/dadaloop82/evershelf
- Repository: https://github.com/dadaloop82/evershelf

## Overview

1. **Overall shape**
   EverShelf is a self-hosted pantry system built as a **PHP + SQLite backend** with a **single-page web client** served from the same repository. The web app, API, database, cron jobs, and runtime data all live on the same host, with optional Android add-ons for kiosk use and BLE scale support.

2. **Browser/PWA frontend**
   `index.html` loads the app shell, and most UI logic sits in `assets/js/app.js` plus small core modules under `assets/js/core/`. The frontend is a mobile-first PWA with offline support, localStorage caching, a queued write model, and multilingual UI strings from `translations/*.json`.

3. **API boundary**
   All server interactions go through `api/index.php`, which acts as the main router for action-based endpoints. Bootstrapping, environment loading, auth/security checks, logging, and database access are split into `api/bootstrap.php`, `api/lib/*`, `api/logger.php`, and `api/database.php`.

4. **Persistence layer**
   Primary persistence is a **SQLite database** created and migrated by `api/database.php` inside `data/`. The `data/` directory also stores runtime JSON caches and state files such as AI usage, shopping totals, dismissed anomalies, and backup timestamps. This means the backend is stateful but file-based, not service-based.

5. **Core business domains**
   The backend is organized around a few main domains: **products**, **inventory**, **shopping**, **settings**, and **dashboard/analytics**. The API exposes operations such as barcode lookup, inventory add/use/list, Bring! list sync, smart shopping predictions, and server configuration reads/writes.

6. **AI workflow**
   Gemini-powered features are server-side API calls, not browser-side logic. The API handles product identification, expiry extraction, recipe generation, anomaly explanations, shopping enrichment, and storage/shelf-life hints. Recipe generation streams results back with **SSE**, and the server keeps API keys hidden from the browser.

7. **External integrations**
   The main external systems are **Google Gemini**, **Bring!**, **Open Food Facts**, and **Home Assistant**. Home Assistant integration is first-class through the API and OpenAPI contract, while Bring! and Open Food Facts support shopping sync and barcode enrichment. GitHub is also used for issue automation and release/update checks.

8. **Background jobs and maintenance**
   `api/cron_smart_shopping.php` runs as a scheduled job to refresh predictions and trigger cleanup. Database maintenance includes automatic retention cleanup and `VACUUM`, with `backup.sh` providing local backups and optional Google Drive backup support described in the docs.

9. **Offline and resilience model**
   The client is designed to keep working when disconnected: it caches server state locally, computes expiry stats from cached data, and queues mutations until connectivity returns. This creates a deliberate split between **local optimistic UI state** and **authoritative server state** in SQLite.

10. **Security and operational boundaries**
   Configuration comes from `.env`, with optional `API_TOKEN` protection for all API calls and special handling for demo mode. Apache/Nginx rules, `.htaccess`, and Docker support reinforce the deployment boundary, while logging and encrypted GitHub issue tokens stay server-side.

11. **Android kiosk add-on**
   `evershelf-kiosk/` is a separate Android app that wraps the web UI in a locked-down WebView for tablet/kiosk deployments. It includes setup, settings, native TTS, update checks, and permissions for camera/mic use.

12. **Integrated BLE scale gateway**
   The kiosk app also contains the BLE scale gateway: `GatewayService`, `GatewayWebSocketServer`, and `BleScaleManager` run a local foreground service that scans a Bluetooth scale and exposes readings over WebSocket. The web/server side has companion endpoints for discovery and relay, so the browser can receive scale events without mixed-content problems.

13. **Deployment and automation**
   The repo is designed to ship via **Docker Compose** or a conventional PHP web server. GitHub Actions cover CI/security and Android builds, while `docs/openapi.yaml` and the wiki document the API and add-on behavior for operators and integrators.

14. **How to draw the diagram**
   A clear diagram would center on the **browser/PWA**, the **PHP API**, and **SQLite/data files**, then show side links to **Gemini**, **Bring!**, **Open Food Facts**, and **Home Assistant**. Add two optional peripheral blocks: **cron/backup jobs** on the server side and the **Android kiosk + BLE gateway** on the client/add-on side.

Main entry points: [`api/index.php`](https://github.com/dadaloop82/evershelf/blob/main/api/index.php) (API router), [`assets/js/app.js`](https://github.com/dadaloop82/evershelf/blob/main/assets/js/app.js) (Frontend app), [`api/bootstrap.php`](https://github.com/dadaloop82/evershelf/blob/main/api/bootstrap.php) (Bootstrap), [`api/database.php`](https://github.com/dadaloop82/evershelf/blob/main/api/database.php) (SQLite layer)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_client["Web client"]
  node_index["App shell<br/>html entry<br/>[index.html]"]
  node_appjs["Frontend app<br/>spa client<br/>[app.js]"]
  node_coreauth["Core modules<br/>ui core<br/>[auth.js]"]
  node_translations["Translations<br/>i18n assets<br/>[en.json]"]
end

subgraph group_server["PHP backend"]
  node_apiindex["API router<br/>php router<br/>[index.php]"]
  node_bootstrap["Bootstrap<br/>php init<br/>[bootstrap.php]"]
  node_security["Security<br/>php guards<br/>[security.php]"]
  node_env["Env config<br/>php config<br/>[env.php]"]
  node_database[("SQLite layer<br/>php persistence<br/>[database.php]")]
  node_logger["Logging<br/>php logs<br/>[logger.php]"]
  node_datafiles["Runtime data<br/>json state<br/>[ai_usage.json]"]
  node_products["Products<br/>domain api<br/>[index.php]"]
  node_inventory["Inventory<br/>domain api<br/>[index.php]"]
  node_shopping["Shopping<br/>domain api<br/>[index.php]"]
  node_settings["Settings<br/>domain api<br/>[index.php]"]
  node_ai["AI features<br/>gemini workflow<br/>[index.php]"]
end

subgraph group_addon["Android add-on"]
  node_kiosk["Kiosk app<br/>android client<br/>[KioskActivity.kt]"]
  node_gateway["Scale gateway<br/>android service<br/>[GatewayService.kt]"]
end

subgraph group_ops["Operations"]
  node_cron["Cron jobs<br/>maintenance job"]
  node_backup["Backups<br/>shell ops<br/>[backup.sh]"]
  node_openapi["API spec<br/>docs contract<br/>[openapi.yaml]"]
  node_ha["Home Assistant<br/>external integration<br/>[Home-Assistant.md]"]
  node_bring["Bring!<br/>external integration"]
  node_off["Open Food Facts<br/>external integration<br/>[index.php]"]
  node_gemini["Gemini<br/>external ai<br/>[index.php]"]
end

node_index -->|"loads"| node_appjs
node_appjs -->|"uses"| node_coreauth
node_appjs -->|"reads"| node_translations
node_appjs -->|"calls"| node_apiindex
node_apiindex -->|"boots"| node_bootstrap
node_bootstrap -->|"loads"| node_env
node_bootstrap -->|"checks"| node_security
node_apiindex -->|"persists"| node_database
node_apiindex -->|"logs"| node_logger
node_database -->|"stores"| node_datafiles
node_apiindex -->|"serves"| node_products
node_apiindex -->|"serves"| node_inventory
node_apiindex -->|"serves"| node_shopping
node_apiindex -->|"serves"| node_settings
node_apiindex -->|"serves"| node_ai
node_cron -->|"refreshes"| node_shopping
node_cron -->|"maintains"| node_database
node_backup -->|"backs up"| node_datafiles
node_kiosk -->|"wraps"| node_appjs
node_gateway -->|"relays"| node_apiindex
node_gateway -->|"feeds"| node_kiosk
node_apiindex -->|"enriches"| node_off
node_shopping -->|"syncs"| node_bring
node_ai -->|"calls"| node_gemini
node_apiindex -->|"integrates"| node_ha
node_openapi -.->|"documents"| node_apiindex

click node_index "https://github.com/dadaloop82/evershelf/blob/main/index.html"
click node_appjs "https://github.com/dadaloop82/evershelf/blob/main/assets/js/app.js"
click node_coreauth "https://github.com/dadaloop82/evershelf/blob/main/assets/js/core/auth.js"
click node_translations "https://github.com/dadaloop82/evershelf/blob/main/translations/en.json"
click node_apiindex "https://github.com/dadaloop82/evershelf/blob/main/api/index.php"
click node_bootstrap "https://github.com/dadaloop82/evershelf/blob/main/api/bootstrap.php"
click node_security "https://github.com/dadaloop82/evershelf/blob/main/api/lib/security.php"
click node_env "https://github.com/dadaloop82/evershelf/blob/main/api/lib/env.php"
click node_database "https://github.com/dadaloop82/evershelf/blob/main/api/database.php"
click node_logger "https://github.com/dadaloop82/evershelf/blob/main/api/logger.php"
click node_datafiles "https://github.com/dadaloop82/evershelf/blob/main/data/ai_usage.json"
click node_products "https://github.com/dadaloop82/evershelf/blob/main/api/index.php"
click node_inventory "https://github.com/dadaloop82/evershelf/blob/main/api/index.php"
click node_shopping "https://github.com/dadaloop82/evershelf/blob/main/api/index.php"
click node_settings "https://github.com/dadaloop82/evershelf/blob/main/api/index.php"
click node_ai "https://github.com/dadaloop82/evershelf/blob/main/api/index.php"
click node_cron "https://github.com/dadaloop82/evershelf/blob/main/api/cron_smart_shopping.php"
click node_backup "https://github.com/dadaloop82/evershelf/blob/main/backup.sh"
click node_openapi "https://github.com/dadaloop82/evershelf/blob/main/docs/openapi.yaml"
click node_kiosk "https://github.com/dadaloop82/evershelf/blob/main/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/KioskActivity.kt"
click node_gateway "https://github.com/dadaloop82/evershelf/blob/main/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/scale/GatewayService.kt"
click node_ha "https://github.com/dadaloop82/evershelf/blob/main/docs/wiki/Home-Assistant.md"
click node_bring "https://github.com/dadaloop82/evershelf/blob/main/scripts/sync-shopping-bring.php"
click node_off "https://github.com/dadaloop82/evershelf/blob/main/api/index.php"
click node_gemini "https://github.com/dadaloop82/evershelf/blob/main/api/index.php"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_index,node_appjs,node_coreauth,node_translations toneBlue
class node_apiindex,node_bootstrap,node_security,node_env,node_database,node_logger,node_datafiles,node_products,node_inventory,node_shopping,node_settings,node_ai toneAmber
class node_kiosk,node_gateway toneMint
class node_cron,node_backup,node_openapi,node_ha,node_bring,node_off,node_gemini toneRose
```

## Components

### Web client

Browser/PWA app and shared frontend assets.

- [App shell](https://github.com/dadaloop82/evershelf/blob/main/index.html): html entry · Single-page app entry point served from the repo root. · `index.html`
- [Frontend app](https://github.com/dadaloop82/evershelf/blob/main/assets/js/app.js): spa client · Main browser-side application logic. · `assets/js/app.js`
- [Core modules](https://github.com/dadaloop82/evershelf/blob/main/assets/js/core/auth.js): ui core · Shared browser helpers for auth and DOM behavior. · `assets/js/core/auth.js`
- [Translations](https://github.com/dadaloop82/evershelf/blob/main/translations/en.json): i18n assets · Localized UI strings for the web client. · `translations/en.json`

### PHP backend

API, persistence, cron jobs, and server-side integrations.

- [API router](https://github.com/dadaloop82/evershelf/blob/main/api/index.php): php router · Main action-based endpoint dispatcher. · `api/index.php`
- [Bootstrap](https://github.com/dadaloop82/evershelf/blob/main/api/bootstrap.php): php init · Environment loading, auth setup, and request bootstrap. · `api/bootstrap.php`
- [Security](https://github.com/dadaloop82/evershelf/blob/main/api/lib/security.php): php guards · API token checks and request protection helpers. · `api/lib/security.php`
- [Env config](https://github.com/dadaloop82/evershelf/blob/main/api/lib/env.php): php config · Loads runtime configuration from environment variables. · `api/lib/env.php`
- [SQLite layer](https://github.com/dadaloop82/evershelf/blob/main/api/database.php): php persistence · Database creation, migrations, and access to the local SQLite store. · `api/database.php`
- [Logging](https://github.com/dadaloop82/evershelf/blob/main/api/logger.php): php logs · Server-side logging and operational trace output. · `api/logger.php`
- [Runtime data](https://github.com/dadaloop82/evershelf/blob/main/data/ai_usage.json): json state · File-based caches and state alongside the database. · `data/ai_usage.json`
- [Products](https://github.com/dadaloop82/evershelf/blob/main/api/index.php): domain api · Barcode lookup and product enrichment flows. · `api/index.php`
- [Inventory](https://github.com/dadaloop82/evershelf/blob/main/api/index.php): domain api · Add, use, and list inventory state and expiry data. · `api/index.php`
- [Shopping](https://github.com/dadaloop82/evershelf/blob/main/api/index.php): domain api · Shopping list sync, predictions, and related totals. · `api/index.php`
- [Settings](https://github.com/dadaloop82/evershelf/blob/main/api/index.php): domain api · Server configuration reads and writes. · `api/index.php`
- [AI features](https://github.com/dadaloop82/evershelf/blob/main/api/index.php): gemini workflow · Server-side Gemini calls for identification, recipe generation, anomalies, and hints. · `api/index.php`

### Android add-on

Kiosk app and BLE scale gateway.

- [Kiosk app](https://github.com/dadaloop82/evershelf/blob/main/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/KioskActivity.kt): android client · Locked-down Android WebView wrapper for kiosk deployments. · `evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/KioskActivity.kt`
- [Scale gateway](https://github.com/dadaloop82/evershelf/blob/main/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/scale/GatewayService.kt): android service · BLE scale scanning and WebSocket relay service. · `evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/scale/GatewayService.kt`

### Operations

Deployment, automation, docs, and maintenance scripts.

- [Cron jobs](https://github.com/dadaloop82/evershelf/blob/main/api/cron_smart_shopping.php): maintenance job · Scheduled refresh, cleanup, and shopping prediction maintenance. · `api/cron_smart_shopping.php`
- [Backups](https://github.com/dadaloop82/evershelf/blob/main/backup.sh): shell ops · Local backup and retention support. · `backup.sh`
- [API spec](https://github.com/dadaloop82/evershelf/blob/main/docs/openapi.yaml): docs contract · OpenAPI definition for integrators and Home Assistant. · `docs/openapi.yaml`
- [Home Assistant](https://github.com/dadaloop82/evershelf/blob/main/docs/wiki/Home-Assistant.md): external integration · First-class external smart-home integration. · `docs/wiki/Home-Assistant.md`
- [Bring!](https://github.com/dadaloop82/evershelf/blob/main/scripts/sync-shopping-bring.php): external integration · Shopping list synchronization provider. · `scripts/sync-shopping-bring.php`
- [Open Food Facts](https://github.com/dadaloop82/evershelf/blob/main/api/index.php): external integration · Barcode and product enrichment source. · `api/index.php`
- [Gemini](https://github.com/dadaloop82/evershelf/blob/main/api/index.php): external ai · External AI provider used by server-side workflows. · `api/index.php`

## Connections

- App shell → Frontend app: loads · Bootstraps the web app shell into the browser.
- Frontend app → Core modules: uses · Shares auth and DOM helpers across the client.
- Frontend app → Translations: reads · Loads localized UI strings.
- Frontend app → API router: calls · Sends all server requests through the API router.
- API router → Bootstrap: boots · Initializes request handling and shared runtime state.
- Bootstrap → Env config: loads · Pulls runtime configuration from the environment.
- Bootstrap → Security: checks · Applies request authentication and protection.
- API router → SQLite layer: persists · Reads and writes SQLite-backed repository state.
- API router → Logging: logs · Emits operational and request logs.
- SQLite layer → Runtime data: stores · Maintains caches and runtime JSON state in data/.
- API router → Products: serves · Handles product lookup and enrichment actions.
- API router → Inventory: serves · Handles inventory mutation and listing actions.
- API router → Shopping: serves · Handles shopping synchronization and prediction actions.
- API router → Settings: serves · Exposes configuration reads and writes.
- API router → AI features: serves · Runs server-side AI workflows and streaming responses.
- Cron jobs → Shopping: refreshes · Recomputes smart shopping predictions and cleanup.
- Cron jobs → SQLite layer: maintains · Runs retention and VACUUM maintenance.
- Backups → Runtime data: backs up · Captures local runtime state and database-related files.
- Kiosk app → Frontend app: wraps · Displays the same web UI inside a locked-down Android shell.
- Scale gateway → API router: relays · Provides local scale discovery and relay support for the web app.
- Scale gateway → Kiosk app: feeds · Streams BLE scale readings into the kiosk runtime.
- API router → Open Food Facts: enriches · Uses product data from Open Food Facts.
- Shopping → Bring!: syncs · Syncs shopping lists with Bring!
- AI features → Gemini: calls · Uses Gemini for identification, recipes, anomalies, and hints.
- API router → Home Assistant: integrates · Exposes Home Assistant-facing operations and contract.
- API spec → API router: documents · Describes the API surface for operators and integrators.
