docs: create app wiki

Nico 2026-05-26 00:31:28 -07:00
parent 6a0ee1c92e
commit 06f4b3d139
9 changed files with 1011 additions and 0 deletions

@ -0,0 +1,123 @@
# Admin and Operations Guide
This page is for system admins and operators.
## System Admin Panel
The `/admin` page is available to users with the `system_admin` role.
The admin panel includes:
- User management.
- Global store management.
Household owners/admins manage household-scoped members, invite links, stores, locations, zones, and catalog items from **Manage**. System admins manage cross-household/global records from **Admin**.
## Runtime Layout
Local and production runtime pieces:
- Backend API: Express, default port `5000`.
- Frontend: Vite/React, Docker-mapped dev port `3010`, direct Vite default `5173`.
- Database: external Postgres, not a container.
- Dev compose: `docker-compose.dev.yml`.
- Production compose: `docker-compose.yml`.
## Environment Variables
Do not commit real `.env`, `backend.env`, or `frontend.env` values.
Important backend variables:
| Variable | Purpose |
| --- | --- |
| `DATABASE_URL` | Preferred Postgres connection string for backend and root migration scripts. |
| `DB_USER`, `DB_PASS`, `DB_HOST`, `DB_PORT`, `DB_NAME` | Backend fallback database settings when `DATABASE_URL` is absent. |
| `JWT_SECRET` | Required for token-compatible auth paths. |
| `ALLOWED_ORIGINS` | Comma-separated allowed frontend origins for CORS. |
| `SESSION_COOKIE_NAME` | Optional session cookie name. |
| `SESSION_TTL_DAYS` | Optional session lifetime in days. |
Important frontend variables:
| Variable | Purpose |
| --- | --- |
| `VITE_API_URL` | Frontend API base URL. Defaults to the local backend URL. |
| `VITE_ALLOWED_HOSTS` | Optional Vite host allowlist. |
## Local Operations
Install:
```bash
npm ci
npm --prefix backend ci
npm --prefix frontend ci
```
Run with Docker:
```bash
docker compose -f docker-compose.dev.yml up
```
Run in separate terminals:
```bash
npm run dev:backend
npm run dev:frontend
```
Health checks:
```bash
curl http://127.0.0.1:5000/
curl http://127.0.0.1:5000/config
```
## Deployment
Gitea Actions build and deploy this app.
- Pushes to `main` build and tag images as `latest`.
- Pushes to `main-new` build and tag images as `main-new`.
- Workflows install dependencies, run reliability checks, build backend/frontend images, push images to the configured registry, then deploy through SSH.
Deployment secrets are stored in Gitea Actions secrets. Do not print or paste them into logs.
## Reliability Gate
The workflow currently runs:
```bash
npm run audit
npm run lint
npm run typecheck
npm test
npm run db:migrate:stale:check
npm run build:backend
npm run build:frontend
```
Use the same commands locally before pushing risky changes.
## Operational Safety
- Do not run migrations against production or shared databases unless that is the explicit operator task.
- Do not add a Postgres container; the app expects an external database.
- Do not log secrets, tokens, session cookies, DB URLs, receipt bytes, or full invite codes.
- Invite code logs/audit entries may include last 4 characters only.
- Backend/API changes in Docker dev usually require rebuilding/restarting the backend service.
Useful dev backend restart:
```bash
docker compose -f docker-compose.dev.yml up -d --build backend
```
Useful env/CORS reload:
```bash
docker compose -f docker-compose.dev.yml up -d --force-recreate --no-deps backend
```

182
Architecture-and-API.md Normal file

@ -0,0 +1,182 @@
# Architecture and API
This page summarizes the current app architecture and active API shape.
## High-Level Flow
```text
React/Vite SPA
-> frontend/src/api shared Axios client
-> Express route
-> controller
-> middleware/services/models
-> external Postgres
```
The active grocery flow is:
```text
User -> Household -> Store Location -> Zones -> List Items / Available Items
```
## Frontend
Routes:
| Route | Page |
| --- | --- |
| `/login` | Login |
| `/register` | Register |
| `/invite/:token` | Invite link summary and acceptance |
| `/` | Grocery list |
| `/manage` | Household and store management |
| `/settings` | User settings |
| `/admin` | System admin panel |
Core providers:
- `AuthProvider`: login state.
- `HouseholdProvider`: user households and active household.
- `StoreProvider`: household stores, active store/location, and zones.
- `UploadQueueProvider`: queued image uploads and retry/discard behavior.
- `ActionToastProvider`: user-visible action outcomes.
- `SettingsProvider`: per-user local settings.
## Backend
Route families:
| Prefix | Purpose |
| --- | --- |
| `/auth` | Register, login, logout. |
| `/users` | Current user profile, password change, username availability. |
| `/admin` | System admin user operations. |
| `/config` | Public frontend config such as image limits. |
| `/households` | Households, members, stores, locations, zones, lists, and available items. |
| `/stores` | Global store records and legacy household store helpers. |
| `/api/groups` | Invite links, join requests, and join policy. |
| `/api/invite-links` | Public invite link summary and authenticated acceptance. |
| `/list` | Legacy/global list routes; prefer scoped household/location routes for new work. |
## Active Scoped Endpoints
Households:
```text
GET /households
POST /households
GET /households/:householdId
PATCH /households/:householdId
DELETE /households/:householdId
GET /households/:householdId/members
PATCH /households/:householdId/members/:userId/role
DELETE /households/:householdId/members/:userId
```
Stores, locations, and zones:
```text
GET /households/:householdId/stores
POST /households/:householdId/stores
PATCH /households/:householdId/stores/:householdStoreId
DELETE /households/:householdId/stores/:householdStoreId
POST /households/:householdId/stores/:householdStoreId/locations
PATCH /households/:householdId/locations/:locationId
DELETE /households/:householdId/locations/:locationId
PATCH /households/:householdId/locations/:locationId/default
GET /households/:householdId/locations/:locationId/zones
POST /households/:householdId/locations/:locationId/zones
PATCH /households/:householdId/locations/:locationId/zones/:zoneId
DELETE /households/:householdId/locations/:locationId/zones/:zoneId
```
Location-scoped list:
```text
GET /households/:householdId/locations/:locationId/list
GET /households/:householdId/locations/:locationId/list/item
POST /households/:householdId/locations/:locationId/list/add
PUT /households/:householdId/locations/:locationId/list/item
PATCH /households/:householdId/locations/:locationId/list/item
DELETE /households/:householdId/locations/:locationId/list/item
GET /households/:householdId/locations/:locationId/list/suggestions
GET /households/:householdId/locations/:locationId/list/recent
GET /households/:householdId/locations/:locationId/list/classification
POST /households/:householdId/locations/:locationId/list/classification
POST /households/:householdId/locations/:locationId/list/update-image
```
Available items:
```text
GET /households/:householdId/locations/:locationId/available-items
POST /households/:householdId/locations/:locationId/available-items
PATCH /households/:householdId/locations/:locationId/available-items/:itemId
DELETE /households/:householdId/locations/:locationId/available-items/:itemId
POST /households/:householdId/locations/:locationId/available-items/import-current
```
Invite links:
```text
GET /api/groups/invites
POST /api/groups/invites
GET /api/groups/join-requests
POST /api/groups/join-requests/decision
POST /api/groups/invites/revoke
POST /api/groups/invites/revive
POST /api/groups/invites/delete
GET /api/groups/join-policy
POST /api/groups/join-policy
GET /api/invite-links/:token
POST /api/invite-links/:token
```
Group invite management uses a `X-Group-Id` header from the frontend wrapper when the user manages multiple groups.
## Auth And Authorization
Authentication:
- Login validates a lowercase username and password.
- Login creates a DB session and sets an HttpOnly cookie.
- Login also returns a JWT-compatible token used by existing client code.
- Protected routes accept valid session or token credentials.
Authorization:
- System admin routes require the `system_admin` role.
- Household routes require membership in the target household.
- Household admin routes require owner/admin membership.
- Location/list routes also verify access to the selected store location.
## Request IDs And Errors
Every API response includes a request ID and sends it as the `X-Request-Id` response header.
Error responses are normalized to:
```json
{
"error": {
"code": "bad_request",
"message": "Readable message"
},
"request_id": "generated-request-id"
}
```
Frontend API wrappers unwrap `{ data, request_id }` success payloads when needed.
## Image Handling
Image uploads use Multer and Sharp.
Configuration is exposed by `/config` and includes:
- Maximum image file size.
- Maximum image dimension.
- Image quality.
Frontend uploads use `UploadQueueContext`, which persists queued jobs and lets users retry failed uploads.

103
Database-and-Migrations.md Normal file

@ -0,0 +1,103 @@
# Database and Migrations
Fiddy uses an external on-prem Postgres database. Do not add or assume a database container.
## Canonical Migration Directory
Canonical migrations live in:
```text
packages/db/migrations
```
Legacy SQL under `backend/migrations` is reference-only. Do not add new canonical migrations there.
## Required Environment
Migration commands need:
- `DATABASE_URL` set in the shell.
- `psql` installed and available on `PATH`.
- The command run from the repo root.
Do not print or commit the value of `DATABASE_URL`.
## Commands
Show status:
```bash
npm run db:migrate:status
```
Create a migration:
```bash
npm run db:migrate:new -- <migration-name>
```
Apply pending migrations:
```bash
npm run db:migrate
```
Verify clean state:
```bash
npm run db:migrate:verify
```
Check stale legacy SQL:
```bash
npm run db:migrate:stale:check
```
Update stale tracking:
```bash
npm run db:migrate:stale
```
## Operator Flow
1. Confirm which database `DATABASE_URL` targets.
2. Run `npm run db:migrate:status`.
3. Create a new migration file if the code change needs schema changes.
4. Review the SQL.
5. Apply pending migrations only when the operator intends to change that database.
6. Run `npm run db:migrate:verify`.
7. Run the relevant app tests/builds.
## Tracking Table
Applied migrations are recorded in:
```text
schema_migrations(filename text unique, applied_at timestamptz)
```
Migrations apply in lexicographic filename order.
## Current Data Areas
The current app stores data for:
- Users and DB-backed sessions.
- Households and household members.
- Invite links, join requests, join policy, and audit events.
- Stores, household stores, locations, and zones.
- Location-scoped list items.
- Available/catalog items.
- Item images and metadata.
- Item classification and notes.
## Safety Rules
- Never run migrations against production/shared data unless explicitly asked.
- Never edit applied migration history manually unless performing a planned database repair.
- Do not log secrets, DB URLs, tokens, cookies, receipt bytes, or full invite codes.
- Invite-code logging may include last 4 characters only.
- Add tests for API behavior that depends on a new schema contract.

65
Home.md Normal file

@ -0,0 +1,65 @@
# Fiddy Wiki
Fiddy is a collaborative grocery list app for households. It lets people keep a shared shopping list, organize items by store location and zone, add product images, track recently bought items, and manage who can access each household.
This wiki is written for two audiences:
- Users who shop with the app and manage households.
- Programmers and operators who run, maintain, or extend the app.
## Start Here
| Audience | Page | Use it for |
| --- | --- | --- |
| Users | [User Guide](User-Guide) | Sign in, create or join a household, use the grocery list, upload images, and adjust settings. |
| Household owners/admins | [Households, Roles, and Invites](Households-Roles-and-Invites) | Manage members, invite links, join policies, and household roles. |
| Store/list managers | [Stores, Zones, and Catalog Items](Stores-Zones-and-Catalog-Items) | Add store locations, choose defaults, organize zones, and maintain reusable item suggestions. |
| Operators | [Admin and Operations Guide](Admin-and-Operations-Guide) | Manage system users, deployment, environment variables, and health checks. |
| Programmers | [Programmer Guide](Programmer-Guide) | Set up the repo, run the app locally, follow coding conventions, and verify changes. |
| Programmers | [Architecture and API](Architecture-and-API) | Understand the Express API, React client, auth, request IDs, and active route families. |
| Programmers/operators | [Database and Migrations](Database-and-Migrations) | Work with the external Postgres database and canonical migration workflow. |
| Everyone | [Troubleshooting](Troubleshooting) | Fix common login, household, store, image upload, CORS, and deployment issues. |
## What The App Does
Fiddy supports:
- Email/password accounts with DB-backed sessions and an HttpOnly session cookie.
- Multiple households per user.
- Household roles: owner, admin, and member.
- Invite links with join policies for closed, automatic, or approval-based joining.
- Store locations per household, including default locations.
- Ordered store zones so the list can match the shopping path.
- Location-scoped grocery lists with quantities, notes, classification, and images.
- Recently bought items for the last 24 hours.
- Search and suggestions from the household/location catalog.
- User settings for theme, list display, recent item count, confirmation behavior, haptics, and debug mode.
- System administration for users and global store records.
- Gitea Actions based build/deploy workflows.
## Current Stack
- Frontend: React 19 and Vite in `frontend/`.
- Backend: Express 5 CommonJS API in `backend/`.
- Database: external on-prem Postgres.
- Package manager: npm.
- Migrations: canonical SQL files in `packages/db/migrations`.
- CI/CD: Gitea Actions in `.gitea/workflows`.
## Important Concepts
The active app flow is household and location scoped:
1. A user signs in.
2. The user creates or joins a household.
3. The user selects a household store location.
4. The grocery list, item suggestions, zones, images, and recently bought items are scoped to that household and location.
Programmers should prefer the current scoped API routes under:
```text
/households/:householdId/locations/:locationId/...
```
Some legacy global list routes still exist for compatibility, but new work should follow the household/location model unless the task explicitly says otherwise.

@ -0,0 +1,82 @@
# Households, Roles, and Invites
Households are the main collaboration boundary in Fiddy. Lists, stores, locations, zones, catalog items, and membership are scoped to a household.
## Household Roles
| Role | Can shop | Manage household | Manage stores/zones | Manage invites | Manage member roles |
| --- | --- | --- | --- | --- | --- |
| Owner | Yes | Yes | Yes | Yes | Yes, including ownership transfer |
| Admin | Yes | Yes | Yes | Yes | Yes, except protected owner actions |
| Member | Yes | No | Limited/no admin actions | No | No |
Rules enforced by the backend:
- Only household members can access a household.
- Owner/admin actions require a household owner or admin role.
- A member cannot promote themselves.
- Owner role changes are protected.
- Server-side authorization is required; client UI checks are only convenience.
## Create A Household
1. Sign in.
2. Use the household create flow.
3. Enter a household name.
4. The creator becomes the household owner.
## Rename Or Delete A Household
Open **Manage > Household**.
Owners/admins can rename a household. Owners/admins can also delete a household, which removes that household's lists and related data. Treat deletion as permanent.
## Invite Links
Owners/admins can create invite links from **Manage > Household > Invite Links**.
Invite link behavior:
- Links have a time-to-live from 1 to 7 days.
- Link settings are immutable after creation.
- Expired links are retained and can be revived.
- Reviving a link resets its expiration and creates a new audit event.
- Single-use links are deleted after successful use.
- Single-use does not bypass approval-required joining.
- Logs and audit records must never expose full invite codes; use last 4 characters only.
When copying or sharing invite links, send them only to people who should join the household.
## Join Policy
Owners/admins choose how invite link joins work:
| Policy | Meaning |
| --- | --- |
| Not accepting | New joins are closed. Existing members continue to use the household. |
| Auto accept | A valid invite link adds the user automatically. |
| Approval required | A valid invite link creates a pending join request that an owner/admin must approve. |
## Join Requests
When approval is required:
1. A user opens an invite link.
2. The app creates a pending join request.
3. Owners/admins review pending requests from the household management screen.
4. Owners/admins approve or deny each request.
Approved users become household members.
## Member Management
Owners/admins can:
- View members.
- Promote members to admin.
- Demote admins to member.
- Transfer ownership where allowed.
- Remove members.
Members can leave a household. If a user belongs to multiple households, they can switch to another household after leaving.

132
Programmer-Guide.md Normal file

@ -0,0 +1,132 @@
# Programmer Guide
This page is for people changing the code.
## Stack
- Backend: Express 5, CommonJS, Node.js.
- Frontend: React 19, Vite, partial TypeScript.
- Database: external Postgres through `pg`.
- Tests: Jest/Supertest for backend, Playwright for e2e.
- Package manager: npm.
Use Node.js 20.19+ or 22.12+ for frontend/Vite commands.
## Repository Map
Key paths:
| Path | Purpose |
| --- | --- |
| `backend/app.js` | Express middleware, CORS, route mounting, and error handler. |
| `backend/routes` | Route registration. Keep these thin. |
| `backend/controllers` | Request parsing and response handling. |
| `backend/models` | Database query modules. |
| `backend/services` | Domain service logic. |
| `backend/middleware` | Auth, RBAC, household access, request IDs, rate limits, image processing. |
| `frontend/src/api` | Axios API wrappers. Use these instead of direct component fetches. |
| `frontend/src/context` | Auth, household, store, settings, toast, and upload queue state. |
| `frontend/src/pages` | Route-level screens. |
| `frontend/src/components` | Shared and feature UI components. |
| `packages/db/migrations` | Canonical SQL migrations. |
| `.gitea/workflows` | Gitea Actions workflows. |
## Setup
```bash
npm ci
npm --prefix backend ci
npm --prefix frontend ci
```
Copy env examples as needed, but never commit real values:
```bash
backend/.env.example -> backend/.env
frontend/.env.example -> frontend/.env
```
Root migration scripts read `DATABASE_URL` from the shell environment.
## Run Locally
Docker dev stack:
```bash
docker compose -f docker-compose.dev.yml up
```
Separate terminals:
```bash
npm run dev:backend
npm run dev:frontend
```
Default endpoints:
- Backend: `http://localhost:5000`
- Frontend through Docker compose: `http://localhost:3010`
- Frontend direct Vite: `http://localhost:5173`
## Coding Conventions
- Preserve the current Express/Vite stack.
- Keep route files thin.
- Put DB-heavy logic in models/services.
- Enforce RBAC and household access server-side.
- Keep frontend network calls in `frontend/src/api`.
- Use the shared Axios client so credentials are sent consistently.
- Use context/hooks for UI state.
- Frontend DB-mutating actions should show toast or bubble outcome notifications.
- Progress notifications should reuse `UploadQueueContext` and `UploadToaster`.
- Do not introduce cron, workers, polling daemons, or background job frameworks.
- Do not add production dependencies unless the task clearly requires one and there is no practical existing option.
## Auth Notes
The current login flow returns a token for compatibility and also creates a DB-backed session. The backend sets an HttpOnly session cookie. The Axios client sends credentials and also attaches the stored token when present.
When changing auth:
- Keep sessions DB-backed.
- Keep session cookies HttpOnly.
- Do not log tokens or cookies.
- Preserve redirect behavior for expired sessions.
## Verification
Choose the narrowest useful checks first, then broaden when risk warrants it.
Common commands:
```bash
npm test
npm run lint
npm run typecheck
npm run audit
npm run build:backend
npm run build:frontend
npm run build
npm run test:e2e
```
Migration checks:
```bash
npm run db:migrate:status
npm run db:migrate:verify
npm run db:migrate:stale:check
```
Do not run `npm run db:migrate` unless an operator explicitly intends to apply migrations to the selected external database.
## Tests To Add
Add or update tests when behavior changes:
- API behavior: Jest/Supertest in `backend/tests`.
- Authz, membership, invalid input, and not-a-member cases: include negative coverage.
- UI behavior: focused Playwright tests in `frontend/tests`.
- Pure docs changes: validate Markdown/content where practical.

@ -0,0 +1,75 @@
# Stores, Zones, and Catalog Items
Store management controls how grocery lists are organized for a household.
## Store Model
Fiddy separates:
- Global store records: system-level store templates.
- Household-owned stores: stores configured for a specific household.
- Locations: concrete shopping locations under a household store.
- Zones: ordered areas inside a location.
- Available items: location-specific catalog items used for suggestions and defaults.
The active shopping list is scoped to a household and one location.
## Add A Household Store And Location
Open **Manage > Stores**.
Owners/admins can:
1. Add a household store.
2. Add one or more locations for that store.
3. Rename stores or locations.
4. Set the default shopping location.
5. Remove stores or locations when they are no longer needed.
The main list uses the active/default location when showing list items and suggestions.
## Manage Zones
Zones represent store areas such as produce, dairy, freezer, household, or checkout.
Owners/admins can:
- Add zones.
- Rename zones.
- Set zone order.
- Delete zones.
Users see list items grouped by the active location's zones. Zone order should match the route people normally walk through the store.
## Manage Available Items
Available items are reusable household/location catalog entries. They power suggestions and default details when users add groceries.
From **Manage > Stores > Manage Items**, owners/admins can:
- Search the catalog.
- Add catalog items.
- Edit item names, defaults, notes, classification, and images.
- Delete catalog items.
- Import current list items into the catalog.
Members can use catalog-backed suggestions while adding items. Admin-only catalog deletion is enforced by the backend.
## Good Catalog Hygiene
Use stable, simple item names:
- Prefer `milk` over `need milk`.
- Prefer `eggs` over `12 eggs` because quantity is tracked separately.
- Use notes for brand, size, or special instructions.
- Keep zones broad enough to be useful while shopping.
## When A Store Is Missing
If the list says no stores are found:
1. Confirm the correct household is selected.
2. Ask an owner/admin to open **Manage > Stores**.
3. Add a store and at least one location.
4. Set the location as default if it should open automatically.

148
Troubleshooting.md Normal file

@ -0,0 +1,148 @@
# Troubleshooting
Use this page for common user, admin, and developer problems.
## I Cannot Log In
Check:
- Username is lowercase or can be lowercased by the app.
- Password is correct.
- Backend is running.
- `JWT_SECRET` is configured.
- The browser can reach the backend API URL.
- Cookies are not blocked for the app origin.
For developers, inspect the response status and `request_id`. Do not log session cookies or tokens.
## I Am Logged Out Unexpectedly
Possible causes:
- Session expired.
- Session row was deleted.
- Backend `SESSION_COOKIE_NAME` changed.
- Browser cookie storage was cleared.
- Frontend and backend origins changed and cookies no longer match CORS/cookie rules.
Log in again after confirming the backend is healthy.
## I Have No Household
Create a household or open an invite link. If invite links fail:
- Confirm the link has not expired.
- Confirm the household join policy accepts new joins.
- If approval is required, wait for an owner/admin to approve the request.
## I See No Stores
This means the active household has no usable store location.
1. Confirm the active household is correct.
2. Ask an owner/admin to open **Manage > Stores**.
3. Add a store and location.
4. Set a default location if needed.
## Suggestions Or Zones Look Wrong
Check:
- Active household.
- Active store location.
- Location zones in **Manage > Stores**.
- Available items in **Manage > Stores > Manage Items**.
- Whether current list items should be imported into the catalog.
## Image Upload Failed
Check:
- Browser network status.
- File type and size.
- `/config` image limit values.
- Upload toaster state.
- Retry the queued upload.
Developers should check the backend image middleware and the request ID from the failed response. Do not log image bytes.
## CORS Error
Backend CORS uses `ALLOWED_ORIGINS`.
Add the exact frontend origin, for example:
```text
http://localhost:3010
http://127.0.0.1:3010
http://localhost:5173
```
After backend env/CORS changes in Docker dev, recreate the backend service:
```bash
docker compose -f docker-compose.dev.yml up -d --force-recreate --no-deps backend
```
Then verify:
```bash
curl http://127.0.0.1:5000/
curl http://127.0.0.1:5000/config
```
## Migration Or Store Management Is Unavailable
Some store/catalog features require the latest database schema.
Check:
```bash
npm run db:migrate:status
npm run db:migrate:verify
```
Only run `npm run db:migrate` when the operator intends to apply migrations to the selected external Postgres database.
## Gitea Actions Failed
Check the failing job:
- Install dependencies.
- Audit.
- Lint.
- Typecheck.
- Backend tests.
- Migration stale check.
- Backend build.
- Frontend build.
- Docker image build/push.
- SSH deploy.
For deployment failures, verify Gitea secrets exist and are current. Do not print secret values in logs.
## API Returned 401 Or 403
401 means the request is not authenticated. 403 means the authenticated user lacks the required role or membership.
Check:
- User is logged in.
- Session cookie is present.
- Token in local storage is current.
- User belongs to the target household.
- User has owner/admin role for management actions.
- System admin user has the `system_admin` role for `/admin`.
## API Returned 500
Use the `request_id` in the response and backend logs to trace the failure.
Common causes:
- Missing environment variable.
- Database connection failure.
- Pending migration.
- Invalid data shape not handled by the route/controller.
- Image processing failure.

101
User-Guide.md Normal file

@ -0,0 +1,101 @@
# User Guide
This guide explains the normal shopping workflow.
## Sign In Or Register
1. Open the app in a browser.
2. Use **Register** to create an account, or **Login** if you already have one.
3. Usernames are normalized to lowercase.
4. Passwords must be at least 8 characters.
The app keeps you signed in with a secure session cookie. If your session expires, the app redirects you back to login.
## Create Or Join A Household
A household is the group that owns lists, stores, locations, invite links, and members.
If you have no household:
1. Open the household prompt from the main list or manage area.
2. Choose **Create Household** to start a new household.
3. Choose **Join Household** if someone sent you an invite link.
If you belong to multiple households, use the household switcher in the navigation bar. The app remembers the active household in your browser.
## Choose A Store Location
The grocery list is scoped to a household store location.
1. Use the store tabs near the top of the grocery list.
2. Pick the location you are shopping at.
3. If there are no stores, ask a household owner/admin to add one from **Manage > Stores**.
The app remembers the active store location for each household.
## Add Grocery Items
On the main list:
1. Type an item name.
2. Set the quantity.
3. Choose **Add** or **Create + Add**.
4. If the item already exists, confirm whether to add to the existing quantity.
5. Optionally add item details, classification, notes, or an image when prompted.
Suggestions appear from the household/location catalog and previous items.
## Mark Items Bought
Use the item action to mark an item as bought. Depending on your settings, the app may ask you to confirm before buying.
Bought items move out of the active list and can appear in **Recently Bought (24HR)**. This section helps recover accidental purchases or review what was just picked up.
## Search The List
Use **Search list** to filter visible list items. Search works on the current household/location list.
When search is active:
- Matching items remain visible.
- Empty zone sections are hidden.
- Collapsed zones are expanded for easier scanning.
## Images
Items can have product images. Images are uploaded through the app and processed by the backend.
If the network drops during an image upload:
- The upload queue keeps track of the failed upload.
- The upload toaster shows progress, success, or failure.
- You can retry or discard a failed upload.
Do not upload sensitive photos or receipt images unless the feature you are using explicitly expects them.
## Settings
Open **Settings** from the user menu.
Available settings include:
- Theme: light, dark, or auto.
- Recently bought visibility.
- Number of recently bought items to show.
- Whether recently bought starts collapsed.
- Confirm before marking bought.
- Auto reload interval.
- Haptic feedback.
- Debug mode.
Settings are stored in your browser for your username.
## Permissions You May See
Fiddy has two role layers:
- System role: normal users generally use the app; system admins can access the admin panel.
- Household role: owner, admin, or member within each household.
Household owners/admins can manage members, invite links, stores, locations, zones, and catalog defaults. Members can use the list and participate in household shopping.