Skip to content

Chris-421/STYLE

Repository files navigation

STYLE

STYLE is an AI-guided fragrance discovery application. A user supplies one to five visual references, reviews an editable interpretation built from a controlled 154-label visual vocabulary, adds practical scent preferences, and receives five differentiated fragrances from the bundled 500-record catalogue. Structured feedback after physical testing deterministically changes the next selection.

STYLE never lets a language model choose or invent a fragrance. AI performs one multimodal visual translation, can regenerate the controlled Style Card from an explicit short user instruction, and may polish the prose for all five already-ranked fragrances in one small text request. Catalogue selection, signal derivation, fallbacks and learning remain inspectable TypeScript functions over local sourced data.

Architecture at a glance

  • React 19, strict TypeScript, Vite and React Router power a mobile-first single-page interface.
  • Zod validates Style Profile v0.2, controlled labels, fragrance signals, preferences, feedback and local profile migrations.
  • A deterministic local engine follows controlled visual label → editorial fragrance signal → catalogue evidence, then applies five role-specific selectors with diversity penalties.
  • Anonymous state lives behind a persistence interface backed by localStorage; image bytes are excluded.
  • Cloudflare Pages Functions expose /api/style/analyze, /api/style/refine, /api/recommendations/copy and /api/health.
  • Production analysis uses a Workers AI binding; local development defaults to a deterministic mock provider.
  • Vitest, Testing Library and Playwright cover domain rules, accessible UI states and the essential journey.

The visual system follows the supplied Etheric Brutalism references: dramatic Bodoni display type, Syne body text, Space Mono metadata, hard borders, asymmetric overlap, and restrained atmospheric cyan/pink fields.

Local setup

Requirements: Node.js 22+ and npm 10+.

npm install
copy .env.example .env.local
npm run dev

Open http://localhost:5173. VITE_AI_PROVIDER=mock enables the complete offline journey. The mock result is deliberately labelled and does not claim to inspect pixels.

Environment

Variable Runtime Purpose
VITE_AI_PROVIDER browser build mock for Vite-only local development or cloudflare to call the Pages Function
AI_PROVIDER Pages Function mock or cloudflare; production default is cloudflare
AI_MODEL Pages Function Workers AI model, default @cf/google/gemma-4-26b-a4b-it

No secret token belongs in any VITE_* variable. Workers AI production access uses the AI binding.

Local Workers AI

Workers AI calls may consume quota. After authenticating Wrangler and accepting the model licence, build and run:

npm run build
npx wrangler pages dev dist --ai AI

Set VITE_AI_PROVIDER=cloudflare before the build and keep AI_PROVIDER=cloudflare. If the binding, quota or model is unavailable, the UI offers a manual Style Card route.

Quality commands

npm run validate:data
npm run typecheck
npm run lint
npm run test
npm run build
npx playwright install chromium
npm run test:e2e

npm run quality runs catalogue validation, type checking, lint, unit/component tests and the production build. Playwright is separate because its browser binary is an environment-level install.

Fragrance data

The app imports data/fragrance_top500_v0.2.json directly and never mutates it. scripts/validate-data.mjs checks each of the 500 records against data/fragrance_record_schema_v0.2.json, verifies the declared count and rejects duplicate IDs before every production build.

To replace or extend the catalogue:

  1. Keep each record at schema version 0.2, or add an explicit migration and update the runtime types.
  2. Preserve source IDs, confidence fields, warnings and nulls.
  3. Update dataset_metadata.record_count.
  4. Run npm run validate:data and the recommendation tests.
  5. Review every new user-facing fact for supporting source data.

The app never shows price or current availability from this dataset because no record contains the required current verification. Neutral typographic placeholders are used instead of fabricated bottle images.

Privacy behaviour

The browser validates JPEG/PNG/WebP files, rejects originals over 8 MB, resizes the longest side to 1024px, re-renders through canvas to strip common metadata and encodes WebP. Prepared blobs exist only in memory and the analysis request; object-URL previews may remain temporarily while the user reviews the Style Card, then are revoked. Source images are not stored in localStorage, a database, object storage, analytics or application logs.

Only the resulting Style Profile, the latest short Style Card refinement instruction, scent preferences and testing history are stored in the current browser. A refinement request is text-only and never resends reference images. The profile page can delete all stored data. Analysis and refinement prompts explicitly prohibit demographic, sensitive, attractiveness, health and psychological inference.

Cloudflare deployment

The free-hosting path is Cloudflare Pages with Pages Functions and a Workers AI binding:

npm ci
npm run quality
npm run build
npx wrangler login
npx wrangler pages project create style-fragrance-discovery
npx wrangler pages deploy dist --project-name style-fragrance-discovery

In the Pages project, add a Workers AI binding named AI and variables AI_PROVIDER=cloudflare and AI_MODEL=@cf/google/gemma-4-26b-a4b-it, then redeploy. Static routes are excluded from Function invocation by public/_routes.json. Verify the deployed /api/health and full analysis journey before considering the release complete. See deployment-cloudflare.md for the exact checklist.

Documentation

Current limitations

The catalogue has no currently verified prices, availability or official-brand sources. Wearing context and performance are sparse and therefore usually neutral in scoring. Local profiles do not sync. The mock provider is a deterministic fixture, while production analysis requires a configured Cloudflare account, accepted model licence and available Workers AI quota. See known-limitations.md for the full list.

About

A Webapp that allows one to find their fragrance and discover the world of parfume based on their personal sense of style, fashion, aesthetic.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages