The script now prints the chown command needed after pushing data, since uploaded files are owned by admin and the web server can't write to them. Updated docs to match. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
4.5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
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 categoriescategories.json- Item category definitions (Flours, Spices, Pasta, etc.)og-image.png- OpenGraph image for social sharingdeploy- Rsync deployment script
Architecture
Frontend (index.html):
- 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 loaded from
containers.jsonat startup intocontainerTypesobject - Item categories loaded from
categories.jsonat startup intoitemCategoriesobject - All API calls go through the
apiCall()function which POSTs toapi.php
Backend (api.php):
- JSON file-based storage in
data/directory - Endpoints:
get,add,update,delete,setPin,verifyPin 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)")
Item Categories (categories.json):
- Defines item categories for organizing inventory (Flours, Spices, Pasta, Baking, etc.)
- Each category has: key (e.g.,
flours),name,color - Category tabs are dynamically generated in the nav bar
- Items display their category as a colored tag
Data Storage:
data/inventory.json- Inventory itemsdata/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
This is a no-build project. To test locally:
php -S localhost:8000
Then open http://localhost:8000 in a browser.
Deployment
The deploy script uses rsync to push to YunoHost:
# 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 - Using
--reset-datauploads files as admin — you must fix ownership afterward (the script shows the command) - If edits aren't saving, check ownership with
ls -laand fix with:sudo chown -R my_webapp__2:my_webapp__2 /var/www/my_webapp__2/www/data/
Key Implementation Details
Data model:
- Items have:
id,name,container(type ID),category(category key),outOfStock(boolean)
Filtering:
currentFilter- Tab filter: 'all', 'in-stock', 'out', 'category', 'recent', 'qr'categoryFilter- Category filter (null or category key), set by clicking category tabscontainerFilter- Container type filter (null or container ID), set by clicking legend items- All 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 listrenderContainerLegend()- Re-renders legend with counts, called fromupdateStats()showToast(message)- Shows temporary notificationescapeHtml(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 usesescapeHtml() - Fix:
sanitize()in api.php should onlytrim(), 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.