Files
pantry/CLAUDE.md
Eric Wagoner 25ec949798 Update documentation for item categories feature
- Add categories.json to file structure in both docs
- Document itemCategories loading in frontend architecture
- Add Item Categories section to README with category table
- Update data model to include category field
- Update filtering documentation with categoryFilter
- Add customization instructions for adding categories

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 12:46:50 -05:00

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 categories
  • categories.json - Item category definitions (Flours, Spices, Pasta, etc.)
  • og-image.png - OpenGraph image for social sharing
  • deploy - 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.json at startup into containerTypes object
  • Item categories loaded from categories.json at startup into itemCategories 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
  • 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 items
  • 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

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
  • 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), 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 tabs
  • containerFilter - 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 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.