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.