The problem
A laundry handling dozens of households a day tracks garments by memory, chalk marks and paper slips. Items get separated from their batch. When a customer says a shirt is missing, there is no record on either side. Two people have different recollections, and the shop pays for the shirt to keep the customer.
What I built
Every item gets a printed barcode at intake, bound to a household. The counter UI creates or looks up a household, adds items with their type, and prints a receipt matching the format the shop already used. Status moves with the garment through the shop, and the customer gets a WhatsApp update that the system composes and a person sends.
The constraint that shaped it
The shop counter is one Windows PC, run by staff who are not going to install Python, and the internet connection is not guaranteed.
That drove the architecture. The application is a FastAPI service with server-rendered pages, so there is no build step and no node_modules on a shop counter. PyInstaller packages it into an executable with a launcher, so it starts from an icon on the desktop. Postgres lives in Supabase so the data survives the machine.
This is the least technically ambitious project here and the one I learned the most from, because the hard constraints were all non-technical: what the staff will tolerate, what breaks when the shop is busy, and how a system fails when the person using it is in a hurry.
Media






How this was built
The spec sheet above lists the stack. This section covers how the work was run, which a screenshot cannot show you.
Where AI did the work
- Generated the schema, ORM models and validation layer as one coherent pass so the database constraints and the Pydantic schemas enforce the same rules instead of drifting apart.
- Kept a running progress log across sessions, so each one resumed from the recorded state of the build instead of a guess at it.
The discipline around it
- Architecture and setup are separate documents from the README: one for someone extending the code, one for someone trying to get it running on the shop counter.
- Receipt rendering was built against photographs of the receipts the shop already used, rather than a layout I invented.
What stayed human
- Nothing auto-sends to a customer. The WhatsApp message is composed by the system and released by the person at the counter, because a wrong automated message to a customer is worse than no message.
- Barcode uniqueness is enforced at the database level rather than in application logic, since a duplicate tag would undo everything the system is for.