🎉 initial commit

This commit is contained in:
2026-09-09 17:49:49 +02:00
commit 9dee2a4013
8 changed files with 80 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
# One server and database per Kitchen
Even though this codebase is built as a reusable template deployed to many ghost-kitchen operators, each Kitchen runs its own independent server and database with exactly one Brand — there is no central multi-tenant backend or cross-kitchen data layer. We chose this over a shared multi-tenant SaaS backend because each Kitchen's server talks directly to that Kitchen's own microcontrollers/machines, and keeping deployments fully independent avoids coupling physical hardware control to a shared cloud service. The trade-off: no built-in cross-kitchen reporting or central admin — any future need for that requires a separate aggregation layer, not a schema change to this one.
@@ -0,0 +1,3 @@
# Order Items are independent, not the Order
Preparation, queuing, pickup, and cancellation are all tracked per Order Item, not per Order. An Order is just a bundle that is "complete" once every Order Item in it has been picked up — but each Order Item cooks on its own Machine, becomes ready on its own, gets notified and picked up on its own, and can be cancelled on its own (locked only once its own first Preparation Step starts). We chose this over treating the Order as the atomic unit because items in the same order can have very different cook times (a pizza vs. a burger); forcing them to stay in lockstep would mean a finished item goes cold waiting on a slower one, or a customer loses the ability to cancel a not-yet-started item just because a sibling item already started cooking.
@@ -0,0 +1,3 @@
# Machine-Tag pool with dynamic assignment
Machines are grouped by capability (Machine Tag, e.g. "oven", "grill", "assembly") into a shared pool per tag, rather than a Preparation Step being pinned to one specific machine at order time. When a Step reaches the top of its tag's Queue, it is dynamically assigned to whichever Machine carrying that tag is idle. We chose dynamic pool assignment over static per-machine queues because a Kitchen can have multiple Machines of the same tag, and pinning a Step to a specific machine up front would let a customer's order sit stuck behind one busy oven while a sibling oven of the same tag sits idle.