Frontend Rework¶
The original web app was designed before the domain and real backend were settled. This work removed unsupported ideas, made scanning the main action, and created a clean boundary between the interface and its data source.
Task FR1: Remove Unsupported Features and Simplify Navigation¶
Like you're 5¶
The shop had doors for rooms that did not really exist, including rewards and an AI helper. We removed those doors and left three clear signs: Scan, Fridge, and Profile.
Normal Explanation¶
The Rewards route and AI chat component were removed because they were not part of the agreed domain or thin-slice scope. The separate Home tab was removed, and navigation was reduced to the three core areas: Scan, Fridge, and Profile.
Technologies used: Svelte components and routes define the interface; domain-driven design keeps the UI aligned with capabilities the system actually owns.
Task FR2: Scan-First Landing Page¶
Like you're 5¶
When visitors enter the shop, the first thing they now see is the scanner and their recent scans, instead of pretend scoreboards.
Normal Explanation¶
The root page became the primary scan entry point. It presents a clear scan action and recent scan history. Invented dashboard statistics were removed because no real backend model supported them.
Technologies used: SvelteKit routing makes / the landing page; a Svelte store
tracks recent scans in the browser.
Task FR2.1: Real Camera Scanning¶
Like you're 5¶
The scan button now opens the phone camera. If the camera reads a product QR code, the website goes straight to that product's passport.
Normal Explanation¶
The landing page now uses a camera scanner component. It tries the browser's native
BarcodeDetector API first and falls back to ZXing when the browser does not provide
native barcode detection. The scanner accepts GS1 Digital Link QR codes and bare
EAN/UPC/GTIN digit payloads, then extracts the GTIN used by the existing product route.
A helper script, scripts/gen-demo-qr.sh, generates scannable demo QR codes for the
seeded catalog.
Technologies used: BarcodeDetector, @zxing/browser, Svelte component state, and
the existing GS1 decoding helper.
Task FR3: Product Result Information Structure¶
Like you're 5¶
We reorganized the product page so the most important answer has the biggest space at the top, followed by neatly labeled shelves for product facts, journey, eco details, and community information.
Normal Explanation¶
The product result page now reserves its main visual area for the future personalized Verdict. Until the verdict backend is complete, it truthfully displays an unknown or degraded state. Remaining content is organized into Info, Journey, Eco, and Community sections.
Technologies used: Svelte components organize the page; a dedicated VerdictHero
component represents the future personalized result without inventing one.
Task FR4: UX and UI Polish¶
Like you're 5¶
We cleaned the shop signs, made buttons and spacing consistent, and added clear messages for empty, loading, locked, and missing-information situations.
Normal Explanation¶
The retained screens received a consistency and usability pass. Layout, navigation, copy, visual hierarchy, empty states, image fallbacks, and locked-page behavior were improved. The interface now communicates what is real, mocked, unavailable, or still coming later.
Technologies used: Svelte components provide reusable UI pieces; CSS defines the visual layout and states; responsive design supports mobile and desktop navigation.
Task FR5: Real-First Ports and Adapters¶
Like you're 5¶
The website has one standard telephone socket. Normally it plugs into the real product room, but developers can unplug it and connect a pretend practice room without rewiring the whole website.
Normal Explanation¶
The web app now depends on a ScanGateway port rather than directly depending on HTTP
or mock data. The default httpScanGateway adapter calls the real API. An
inMemoryScanGateway adapter remains available for offline development and tests. A
composition root selects the adapter from configuration.
The real path uses scanned GTINs and backend product data rather than hand-authored frontend products.
Technologies used: ports and adapters isolate infrastructure; TypeScript interfaces define the port; the composition root chooses an implementation; environment variables control local configuration.
Task FR6: Session Refresh and Expiry Feedback¶
Like you're 5¶
If someone leaves the app open for a while, it tries to quietly renew their login. If that no longer works, the app explains that the session expired and asks them to sign in again.
Normal Explanation¶
The frontend token vault now checks JWT expiry before attaching an access token. The
API client uses the stored refresh token to call POST /api/v1/sessions/refresh, then
replays one failed request after a successful refresh. If refresh fails, the local
session is cleared and locked pages show a session-expired message.
The identity service exposes the refresh endpoint by proxying Keycloak's refresh-token
grant. Invalid or revoked refresh tokens map to 401 session_expired.
Technologies used: Keycloak refresh tokens, a small client-side token vault, a single-flight refresh promise, and Fastify route validation.