Shopping lists:
- Multiple lists per tenant: picker uses checkboxes instead of
radios. Relay schema migrated to composite PK (tenant_id,
card_uid) with a position column for display ordering.
- Picker rows are drag-and-drop reorderable (grip handle +
accent drop indicator). Order persists in localStorage and is
pushed to the relay as position integers — phone renders lists
in that order (ORDER BY position, title).
- Each picker row has a goto-arrow that closes the popup,
switches to the card's bucket if needed, and opens the card.
- Relay DELETE /api/shopping removes deactivated lists. Client
proxy forwards DELETE. Deactivating a list in the picker
immediately removes it from the relay.
- Phone UI renders multiple lists as stacked boxes with headers.
Section headings (# h1–h6) get 14px top padding for breathing
room. CSS selectors fixed to match div-based headings inside
the new .shopping-list-box containers.
- Help text updated for multi-list wording.
- pullOne preserves the synced position so a pull doesn't cause
a spurious re-push of the same order.
Test fixes:
- Line-numbers gutter height tolerance bumped 50%→60% — OS text
shaping can push the divergence past 50%.
- Find/replace flaky: replaced sleep(200) with waitFor on the
confirm dialog so slow renders don't miss the OK click.
- Shopping picker test updated: checkboxes instead of radios.
Bumps to 1.9.25.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
hyprcrd — Electron Desktop App
Wraps the PHP backend in an Electron shell. A static PHP binary is bundled per platform so users don't need PHP installed.
How it works
- On launch, the app starts PHP's built-in server on a random port (
127.0.0.1) router.phpreplaces Apache's.htaccessrewrite rules- A
BrowserWindowloadshttp://127.0.0.1:<port>/ - On quit, the PHP process is killed cleanly
User data (database + uploads) is stored outside the app bundle so it survives updates:
- Dev:
electron/appdata/ - Linux:
~/.config/hyprcrd/data/ - macOS:
~/Library/Application Support/hyprcrd/data/ - Windows:
%APPDATA%/hyprcrd/data/
Development
cd electron
npm install
npm start # launches the app using system or bundled PHP
Requires PHP 8.1+ with pdo_sqlite and zip extensions — either on
the system PATH or as a static binary in php-bin/<platform>/.
Bundling PHP
Static PHP binaries are not checked into git. Fetch them before building:
./fetch-php.sh # downloads ~20MB per platform from static-php-cli
Or place them manually (see php-bin/README.md for sources):
php-bin/linux/php
php-bin/darwin/php
php-bin/win32/php.exe
The app prefers the bundled binary. If none is found, it falls back to system PHP. If neither exists, a dialog tells the user what to install.
Building distributables
npm run dist
Uses electron-builder. Output:
| Platform | Format | Location |
|---|---|---|
| macOS | .dmg |
dist/ |
| Windows | NSIS | dist/ |
| Linux | AppImage | dist/ |
File structure
electron/
main.js Electron main process — spawns PHP, creates window
preload.js Exposes window.hyprcrdElectron (platform, isElectron)
router.php PHP built-in server router (replaces .htaccess)
fetch-php.sh Downloads static PHP binaries for all platforms
php-bin/ Platform-specific PHP binaries (gitignored)