Public Access
bad11807e029eac7f290992715dd4719c7c9163d
First tests cover the library search debounce (fails on the old looping version), the Pile of Shame states and the backlog save body. jsdom is enabled per test file, so the plain util tests stay in the node environment.
To Be Played - Frontend
A modern web application to manage your game backlog, built with React and Vite.
🚀 Tech Stack
- Framework: React
- Build Tool: Vite
- Styling: Tailwind CSS 4
- Icons: Material Design Icons (MDI)
📂 Project Structure
├── public/ # Static assets (favicons, icons)
├── src/
│ ├── assets/ # Images and global media
│ ├── components/ # Reusable React components
│ ├── App.jsx # Main application layout and entry component
│ ├── main.jsx # App initialization (React DOM, Styles)
│ └── style.css # Global Tailwind and custom CSS
├── index.html # Entry HTML file
├── package.json # Dependencies and scripts
└── vite.config.js # Vite configuration
🛠️ Development
Setup
npm install
Start Development Server
npm run dev
Build for Production
npm run build
🗺️ Roadmap / Open Topics
Tracking known work that is not yet implemented. Each item is independently actionable.
Security
- Move JWT out of
localStorage. Today the token is stored underlocalStorage["tbp_jwt"], which makes it readable by any script running on the page — a single XSS in an npm dependency exfiltrates every session. Switch to an httpOnlySecureSameSite=Laxcookie set bytbp-auth-serviceon login. The SPA no longer touches the token directly; the browser attaches it automatically to requests to*.tbp.andreas-dahm.eu. Requires coordinated changes in Auth (set the cookie) and Deployment (cookie domain + CORSallowCredentials=true). - Add CSRF handling. Once auth rides on a cookie, the SPA must echo a CSRF token in a header on state-changing requests. Spring Security's
CookieCsrfTokenRepository.withHttpOnlyFalse()on the server pairs with a smallfetchinterceptor on the client that readsXSRF-TOKENand setsX-XSRF-TOKEN. - Content Security Policy. Add a CSP header in
nginx.confso XSS exfiltration paths are blocked even if a vulnerability slips in. Minimum starting point:default-src 'self'; img-src 'self' data: https://*.steamstatic.com; object-src 'none'; base-uri 'self'; frame-ancestors 'none'. Tighten further by replacing inline styles/scripts (Tailwind is already build-time, so this should be feasible).
Testing
The project has no test runner today. Suggested setup:
- Unit / component tests: Vitest + React Testing Library. Tests live next to the component (
Component.test.jsx). - API mocking: MSW (Mock Service Worker) so component tests don't hit the real backend and the same handlers can drive Storybook later.
- End-to-end tests: Playwright, scoped to the golden paths (login → see library → log out, registration with invitation code, settings update). Run against the real
tbp-auth-service+tbp-core-serviceviadocker-compose.dev.ymlin CI. - First test targets: the auth context / token-handling code, the dark-mode toggle (
localStorage["tbp_dark_mode"]), and i18n string resolution.
Other
- Audit
localStorageusage. Currently used fortbp_jwt(planned to move) andtbp_dark_mode. Document any other keys before they accumulate. - API base URL handling.
VITE_API_URLcovers Auth; Core's base URL is implicit. Make both explicit (e.g.VITE_AUTH_URL,VITE_API_URL) so dev / prod / preview environments are unambiguous.
🎯 Product Roadmap (Frontend-owned slices)
The full cross-service product roadmap lives in ToBePlayed-Deployment/README.md. This section lists only the UI / UX slices that land in the Frontend.
1. Backlog tracking UI
Today GameLibrary.jsx is a paginated grid of synced Steam games — there is no per-game state. Once Core exposes status + notes + rating, the Frontend needs:
- Status chips on each game card (
BACKLOG / PLAYING / COMPLETED / DROPPED / ON_HOLD / WISHLIST) with one-click cycling or a popover for explicit selection. - Status filter bar above the grid; multi-select; persisted to URL search params so links are shareable and back-button works.
- Game detail page (
GameDetail.jsxexists — extend it) with rating widget (stars or 1–10), completion date picker, markdown notes editor with preview. Optimistic update on save, server reconciliation on failure. - Drag-to-reorder within
BACKLOGfor priority. Use a small library (@dnd-kit/core) — well-maintained, accessible.
2. "What to play next" page
- New route:
/play-next(or surface from Dashboard). - Form: time budget radio (15 min / 1 h / weekend), mood tag multi-select.
- On submit: call Core's picker endpoint, render 3 cards. "Reroll" button calls again.
- One-tap "Start playing" sets game status to
PLAYING.
This page is the single best mobile entry point — design mobile-first.
3. Achievement views
Data is already in Core. The Frontend needs:
- Achievement progress ring on each game card + game detail.
- New route
/achievementsshowing library-wide unlocked / total / percent. - "Closest to 100%" widget on Dashboard.
4. Public profile + sharing
- New route
/u/:usernamerendered server-friendly (consider SSR / pre-render for SEO, or at least set proper<title>/<meta>viareact-routerloaders so link previews work). - "Currently playing" + "Recently completed" sections.
- "Share my profile" button (copies URL).
- Settings toggle for
profile_public.
5. Friends + compare
/friendspage: list, request, accept, remove.- "Add friend" search by username (autocomplete against Auth endpoint).
- "Compare backlogs with X" page: lists games both own, intersected with
BACKLOGstatus on either side — i.e. "next co-op night candidates".
6. Mobile / PWA
- Verify the SPA is installable as a PWA: manifest, icons (already in
public/?), service worker viavite-plugin-pwa. - Test core flows (login, picker, status update) on a real phone, not just devtools. The "what to play tonight" use case is mobile-primary.
7. UX details that compound
- Search: client-side fuzzy search across library (Fuse.js or similar) on the already-loaded page; server-side search if the library gets large enough that pagination hurts.
- Empty states: every list should have an empty state with a clear next action ("Connect Steam to import games", "No completed games yet — mark one!").
- Optimistic updates for any status / rating / notes change — they should feel instant.
- Keyboard shortcuts for power users (
j/kto navigate,sto set status,?to show shortcut list). - i18n is already wired (
i18next); make sure every new string lands in the translation files, not hardcoded.
Languages
JavaScript
96.7%
CSS
3.2%