docs: create app wiki
parent
6a0ee1c92e
commit
06f4b3d139
123
Admin-and-Operations-Guide.md
Normal file
123
Admin-and-Operations-Guide.md
Normal file
@ -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
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
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
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.
|
||||
|
||||
82
Households-Roles-and-Invites.md
Normal file
82
Households-Roles-and-Invites.md
Normal file
@ -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
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.
|
||||
|
||||
75
Stores-Zones-and-Catalog-Items.md
Normal file
75
Stores-Zones-and-Catalog-Items.md
Normal file
@ -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
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
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.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user