[{"data":1,"prerenderedAt":195},["ShallowReactive",2],{"case-study:\u002Fcase-studies\u002Fbinventory":3},{"id":4,"title":5,"body":6,"date":184,"description":185,"extension":186,"meta":187,"navigation":188,"path":189,"provenance":190,"sensitivityReviewed":191,"seo":192,"sources":191,"stem":193,"__hash__":194},"caseStudies\u002Fcase-studies\u002Fbinventory.md","A Phone-First Whole-Home Inventory System",{"type":7,"value":8,"toc":173},"minimark",[9,14,18,21,24,28,31,66,70,73,93,100,103,106,109,113,119,125,131,137,141,144,147,151,154,157,160,164,167,170],[10,11,13],"h2",{"id":12},"problem","Problem",[15,16,17],"p",{},"I wanted to solve a real household problem: knowing what we own, where it is, and\nwhat maintains it. Manuals get lost, warranties lapse unnoticed, and nobody\nremembers which bin holds the spare cables. I did not want a spreadsheet or a\ncloud service that would ask the household to create accounts and hand our\nbelongings to someone else's servers.",[15,19,20],{},"The design goal was a system I could use while standing in a closet with a phone\nin one hand. Every bin, drawer, appliance, and standalone item gets a printed QR\nsticker; scanning it opens that thing's page, showing its contents, photos,\nmanuals, appliance details, and maintenance history. The people who use it are my\nown household, on our own network, so the product could make assumptions a public\nSaaS never could.",[15,22,23],{},"This case study is an architecture and engineering-decisions write-up. The\nrepository is private and under active development, so it is not linked here, and\nevery example in this write-up is generalized: no real household data, addresses,\nor photos appear.",[10,25,27],{"id":26},"constraints","Constraints",[15,29,30],{},"The application is private and runs only on the home network, which shaped nearly\nevery decision.",[32,33,34,42,48,54,60],"ul",{},[35,36,37,41],"li",{},[38,39,40],"strong",{},"No accounts."," Access is bounded by the trusted home Wi-Fi, so the app has no\nlogin. Anyone on the network can view and edit everything. That removed an\nentire authentication and authorization surface but meant I had to solve\naccountability a different way.",[35,43,44,47],{},[38,45,46],{},"Local-first and private."," Nothing about the household leaves the house. Data\nlives in a local database on a single always-on machine, and the AI features\nrun on that same machine rather than calling a cloud API.",[35,49,50,53],{},[38,51,52],{},"Phone-first and offline-capable."," The primary device is a phone used away\nfrom a desk, sometimes in a garage or basement with weak signal, so the app had\nto install like a native app and keep working offline.",[35,55,56,59],{},[38,57,58],{},"A secure origin without a public domain."," The in-app camera scanner and\noffline installation require a secure (HTTPS) origin, which is awkward on a LAN\nthat has no public domain and no public certificate authority.",[35,61,62,65],{},[38,63,64],{},"Deliberately modest scale."," This serves one household. A local database and a\nsingle host are correct product constraints here, not a claim that the same\ndesign should serve an internet-scale application.",[10,67,69],{"id":68},"architecture","Architecture",[15,71,72],{},"Binnie (formerly Binventory) is a Next.js 15 application using the App Router, written in\nTypeScript with React, and styled with Tailwind CSS v4. Persistence is a local\nSQLite database accessed through Prisma, with schema changes managed as versioned\nmigrations.",[15,74,75,76,79,80,84,85,88,89,92],{},"The domain model is the heart of it. A ",[38,77,78],{},"label"," is either a ",[81,82,83],"em",{},"container"," (a bin,\ndrawer, or box that holds items) or a ",[81,86,87],{},"single item"," (like an appliance), and both\nget printable QR codes. Labels live in rooms; items live in containers; and a\n",[38,90,91],{},"manuals library"," links PDF manuals and links to any number of labels and items\nthrough a many-to-many relationship, so one furnace manual can belong to both the\nfurnace and the utility closet without duplication. On top of that sits an\nappliance passport (model and serial numbers, purchase and warranty dates, and a\ndated maintenance log) and a consumables model that tracks stock levels and\ngenerates a shopping list automatically.",[15,94,95,96,99],{},"Because there are no accounts, every label keeps an ",[38,97,98],{},"append-only activity\nhistory",", and the home page shows a recent-activity feed across the whole house.\nIt is a convenience log rather than an audit trail, so it records what happened\nwithout recording who did it, and it makes an accidental change easy to spot and\nundo.",[15,101,102],{},"Two capabilities run as on-device AI rather than cloud calls. A local semantic\nsearch matches by meaning as you type, is tolerant of typos, and never sends a\nquery off the machine. A vision assistant powers batch cataloging and\nserial-number extraction: you photograph a shelf of items and the model proposes\nwhat each one is, or re-reads existing photos to propose model and serial numbers.\nEvery proposal is reviewed and editable before it is applied, and a batch can be\nundone in one step. The AI proposes; a human confirms.",[15,104,105],{},"The app serves a secure origin over the LAN using a certificate authority created\nonce for the household, whose keys never leave the machine; each phone enrolls\nonce, and the old insecure address permanently redirects so that already-printed\nQR stickers keep working. It installs as a Progressive Web App with offline\nsupport for pages already visited.",[15,107,108],{},"Development is spec-driven. Each feature area is a numbered specification folder\nwith its own plan and quickstart, so the requirements, the design, and the\nverification steps for a feature live together and precede the code.",[10,110,112],{"id":111},"tradeoffs","Tradeoffs",[15,114,115,118],{},[38,116,117],{},"No accounts, an activity log instead of an audit trail."," Because the trust\nboundary is the home network, adding logins would have been friction with no\nsecurity benefit for this deployment. The cost is that the app cannot attribute a\nchange to a person, so I chose an append-only, blame-free history that still makes\nmistakes visible and reversible. It is the right trade for a household and the\nwrong one for a shared public system, and I kept that boundary explicit.",[15,120,121,124],{},[38,122,123],{},"SQLite and a single local host over a managed database."," For one household on\none network, a local database removed all operational overhead and kept the data\nprivate by construction. The trade is that this design does not scale horizontally\nand was never meant to; I treated that as a deliberate product constraint rather\nthan a limitation to apologize for.",[15,126,127,130],{},[38,128,129],{},"On-device AI over cloud APIs."," Running the vision and search models on the\nlocal machine keeps every photo and query inside the house and removes per-call\ncost, at the expense of being bound by local hardware rather than a large hosted\nmodel. To keep that honest, the AI never acts on its own: batch identification and\nserial extraction always produce reviewable proposals, and nothing is written\nuntil a person confirms it.",[15,132,133,136],{},[38,134,135],{},"A household certificate authority over plain HTTP or a public certificate."," A\nsecure origin is what unlocks the camera scanner and offline installation on\nphones, and a LAN with no public domain cannot obtain a normal certificate. A\nprivate certificate authority plus a one-time per-device enrollment buys a real\nsecure origin locally, at the cost of a short enrollment step on each new phone.",[10,138,140],{"id":139},"testing","Testing",[15,142,143],{},"The application uses a Vitest suite, run against a database that is separate from\nboth development and production. The spec-driven workflow is part of the testing\nstrategy: each feature's quickstart is a written procedure I validate the feature\nagainst, so acceptance is defined before the code is written rather than\nrationalized after it.",[15,145,146],{},"Data safety gets particular care because a home inventory is only useful if it is\ntrustworthy. Development, test, and production each use their own database file, so\nschema experiments never touch live data; migrations are exercised against a\nthrowaway snapshot before they are deployed; and a nightly backup export runs on a\nschedule with the application surfacing how fresh the most recent backup is.",[10,148,150],{"id":149},"results","Results",[15,152,153],{},"Binnie is a working, installed application that the household uses. Printed QR\nstickers open the right page on any phone on the network, manuals and warranties\nand consumables live in one place instead of scattered across drawers and inboxes,\nand cataloging a shelf is a matter of taking photos and confirming what the\non-device assistant proposes.",[15,155,156],{},"Its stickers survived a migration of the app's own address because the old origin\npermanently redirects to the secure one, so nothing printed had to be reprinted.\nSearch finds things by meaning without anything leaving the house, and the\nrecent-activity feed has already earned its place by making an accidental archive\neasy to notice and restore.",[15,158,159],{},"It remains a private project under active development, and I describe it here at\nthe level of its architecture and engineering decisions rather than through\nscreenshots of a real home.",[10,161,163],{"id":162},"what-id-change-and-what-i-learned","What I'd Change and What I Learned",[15,165,166],{},"The clearest lesson was how much leverage a precise domain model carries. Getting\nthe label-versus-item distinction and the many-to-many manuals relationship right\nearly made later features (consumables, the appliance passport, the activity feed)\nfeel like small additions rather than structural changes. When I was tempted to\nshortcut the model, that was exactly when I should have slowed down.",[15,168,169],{},"The second lesson was that on-device AI is most useful when it is bounded. The\nvision assistant is valuable precisely because it proposes rather than decides, and\nbecause a person reviews every batch before it is written. If I extended it, I\nwould keep that shape and resist letting the model write directly to the database,\nhowever confident it seemed.",[15,171,172],{},"If I were starting over, I would define the backup and restore procedure, the\ndev-test-production data separation, and the secure-origin story before building\nfeatures rather than alongside them. Those operational concerns are what make a\nhousehold actually trust the app with the real contents of their home, and they\ndeserved to be first-class from the first commit.",{"title":174,"searchDepth":175,"depth":175,"links":176},"",2,[177,178,179,180,181,182,183],{"id":12,"depth":175,"text":13},{"id":26,"depth":175,"text":27},{"id":68,"depth":175,"text":69},{"id":111,"depth":175,"text":112},{"id":139,"depth":175,"text":140},{"id":149,"depth":175,"text":150},{"id":162,"depth":175,"text":163},"2026-07-22","A private, phone-first home-inventory application built around QR labels, an on-device AI catalog assistant, and a LAN-only secure origin, developed as a spec-driven personal project.","md",{},true,"\u002Fcase-studies\u002Fbinventory","personal_ai_assisted",null,{"title":5,"description":185},"case-studies\u002Fbinventory","3r91vN8FB9oAh8zUmNugJmgUJpUSxUGcL88cGtOd9BQ",1788403975816]