Files
bblaz 39dd474813
ci/woodpecker/push/woodpecker Pipeline was successful
Align stock API with paginated backend and bump to v0.2.2
2026-04-12 17:57:53 +02:00

7.2 KiB

Lonc Agent Guidelines

This document is the working guide for future coding agents on the Lonc frontend.

Project purpose

Lonc is a lightweight PWA frontend for household kitchen stock and labeling workflows.

The frontend:

  • talks to a separate Tryton backend
  • uses Tryton user application keys for auth
  • is optimized for phone and desktop use
  • prefers practical, high-frequency operational UX over generic CRUD

Core stack

  • Vite
  • Alpine.js
  • Bootstrap 5
  • plain fetch() API modules
  • static PWA assets in public/

General operating procedure

When changing this project, follow this order:

  1. Find the existing feature module instead of adding parallel logic.
  2. Prefer updating shared API helpers before patching individual pages.
  3. Preserve the existing UX language and interaction patterns.
  4. Verify with npm run build.

For larger behavior changes:

  1. Check the relevant API module in src/api/
  2. Check the page module in src/features/
  3. Check supporting shared state in src/app/
  4. Check matching CSS in src/styles/app.css

Key architecture rules

API usage

  • All HTTP requests should go through src/api/client.js
  • Do not build ad hoc URLs in feature components
  • Use getPath() and shared API modules in src/api/
  • Prefer same-origin requests when baseUrl is empty
  • Keep custom headers minimal

Auth model

Lonc does not use Tryton JSON-RPC session login.

It uses Tryton user application keys for the kitchen application:

  1. POST /{database}/user/application/
  2. store returned key locally
  3. user validates key in Tryton preferences
  4. frontend verifies with authenticated kitchen request

Relevant session states:

  • not_connected
  • pending_validation
  • connected
  • invalid_key

If authenticated requests start failing after a key had previously worked, the app should move toward invalid-key handling instead of repeatedly hitting the backend.

Service worker

  • In development, service workers should not stay registered
  • In production, avoid sticky caching for JS/CSS
  • Be careful when debugging frontend/API mismatches because stale cached bundles have already caused confusion in this project

Current backend conventions

These are current project assumptions and should not be casually changed.

Main endpoints

  • /{database}/user/application/
  • /{database}/kitchen/kitchens
  • /{database}/kitchen/items
  • /{database}/kitchen/items/upsert
  • /{database}/kitchen/items/grouped
  • /{database}/kitchen/items/{uuid_b64}
  • /{database}/kitchen/items/{uuid_b64}/stock
  • /{database}/kitchen/items/{uuid_b64}/use
  • /{database}/kitchen/changes
  • /{database}/kitchen/locations

Labels

  • Preview uses label-preview flags
  • Submit/create flow uses upsert apply (/kitchen/items/upsert?mode=apply)
  • UI exposes a Print checkbox next to save (default on for current page session)
  • If Print is enabled and save succeeds, label printing uses /kitchen/items/{uuid_b64}/print-label

Item-definition search for label creation

The label form does not search items directly anymore.

It now searches grouped items:

  • GET /{database}/kitchen/items/grouped?search_name=...&expanded=0

Reason:

  • grouped result is a better template for “new item from existing definition”
  • not expanding children keeps the query lighter

List pagination

  • GET /{database}/kitchen/items and GET /{database}/kitchen/items/grouped are paginated (limit/offset, backend default limit=100)
  • frontend API helpers aggregate pages when no explicit limit/offset is requested

Grouped stock view

Grouped stock view uses:

  • GET /{database}/kitchen/items/grouped?expanded=0 for summary
  • GET /{database}/kitchen/items/grouped?expanded=1 for hydrated child details

Important:

  • group-level fields are meaningful and should be used
  • group expiration status should follow the backend-provided “first item expires” semantics
  • with expanded=0, grouped child items may be ID-only stubs ({ id })
  • do not assume grouped child records are fully returned unless expanded=1

Stock updates

  • POST /{database}/kitchen/items/{uuid_b64}/stock creates a stock event and returns { status, stock }
  • frontend refreshes item details with GET /{database}/kitchen/items/{uuid_b64} after stock updates

UX rules that should be preserved

Label creation

  • Required fields must be clearly marked with a red asterisk
  • Required-field validation should happen before both preview and create
  • Quantity is always visible
  • Quantity is required only for measured
  • Production date is required
  • changing production date should keep expiration calculations in sync
  • item-definition selection should act like copying defaults for a new item, not cloning old dates blindly
  • location picker and expiration day picker were tuned for Safari/iPhone behavior, so be cautious when changing event handling

Stock review

This is an operational page, not a generic data table.

Priorities:

  • expiration visibility
  • stock state clarity
  • location clarity
  • quick actions
  • phone usability

Do not degrade it into a dense admin CRUD screen.

Filters and overviews

Stock page filtering is intentionally overview-driven:

  • main text search
  • Expiration overview
  • Location overview

The overviews:

  • are collapsible
  • are collapsed by default
  • act as filter controls
  • should remain visually understandable on both small and large screens

Normal and grouped stock views

These two views should feel related.

  • same filter concepts
  • similar visual language
  • direct “view item” access should exist in both
  • grouped view should stay compact by default

Known project-specific decisions

  • Quantity prefill on label creation comes from quantity_initial, not quantity
  • grouped label search should use grouped entities as source defaults
  • grouped expiration logic should rely on backend-provided group semantics
  • location filtering includes descendants when parent is selected
  • removing a parent location from filters removes its selected children too
  • grouped child item cards use softer expiration colors than the parent group card

File map

App shell and state

  • src/app/bootstrap.js
  • src/app/router.js
  • src/app/store.js
  • src/app/config.js

API layer

  • src/api/client.js
  • src/api/auth.js
  • src/api/stock.js
  • src/api/locations.js
  • src/api/labels.js

Main feature pages

  • src/features/auth/login-page.js
  • src/features/auth/settings-page.js
  • src/features/labels/label-create-page.js
  • src/features/stock/stock-list-page.js
  • src/features/stock/stock-detail-page.js

Styling

  • src/styles/app.css

Editing guidance for future agents

  • Keep behavior centralized where possible
  • Reuse existing helpers instead of inventing near-duplicates
  • Be careful when modifying auth invalidation, service worker behavior, or custom pickers
  • If changing endpoint behavior, update both API modules and README/AGENTS notes when appropriate
  • When changing interactive UI, test the desktop and small-screen behavior mentally at minimum

Verification expectation

After meaningful frontend changes, run:

npm run build

If behavior depends on caching, auth, or service workers, mention that explicitly in the handoff.