Public Access
docs: rewrite the readme with screenshots for the public showcase
This commit is contained in:
1 parent
83494519f9
commit
2cacc88844
5 files changed
+70
-102
No files matched your search
@@ -1,123 +1,91 @@
|
||||
# To Be Played - Frontend
|
||||
# To Be Played – Frontend
|
||||
|
||||
A modern web application to manage your game backlog, built with React and Vite.
|
||||
Web app of **To Be Played**, a Steam backlog tracker: import your Steam library, decide what to play, and track what
|
||||
you finished. The app is shown as "Game Log" in the UI, in German and English, light and dark.
|
||||
|
||||
## 🚀 Tech Stack
|
||||

|
||||
|
||||
- **Framework:** [React](https://react.dev/)
|
||||
- **Build Tool:** [Vite](https://vitejs.dev/)
|
||||
- **Styling:** [Tailwind CSS 4](https://tailwindcss.com/)
|
||||
- **Icons:** [Material Design Icons (MDI)](https://materialdesignicons.com/)
|
||||
| Game detail | Public profile | Mobile |
|
||||
|---|---|---|
|
||||
|  |  |  |
|
||||
|
||||
## 📂 Project Structure
|
||||
To Be Played is split into three repositories:
|
||||
|
||||
| Repository | Role |
|
||||
|---|---|
|
||||
| ToBePlayed-Auth | Users, login, settings, signs JWTs |
|
||||
| ToBePlayed-Core | Steam library, backlog, wishlist, stats; verifies JWTs |
|
||||
| **ToBePlayed-Frontend** (this one) | React single-page app |
|
||||
|
||||
## Features
|
||||
|
||||
- **Dashboard**: most played games, games in progress, "Pile of Shame" with backlog hours and a random suggestion,
|
||||
Steam avatar and a banner from the most played game of the last two weeks.
|
||||
- **Library**: status filters, "short games" filter (up to 10 h), search, sorting by playtime, recently seen, newest
|
||||
in library, rating or priority, paging.
|
||||
- **Game detail**: status, priority, 1–5 star rating, notes, achievements, time to beat (story / extras / 100 %),
|
||||
and a hint when Steam shows recent playtime for a game still in the backlog.
|
||||
- **Wishlist** with store price and discount.
|
||||
- **Public profile** at `/u/<display name>`, opt-in in the settings.
|
||||
- **Appearance**: accent color, corner style, wide layout, page background and banner from your own game art.
|
||||
Saved in Auth, so it follows you to every device.
|
||||
- German and English, dark mode, mobile layout, session-expired message instead of a silent logout.
|
||||
|
||||
## Tech stack
|
||||
|
||||
- React 19, React Router 7, Vite 8
|
||||
- Tailwind CSS 4, Radix UI primitives (shadcn/ui style components), Lucide icons
|
||||
- react-hook-form + zod for forms, i18next for translations (`public/i18n`)
|
||||
- Vitest + React Testing Library + jsdom
|
||||
- Production image: nginx (Alpine), SPA fallback and long-term caching for hashed assets
|
||||
- CI: Forgejo Actions (`npm ci`, `npm test`, `npm run build`, Docker image)
|
||||
|
||||
## Project structure
|
||||
|
||||
```text
|
||||
├── 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
|
||||
src/
|
||||
├── pages/ # One component per route (Dashboard, GameLibrary, GameDetail, ...)
|
||||
├── components/ # Shared components; ui/ holds the base components
|
||||
├── hooks/ # Data hooks (library sync, Steam profile, appearance, session expiry)
|
||||
├── context/ # PreferencesContext: theme, language, appearance
|
||||
├── utils/ # Validation schemas and helpers
|
||||
└── test/ # Test setup (i18n mock)
|
||||
```
|
||||
|
||||
## 🛠️ Development
|
||||
Tests sit next to the code they test (`Component.test.jsx`).
|
||||
|
||||
## Run locally
|
||||
|
||||
Needs Node 24 and running Auth and Core services.
|
||||
|
||||
### Setup
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### Start Development Server
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Build for Production
|
||||
| Variable | Purpose |
|
||||
|---|---|
|
||||
| `VITE_API_URL` | Base URL of the Auth service |
|
||||
| `VITE_CORE_API_URL` | Base URL of the Core service |
|
||||
|
||||
Values for development and production live in `.env.development` and `.env.production`. They end up in the
|
||||
browser bundle, so they must never hold a secret.
|
||||
|
||||
## Tests and build
|
||||
|
||||
```bash
|
||||
npm test
|
||||
npm run build
|
||||
```
|
||||
|
||||
## 🗺️ Roadmap / Open Topics
|
||||
## Roadmap
|
||||
|
||||
Tracking known work that is not yet implemented. Each item is independently actionable.
|
||||
- "What to play next" page: time budget and mood on top of the current random suggestion.
|
||||
- Achievement progress on the library cards and a library-wide achievement page.
|
||||
- Move the JWT from `localStorage` to an httpOnly cookie (needs Auth changes) and add a Content Security Policy in
|
||||
`nginx.conf`.
|
||||
- Installable PWA.
|
||||
|
||||
### Security
|
||||
|
||||
- **Move JWT out of `localStorage`.** Today the token is stored under `localStorage["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 httpOnly `Secure` `SameSite=Lax` cookie set by `tbp-auth-service` on 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 + CORS `allowCredentials=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 small `fetch` interceptor on the client that reads `XSRF-TOKEN` and sets `X-XSRF-TOKEN`.
|
||||
- **Content Security Policy.** Add a CSP header in `nginx.conf` so 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-service` via `docker-compose.dev.yml` in CI.
|
||||
- **First test targets:** the auth context / token-handling code, the dark-mode toggle (`localStorage["tbp_dark_mode"]`), and i18n string resolution.
|
||||
|
||||
### Other
|
||||
|
||||
- **Audit `localStorage` usage.** Currently used for `tbp_jwt` (planned to move) and `tbp_dark_mode`. Document any other keys before they accumulate.
|
||||
- **API base URL handling.** `VITE_API_URL` covers 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.jsx` exists — 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 `BACKLOG` for 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 `/achievements` showing library-wide unlocked / total / percent.
|
||||
- "Closest to 100%" widget on Dashboard.
|
||||
|
||||
### 4. Public profile + sharing
|
||||
|
||||
- New route `/u/:username` rendered server-friendly (consider SSR / pre-render for SEO, or at least set proper `<title>` / `<meta>` via `react-router` loaders so link previews work).
|
||||
- "Currently playing" + "Recently completed" sections.
|
||||
- "Share my profile" button (copies URL).
|
||||
- Settings toggle for `profile_public`.
|
||||
|
||||
### 5. Friends + compare
|
||||
|
||||
- `/friends` page: list, request, accept, remove.
|
||||
- "Add friend" search by username (autocomplete against Auth endpoint).
|
||||
- "Compare backlogs with X" page: lists games both own, intersected with `BACKLOG` status 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 via `vite-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/k` to navigate, `s` to set status, `?` to show shortcut list).
|
||||
- **i18n** is already wired (`i18next`); make sure every new string lands in the translation files, not hardcoded.
|
||||
## License
|
||||
|
||||
All rights reserved. The source is public for reading only.
|
||||
Reference in new issue
Block a user