docs(readme): update features, repos and container env
Build, Test & Push Frontend / quality-check (push) Successful in 38s
Build, Test & Push Frontend / docker (push) Successful in 36s

Match README to the code: PlayStation import, stat charts, public
routes, Gitea CI, and the AUTH_HOST/API_HOST image variables.
This commit is contained in:
lobo committed 2026-10-14 14:51:40 +02:00
1 parent 42bc83bb28
commit 25ade98989
1 file changed
+29 -9
+29 -9
View File
@@ -1,7 +1,7 @@
# To Be Played – Frontend # 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 Web app of **To Be Played**, a backlog tracker: import your Steam and PlayStation libraries or add games by hand,
you finished. The UI is in German and English, with light and dark mode. decide what to play, and track what you finished. The UI is in German and English, with light and dark mode.
![Library](docs/screenshots/library-desktop-dark.png) ![Library](docs/screenshots/library-desktop-dark.png)
@@ -9,13 +9,14 @@ you finished. The UI is in German and English, with light and dark mode.
|---|---|---|---| |---|---|---|---|
| ![Dashboard](docs/screenshots/dashboard-desktop-dark.png) | ![Game detail](docs/screenshots/detail-desktop-dark.png) | ![Public profile](docs/screenshots/profile-desktop-dark.png) | ![Mobile library](docs/screenshots/library-mobile-dark.png) | | ![Dashboard](docs/screenshots/dashboard-desktop-dark.png) | ![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: To Be Played is split into four repositories:
| Repository | Role | | Repository | Role |
|---|---| |---|---|
| ToBePlayed-Auth | Users, login, settings, signs JWTs | | ToBePlayed-Auth | Users, login, settings, signs JWTs |
| ToBePlayed-Core | Steam library, backlog, wishlist, stats; verifies JWTs | | ToBePlayed-Core | Steam library, backlog, wishlist, stats; verifies JWTs |
| **ToBePlayed-Frontend** (this one) | React single-page app | | **ToBePlayed-Frontend** (this one) | React single-page app |
| ToBePlayed-Deployment | Docker Compose stack, env template, ROADMAP.md (history), plans |
## Features ## Features
@@ -41,6 +42,8 @@ To Be Played is split into three repositories:
- **Your stats** (`/stats`): totals and statuses; the pile in hours, in weeks at your pace of the last 90 days and in - **Your stats** (`/stats`): totals and statuses; the pile in hours, in weeks at your pace of the last 90 days and in
years of full-time work, and its oldest unplayed game; most played and most loyal games; top genres and moods; years of full-time work, and its oldest unplayed game; most played and most loyal games; top genres and moods;
trips to the moon, the longest gaming day, games started but under one hour; finished games per year; games per platform. trips to the moon, the longest gaming day, games started but under one hour; finished games per year; games per platform.
The user picks a chart form per group (bars, pie, donut, line or list, `src/utils/statCharts.js`). Auth saves it
(`PUT /api/users/settings/stat-chart`).
- **Click a number** (stats page, dashboard, public profile, landing page, Pile Points): a number, bar, row or year - **Click a number** (stats page, dashboard, public profile, landing page, Pile Points): a number, bar, row or year
opens the games behind it in a dialog (a bottom sheet on phones), 40 per page with "Load more". In your own opens the games behind it in a dialog (a bottom sheet on phones), 40 per page with "Load more". In your own
views the status counts and the pile link to the library with the filter instead. Not clickable: sums (playtime), views the status counts and the pile link to the library with the filter instead. Not clickable: sums (playtime),
@@ -216,9 +219,11 @@ flowchart LR
- react-hook-form + zod for forms, i18next for translations (`public/i18n`) - react-hook-form + zod for forms, i18next for translations (`public/i18n`)
- Vitest + React Testing Library + jsdom - Vitest + React Testing Library + jsdom
- Production image: nginx (Alpine), SPA fallback, long-term caching for hashed assets, Content Security Policy - Production image: nginx (Alpine), SPA fallback, long-term caching for hashed assets, Content Security Policy
and security headers and security headers. nginx reads `AUTH_HOST` and `API_HOST` from the container env at start (`nginx.conf` is an
nginx template) and puts them into the CSP `connect-src`.
- ESLint with the React hooks rules (`npm run lint`) - ESLint with the React hooks rules (`npm run lint`)
- CI: Forgejo Actions (`npm ci`, `npm run lint`, `npm test`, `npm run build`, Docker image) - CI: Gitea Actions (`.gitea/workflows/docker-publish.yml`: `npm ci`, `npm run lint`, `npm test`, `npm run build`, then the
Docker image tagged `latest`, `<branch>`, `<branch>-<sha>`)
## Architecture ## Architecture
@@ -259,6 +264,8 @@ flowchart LR
- The pages that need a login sit under the `RequireSession` layout route in `App.jsx`. Without a session it opens - The pages that need a login sit under the `RequireSession` layout route in `App.jsx`. Without a session it opens
the login page: after a `401` with the "session expired" message and back to the same page, after a logout the login page: after a `401` with the "session expired" message and back to the same page, after a logout
without a way back. A public page stays open when the session ends there. without a way back. A public page stays open when the session ends there.
- Public routes: `/`, `/login`, `/register`, `/confirm-email`, `/reset-password`, `/u/:name` and `/impressum`
(`ImprintPage`, linked from the footer). Every other route sits under `RequireSession`.
- `CurrentUserProvider` holds `GET /api/users/me` for the whole app (`useCurrentUserContext`, `useCurrentUser`). - `CurrentUserProvider` holds `GET /api/users/me` for the whole app (`useCurrentUserContext`, `useCurrentUser`).
Dashboard and settings load it again when they open. Dashboard and settings load it again when they open.
- Tests render through `src/test/renderWithProviders.jsx` (a data router like `main.jsx`) and answer requests - Tests render through `src/test/renderWithProviders.jsx` (a data router like `main.jsx`) and answer requests
@@ -340,13 +347,16 @@ flowchart LR
```text ```text
src/ src/
├── App.jsx, main.jsx, i18n.js # Routes, entry point, i18next setup
├── style.css, skins.css, effects.css # Base styles, the skins, the background effects
├── pages/ # One component per route (Dashboard, GameLibrary, GameDetail, ...): loads data, places cards ├── pages/ # One component per route (Dashboard, GameLibrary, GameDetail, ...): loads data, places cards
├── components/ # Cards and shared components; ui/ holds the base components, import/ and stats/ the parts ├── components/ # Cards and shared components; ui/ holds the base components, import/, stats/ and people/ the
│ # of one page that share page-only code │ # parts of one page that share page-only code
├── hooks/ # Data hooks (game, dashboard, library sync, Steam profile, appearance, session) ├── hooks/ # Data hooks (game, dashboard, library sync, Steam profile, appearance, session)
├── context/ # PreferencesContext: theme, language, appearance ├── context/ # CurrentUserContext, PreferencesContext
├── lib/ # utils.js (class name helper)
├── utils/ # Validation schemas and helpers ├── utils/ # Validation schemas and helpers
└── test/ # Test setup (i18n mock) └── test/ # renderWithProviders.jsx, fetchRoutes.js, i18n mock, WalletLoader, fixtures/import
``` ```
Tests sit next to the code they test (`Component.test.jsx`). Tests sit next to the code they test (`Component.test.jsx`).
@@ -388,6 +398,16 @@ npm run dev
Values for development and production live in `.env.development` and `.env.production`. They end up in the 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. browser bundle, so they must never hold a secret.
Production image (container env, read by nginx at start):
| Variable | Purpose |
|---|---|
| `AUTH_HOST` | Auth host name for the CSP `connect-src` |
| `API_HOST` | Core host name, same |
Both default to empty in the image; `docker-compose.yml` of the Deployment repo passes them. `FRONTEND_HOST` is not
passed to the frontend image; compose uses it for the Traefik rule and as `APP_FRONTEND_URL` of Auth and Core (Deployment `docker-compose.yml`:68,152).
## Tests and build ## Tests and build
```bash ```bash