# To Be Played – Frontend 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. ![Library](docs/screenshots/library-desktop-dark.png) | Game detail | Public profile | Mobile | |---|---|---| | ![Game detail](docs/screenshots/detail-desktop-dark.png) | ![Public profile](docs/screenshots/profile-desktop-dark.png) | ![Mobile library](docs/screenshots/library-mobile-dark.png) | 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, and an achievement card: unlocked total, perfect games, average completion and the 5 games closest to 100 %. - **What to play next** (`/play-next`): three backlog picks for a time budget (up to 5 / 15 / 40 h or any), high priority first, reroll without repeats, and "Start playing" in one click. - **Library**: status filters, "short games" filter (up to 10 h), search, sorting by playtime, recently seen, newest in library, rating or priority, paging. Each row shows the unlocked achievements. - **Game detail**: status, priority, 1–5 star rating, notes, achievements, time to beat (story / extras / 100 %), a hint when Steam shows recent playtime for a game still in the backlog, and one to set the status to 100 % when every achievement is unlocked. - **Wishlist** with store price and discount. - **Public profile** at `/u/`, opt-in in the settings, with perfect games and average completion. - **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. - **Session**: the tokens are HttpOnly cookies that no script can read. `apiFetch` renews an expired access token once and sends the request again; parallel requests and other tabs share one refresh. ## 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 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) ``` Tests sit next to the code they test (`Component.test.jsx`). ## Run locally Needs Node 24 and running Auth and Core services. ```bash npm install npm run dev ``` | 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 - Mood filter for "What to play next". - A Content Security Policy in `nginx.conf`. - Installable PWA. ## License All rights reserved. The source is public for reading only.