FridgeStare

Because 6pm comes every single day.

⬇ Download from GitHub

There are a hundred of these apps. I built my own because I wanted exactly what I wanted — scan a UPC as you unpack groceries, tag it as a protein, side, or dessert, and when dinner comes around the planner gives you options based on what's actually in your kitchen. Because we've all stood in front of the fridge at 6pm, staring, with absolutely no plan, even though you just went shopping.

No accounts, no huge dependencies, no bloat.

The scanning system is solid enough that I'm pulling it out for other projects. The rest is just a thing that works for my house. YMMV.

A lightweight, self-contained grocery inventory and meal planning app. Scan UPC barcodes with your phone camera, look up product info, track your stock, and get randomized meal suggestions from what you have on hand.

Design Philosophy

Everything in this app is intentionally simple — sometimes to the point where it might look like a corner was cut. To the contrary...

The rule: if making it more complex doesn't make it noticeably better for a family kitchen, it stays simple.

Features

Requirements

Deployment

Option 1: Manual (any PHP host)

# Upload files to your web root (scp, FTP, rsync, or unzip a release)
scp -r . user@host:/var/www/fridgestare/

# Copy the example config and edit it
cp config.example.php config.php
# Edit config.php with your settings (timezone, API keys, etc.)

# On first visit, the app auto-creates "Default user" / PIN 1234

Requirements: PHP 7.4+ with php-sqlite3, Apache with mod_rewrite.

Option 2: Docker

docker-compose up -d
# App available at http://localhost:8420

The Docker image uses PHP 8.2 Apache with SQLite and zbarimg pre-installed. It strips any local API keys and writes clean defaults. The database is stored in a named Docker volume (survives restarts).

Configuration

Copy config.example.php to config.php and edit:

SettingDescription
timezoneDisplay timezone for ledger timestamps (e.g. America/New_York)
session_timeout_daysHow long a PIN login lasts (default 30)
pin_max_attemptsFailed attempts before lockout (default 5)
pin_lockout_hoursLockout duration after max attempts (default 1)
default_qtyStarting quantity for manual adds (default 1)
debugSet to true to show scanner debug overlay
upcitemdb_keyOptional API key for UPCItemDB product lookup
turnstile_site_keyCloudflare Turnstile site key (free)
turnstile_secret_keyCloudflare Turnstile secret key

Note: config.php is excluded from version control. The repo only tracks config.example.php (with empty keys) so you never accidentally commit live API keys.

First Run

Important: Change the default PIN immediately.

  1. Log in with Default user / PIN 1234
  2. Go to Settings → Users
  3. Create a new user with a name and PIN of your choice
  4. Log out (tap your name in the top bar → Switch User) and log in as your new user
  5. Go back to Settings → Users and delete Default user

That's it. The default user is just a starting key — not meant for daily use.

Database Reset

To wipe all data and restore the factory default user:

php reset-db.php

This is a CLI-only script — it refuses to run via the web. It clears inventory, ledger, products, rate limits, sessions, and users, then recreates Default user / PIN 1234.

Highly Recommended: Cloudflare Turnstile (CAPTCHA)

PIN auth is intentionally kept simple — no email, no password managers. That also means a 4-digit PIN is not strong on its own. Adding Turnstile blocks automated brute-force attempts, which is the real threat.

It's free for any amount of traffic. Takes 2 minutes:

  1. Go to dash.cloudflare.comTurnstileAdd Site
  2. Enter your domain → Widget type: Non-interactiveCreate
  3. Copy the Site Key and Secret Key
  4. In SettingsDanger Zone, paste both keys and save

If you skip it, the CAPTCHA simply doesn't appear — the app works fine either way. But for any public-facing install, it's strongly advised.

Tech Stack

License

MIT

Statement on AI use

AI was used to generate portions of the code and for security reviews and bug chase/fixing. The architecture and scaffolding was done by a real human (me!)


© 2026 Garrett Wiedmeier