# Sustenance A small shared grocery list built with Rust, Axum, Maud, htmx, WebSockets, and SQLite. ## Run locally ```sh cargo run ``` Open . The application creates `sustenance.db` in the working directory on first start. ## Configuration | Variable | Default | Purpose | | --- | --- | --- | | `DATABASE_PATH` | `sustenance.db` | SQLite database path | | `BIND_ADDRESS` | `127.0.0.1:3000` | Listen address | | `PUBLIC_BASE_URL` | derived from `BIND_ADDRESS` | Base URL used in invitation links | | `COOKIE_SECURE` | `false` | Add the `Secure` attribute to session cookies | | `REGISTRATION_MODE` | `invite_only` | Use `open` for local development; otherwise registration requires a valid list invitation after the first account | | `SEED_CONFIG` | `seed.json` | Optional JSON file with a default user to create when the database is first initialized | | `RUST_LOG` | `sustenance=info,tower_http=info` | Log filter; HTTP requests are logged at info level | ### Seeding a default user If a JSON config file exists at the path given by `SEED_CONFIG` (default `seed.json`), Sustenance creates the configured user on startup when the database has no users yet. The file is optional — if it is missing or invalid, seeding is silently skipped. ```json { "user": { "email": "you@example.com", "display_name": "You", "password": "a-strong-password" } } ``` ## Current features - Email/password accounts with Argon2 password hashes - Cookie-backed sessions and CSRF tokens for list mutations - Shared lists with one-time, seven-day invitation links - Invite-only registration by default after the first account - Add, edit, check, and delete grocery items - Global categories with common defaults seeded at startup and custom category creation - Items grouped by category and assigned from the add/edit forms - Meals with ingredients, markdown descriptions, and one-click "add meal to list" - Server-authoritative last-write-wins updates - Per-list WebSocket updates with server-rendered htmx fragments - In-memory presence for members currently viewing a list - Responsive layout for phone, tablet, and desktop The htmx scripts are currently loaded from unpkg. They can be vendored into `static/` before production deployment. ## Verification ```sh cargo fmt --all -- --check cargo check cargo test ``` ### End-to-end tests (Playwright) The e2e tests live in `e2e/` and use Playwright with a real browser. Each test starts its own server against a fresh, throwaway database on a unique port, so tests are fully isolated from each other and from your real `sustenance.db`. The tests launch `target/debug/sustenance`, so build the server first: ```sh # one-time setup cargo build cd e2e npm install npx playwright install chromium # run the tests (each test launches its own server against a fresh DB) cd e2e npx playwright test ```