Choosing an outfit starts with a few practical questions: how cold is it, where am I going, and which clothes are available? testPWA grew around that routine into Daily Wardrobe, a browser application that keeps garment photos, wardrobe data, and wear records on the device.
View the project and open the web app.
The main loop is short: add clothes, choose an outfit, record wearing it, and review how it felt. Reliability required more care than producing an outfit: images must survive edits, history must retain its meaning, and automatic suggestions must respect manual decisions.
One garment, several image roles
A list needs a thumbnail. Editing needs an original. Wear history needs the image from that moment. Copying one large image into every object makes those requirements expensive and difficult to separate.
Metadata lives in Dexie / IndexedDB. Images prefer OPFS, with an IndexedDB Blob fallback when usable file-writing support is absent. SHA-256 content identifiers deduplicate images; garments reference source files, display images, and thumbnails, which are read as needed.
Display images have a maximum edge of 1600 pixels, and thumbnails 320. Source files remain separate from crop and rotation parameters. Re-encoded display images omit EXIF, but original files can retain their original metadata. Local storage does not imply that all metadata has been removed.
Local writes still need concurrency control
Two browser windows can edit the same wardrobe. Without version checks, a stale window could overwrite a newer change.
The storage layer checks an expected revision, writes and verifies images in staging, then checks that revision again inside the IndexedDB transaction that publishes the new dataset. Only a successful commit switches the active pointer. A conflict asks the user to reload.
OPFS and IndexedDB do not share one transaction. Preparing images before publishing their references addresses that gap. Failed saves preserve the existing wardrobe; expired staging data and unreferenced assets can be reclaimed later.
Recommendations explain conditions; history preserves facts
The Today screen uses real weather and local rules to select up to three outfits, considering apparent temperature, occasion, thermal preference, colors, and recent wear. The function receives explicit weather input. This is rule-based ranking, not generative virtual try-on.
Missing weather produces a cache status, retry, or city-change option instead of invented conditions. Wardrobe management and custom outfits remain usable.
Wear records need more than garment IDs. Renaming or deleting a garment next week should not rewrite last week. Records retain the names, attributes, and image references from that moment. Repeating the same garment contents on the same local date and in the same time zone reuses the existing record.
The current wardrobe answers what is available now. A wear snapshot answers what was worn then.
On-device analysis must respect manual input
Optional analysis runs a quantized FashionCLIP image encoder through ONNX Runtime Web in a dedicated Worker, using CPU / WebAssembly. Classification and thickness suggestions reuse the same image embedding; local image processing extracts colors. Photos are not sent to a cloud inference service.
Model resources are cached separately from the application shell. Initial resources total about 97.4 MiB and are not fetched automatically on the first visit. Once fully cached, they can be read offline. Manual entry remains available when analysis is unsupported, disabled, or fails.
Form merging matters as much as inference. If a user renames a garment while analysis runs, a late suggestion must not overwrite it. Name, category, colors, and thickness track whether their values came from a default, the user, or analysis. Manual changes take priority, changing the image invalidates stale work, and undo restores only automatic fields that have not since been edited.
Thickness is estimated from appearance. Ambiguous results remain unknown, and shoes or bags do not receive forced fabric-thickness labels. Similarity scores are not accuracy percentages. Development checks on six example images cannot establish real-world accuracy.
A backup is useful only if restoration is safe
Local storage cannot prevent cleared browser data, device damage, or moving to another phone. Recoverable backup is part of the main workflow.
ZIP backups include personal garments, outfits, preferences, wear history, and associated images. Examples, drafts, weather cache, and rebuildable thumbnails are excluded. Restoration validates structure, fields, references, and images in separate staging storage, presents a preview, then switches the wardrobe after confirmation. Cancellation and validation failure leave the original intact.
Images are read and checked individually instead of copying the whole library into a large JavaScript buffer. A roughly 200 MiB backup experiment checks structure and file I/O, but does not establish memory behavior on every mobile browser.
The interface carries these decisions
Cream paper, burgundy accents, serif headings, and flat-lay garment images frame four stable sections: Today, Wardrobe, Outfits, and Profile. Example clothes stay separate from personal clothes, allowing exploration before collecting photos.
The visual design supports concrete behavior: filters are edited before application, closing an editor handles drafts, analysis is correctable, and restoration has a preview.
The app implements these core flows. Automatic background removal, account-based cloud sync, and virtual try-on are not integrated. Mobile offline cold starts, large restores, regional weather connectivity, and analysis accuracy still need real-device evaluation. The next step is testing those boundaries in everyday use.