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>
123 lines
4.5 KiB
Markdown
123 lines
4.5 KiB
Markdown
# 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:
|
|
|
|
```bash
|
|
php -S localhost:8000
|
|
```
|
|
|
|
Then open `http://localhost:8000` in a browser.
|
|
|
|
## Deployment
|
|
|
|
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
|
|
- Using `--reset-data` uploads files as admin — you must fix ownership afterward (the script shows the command)
|
|
- If edits aren't saving, check ownership with `ls -la` and 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 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.
|