- use the defined toolkit (e.g. uv, ruff, ty, yarn, biome) for dependency management and code quality
- Ensure tests are still succeeding after making a change, if a test exists
- Do not implement unasked extra features or edge cases, if you think they are crucial, you need to ask for permission first
- new dependencies need to work especially under unix (Raspberry Pi) systems
- v1 (Qt): Desktop app using PyQt6, run via
runme.pyorjust qt - v2 (Web): React frontend + FastAPI backend, run via
just api+just web - Unless specified otherwise, features should target both versions
src/- Main Python source (shared between v1/v2)src/ui/- Qt UI setup code (v1 only)src/api/- FastAPI routers & endpoints (v2 backend)web_client/src/- React components (v2 frontend)tests/- Pytest testsdashboard/- Separate analytics dashboard app
Shared code (used by both v1 and v2):
src/database_commander.py- Database operationssrc/models.py- Core data modelssrc/machine/- Hardware controlsrc/config/- Configuration handling
Version-specific code:
src/ui/- Qt only (v1)src/api/- FastAPI only (v2)
src/config/- Configuration management modulecustom_config.yaml- User customization fileweb_client/.env.*- Web client environment settings
Key modules use singletons — never instantiate new copies, always import the existing instance:
- Via
__new__:MachineController(src/machine/controller.py),NFCPaymentService(src/service/nfc_payment_service.py) - Module-level instances:
DB_COMMANDER(src/database_commander.py),CONFIG/shared(src/config/config_manager.py),DIALOG_HANDLER(src/dialog_handler.py),ADDONS(src/programs/addons.py)
just python-check- ruff lint + format check + ty type checkjust python-test- pytest with coveragejust python-fix- auto-fix lint and formattingjust web-lint/just web-format- web client checks
- Python: User-facing text uses
DialogHandlerwith keys fromsrc/language.yaml - Web client: i18next with translation files in
web_client/src/locales/
- SQLite + SQLAlchemy ORM, models in
src/db_models.py - Tests use in-memory SQLite (
sqlite:///:memory:) via thedb_commanderfixture