Add end-to-end Outfits experience with demo mode - #7
Draft
bwu640 wants to merge 7 commits into
Draft
Conversation
Build the missing Outfits feature so the generate-outfits skill's output is finally usable in the app, and make the whole app explorable without an OpenAI key. - Add outfits store (normalization, filesystem CRUD, crash-safe atomic writes) shared with the import pipeline via a new fs-utils module. - Add /api/import/outfits routes (list/create/read/update/delete/generate) plus outfit image serving, wired into the existing Vite-middleware backend. - Outfit image generation uses OpenAI when configured and falls back to a local sharp flat-lay composite (demo mode) otherwise. - Add an Outfits gallery, outfit builder, and detail viewer in the app with a top-level Wardrobe/Outfits nav, empty/loading/error/unconfigured states, and onboarding copy. - Persist gallery edits to library.json through a new wardrobe PATCH route, migrating and retiring the old localStorage-only edits. - Add scripts/seed-demo.mjs and a seed:demo script for a no-key demo wardrobe. - Add Vitest with tests for outfit normalization/persistence and pipeline helpers; check now runs tests before build.
Set Vite base to './' so built index.html references JS/CSS with relative URLs, fixing 404s when dist is served from a nested path. Runtime /api fetches are unaffected, preserving dev/preview backend path handling.
Add src/api.js with apiUrl() that prefixes root-relative /api and /_ipx requests with a deploy proxy prefix. deploy_website rewrites the literal __PORT_4173__ token to the proxy path when hosting dist from a nested URL; locally the token is untouched, so requests stay same-origin and dev/preview are unchanged. Wire every wardrobe, Outfits, import, and image URL through the helper.
The Outfits card art, card placeholders, garment picker thumbnails, and viewer piece thumbnails rendered /api/... paths via plain <img> tags, bypassing apiUrl() and 404ing on nested hosted deployments. Route every outfit image src (including cache-busting query strings) through apiUrl(). Extract pure normalizePrefix/joinApiPath helpers and add tests covering local same-origin, path/full-URL proxy prefixes, query-string preservation, and no double-prefixing.
The Vite middleware backend and filesystem persistence only run under dev/preview, so static hosts have no /api. Add a VITE_DATA_MODE=browser build that serves the same /api/import/... shapes from a bundled demo JSON (base64 data URLs) plus localStorage, with client-side canvas outfit previews. Persistence is per-browser only and documented as such. - api.js: DATA_MODE flag + apiFetch dispatching to in-browser adapter - data-browser.js: localStorage-backed adapter for wardrobe/outfits CRUD - demo-fixtures.mjs: shared garment/outfit fixtures for both seeders - seed-demo-static.mjs: emits public/demo-data.json for the static build - vercel.json + build:vercel script; README deployment + limitation notes
Introduce server-side Vercel functions for the deployed app so real garment photos, outfits, generated cutouts/previews, and a private model reference photo persist durably across devices via Vercel Blob (with a local filesystem fallback for dev/tests). All routes are gated by a shared app passcode that is stored only in env and exchanged for an HttpOnly, Secure, SameSite=Lax HMAC-signed session cookie; login attempts are rate-limited per instance. - Extract the OpenAI/image pipeline into scripts/wardrobe-core.mjs, shared by the Vite middleware and the new backend to avoid duplication. - api/_lib: keys (path-traversal-safe normalization), storage (Blob + local), auth (passcode/session/rate limit), http adapters, and a transport-agnostic router that runs generation synchronously (serverless-safe). - api functions: authenticated import catch-all, auth login/logout/session, and one-at-a-time bulk-import. Blob URLs are never exposed; assets stream through authenticated functions. - Frontend: passcode login gate + logout, 401 handling in apiFetch. The browser demo build is untouched (no backend, no gate). - scripts/bulk-import.mjs CLI for seeding garments and the reference photo. - Cost guardrails: 4MB upload cap, 5 garments/outfit, 500-item wardrobe. - Tests for auth, storage-key normalization, key builders, and API/bulk-import validation; production build wired via vercel.json + build:production. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
All Blob objects are written with access:'private' and read back through the authenticated SDK get() by pathname, so no Blob URL, token, or store id is ever returned to the client. Auth resolves to Vercel OIDC (VERCEL_OIDC_TOKEN + BLOB_STORE_ID) when present, otherwise a read-write token. On Vercel with no private store configured, data access fails closed with an exposable 503 instead of silently using the ephemeral filesystem. Config reporting no longer leaks the internal model-reference pathname. Adds tests asserting private access, OIDC threading, and fail-closed getStore. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a complete Outfits feature: backend outfits API with atomic filesystem persistence and crash-safe boot recovery, an in-app Outfits gallery, builder, and viewer, unified backend persistence for gallery edits, and an OpenAI-free demo mode so the app is fully explorable without an API key or reference photo.
Behavior
data/library.json; legacy localStorage edits migrate on load.Testing
npm run checkpasses.Generated by Computer