Wardrobe
A clothing inventory that outgrew Airtable
A Rails app for managing a clothing inventory, replacing an Airtable base that had outgrown the tool. Items carry photos, categories, and colours; the index offers a gallery and a list view; and /outfit proposes something to wear.
Two interface details worth the trouble
Infinite scroll that degrades. Items load 48 at a time and append as you scroll, but the sentinel at the bottom of the page is a real <a href="?page=N">. With JavaScript off it is ordinary next-page navigation rather than a dead end.
A search field that keeps its focus. The search form is rendered outside the frame it updates. Inside it, the field was destroyed and rebuilt on every keystroke — which on a phone dropped focus and closed the keyboard mid-word. It also replaces a single history entry as you type instead of stacking one per keystroke, so Back means “leave search” rather than “delete one letter”.
The outfit suggester is shaped by the actual data
Two facts from the real wardrobe drove the whole design, and both are the kind of thing you only learn by looking:
- 48 of the 175 “tops” are jackets or coats. Outerwear is separated into its own layer category so it is offered over a garment and never as the primary one — otherwise a suggestion is “wear this wool coat” and nothing else.
- 43% of the wardrobe is black, and 70% is black, navy, grey or white. Colour-pairing rules would almost never fire, so they aren't implemented. Pretending otherwise would be decoration, not logic.
- The scarce resource is attention, not clothing. With 175 tops the same handful get worn, so selection draws from the least-recently-suggested quarter of the candidates for each role. Forgotten items resurface on their own.
The random seed lives in the URL, so a suggestion is reproducible and shareable rather than a one-time roll you can never get back.
Throwing something out shouldn't delete history
A saved outfit's garment references are ON DELETE SET NULL, so getting rid of a sweater leaves a gap in the outfits that used it instead of destroying them. The outfit's kind — dress or separates — is stored rather than inferred, because once a garment is nulled you can no longer tell a dress outfit missing its dress from a separates outfit.
Outfits can also be built by hand, posting to the same controller with the same checks, and the pickers are driven by the very scopes the suggester draws on — so the builder offers exactly what a suggestion could have contained.