Update documentation with all features and learnings

- Updated README with all features: spices filter, shopping list export,
  clickable container legend, category prefixes
- Added deployment troubleshooting for file ownership issues
- Updated CLAUDE.md with architecture details, filtering logic,
  common issues and fixes
- Added live URL reference

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2025-12-23 22:23:23 -05:00
parent 726325e501
commit 08d550b0bd
2 changed files with 154 additions and 75 deletions

View File

@@ -4,9 +4,17 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Overview
Pantry is a simple web app for tracking kitchen pantry items. It's a single-page application with no build step, consisting of just two files:
Pantry is a simple web app for tracking kitchen pantry items. It's a single-page application with no build step.
**Live URL:** https://pantry.kestrelsnest.social
## File Structure
- `index.html` - Frontend (HTML/CSS/JS all in one file)
- `api.php` - Backend API (JSON file-based storage)
- `containers.json` - Container type definitions with categories
- `og-image.png` - OpenGraph image for social sharing
- `deploy` - Rsync deployment script
## Architecture
@@ -14,18 +22,24 @@ Pantry is a simple web app for tracking kitchen pantry items. It's a single-page
- Vanilla JavaScript, no frameworks
- Uses QRCode.js from CDN for QR code generation
- Custom CSS with CSS variables for theming (earthy color palette: cream, terracotta, forest green)
- Container types defined in `containerTypes` object (around line 754) - must be kept in sync with backend
- Container types loaded from `containers.json` at startup into `containerTypes` object
- All API calls go through the `apiCall()` function which POSTs to `api.php`
**Backend (`api.php`)**:
- JSON file-based storage in `data/` directory
- Endpoints: `get`, `add`, `update`, `delete`, `setPin`, `verifyPin`
- Default inventory defined in `$defaultInventory` array (lines 31-64)
- Container types should match frontend when modified
- `sanitize()` function only trims whitespace - do NOT add HTML encoding (causes double-encoding issues)
**Container Configuration (`containers.json`)**:
- Defines container types organized by category
- Each container has: `id`, `name`, `color`
- Categories have: `name`, `containers[]`
- Frontend displays as "Category: Container Name" (e.g., "Glass Spice Jars: Hex (Large)")
**Data Storage**:
- `data/inventory.json` - Inventory items
- `data/pin.txt` - 4-digit PIN for edit mode (plain text, view-only protection)
- `data/pin.txt` - 4-digit PIN for edit mode (plain text)
- `data/` directory must be owned by web server user (my_webapp__2), not admin user
## Development
@@ -37,14 +51,63 @@ php -S localhost:8000
Then open `http://localhost:8000` in a browser.
## Key Implementation Details
- PIN system is view-only protection (anyone can view, PIN required to edit)
- PIN stored in plain text - adequate for household use only
- Items have: `id`, `name`, `container` (type), `outOfStock` (boolean)
- Frontend sorts items: in-stock first, then alphabetically
- 8 container types with color-coded dots in UI
## Deployment
Designed for YunoHost "My Webapp" deployment. Upload `index.html` and `api.php` to the `www/` folder. The `data/` directory is created automatically and must be writable by the web server.
The `deploy` script uses rsync to push to YunoHost:
```bash
# Deploy code, pull data from server
./deploy
# Deploy code AND push local data to server
./deploy --reset-data
```
**Important deployment notes:**
- Files in `data/` must be owned by the web server user (`my_webapp__2`) for PHP to write to them
- If deploying with `--reset-data`, the uploaded files get admin ownership - the web server then can't edit them
- Fix with: `sudo chown my_webapp__2:my_webapp__2 /var/www/my_webapp__2/www/data/inventory.json`
- Adding admin to the my_webapp__2 group allows the deploy script to write while keeping web server access
## Key Implementation Details
**Data model:**
- Items have: `id`, `name`, `container` (type ID), `outOfStock` (boolean)
**Filtering:**
- `currentFilter` - Tab filter: 'all', 'in-stock', 'out', 'spices', 'qr'
- `containerFilter` - Container type filter (null or container ID), set by clicking legend items
- Both filters combine with search text
**Container legend:**
- Clickable - filters inventory by that container type
- Shows count of items per container type
- Active filter highlighted in forest green
**Shopping list:**
- Tap "Out of Stock" stat to copy all out-of-stock item names to clipboard
- Sorted alphabetically, one per line
**UI patterns:**
- `renderInventory()` - Re-renders the item list
- `renderContainerLegend()` - Re-renders legend with counts, called from `updateStats()`
- `showToast(message)` - Shows temporary notification
- `escapeHtml(text)` - Escapes text for safe HTML display (used on item names)
## Common Issues
**Apostrophes/special characters showing as HTML entities:**
- Caused by double-encoding: API was using `htmlspecialchars()` AND frontend uses `escapeHtml()`
- Fix: `sanitize()` in api.php should only `trim()`, not HTML-encode
- Affected items need to be re-saved through UI
**Edits not saving:**
- Usually file ownership issue - web server can't write to files owned by admin
- Check ownership of `data/inventory.json`
## OpenGraph
Meta tags in `<head>` point to `og-image.png` at:
- `https://pantry.kestrelsnest.social/og-image.png`
If URL changes, update the `og:image` and `twitter:image` meta tags.