docs(readme): add the architecture overview
Build, Test & Push Frontend / quality-check (push) Successful in 14s
Build, Test & Push Frontend / docker (push) Successful in 24s

This commit is contained in:
lobo committed 2026-09-26 07:37:44 +02:00
1 parent fa1bd59509
commit b0c78d8dca
1 file changed
+27
+27
View File
@@ -50,6 +50,33 @@ To Be Played is split into three repositories:
and security headers
- CI: Forgejo Actions (`npm ci`, `npm test`, `npm run build`, Docker image)
## Architecture
```mermaid
flowchart LR
Browser["Browser"] --> Proxy["Traefik (TLS)"]
Proxy --> Frontend["ToBePlayed-Frontend<br/>nginx, static files"]
Proxy --> Auth["ToBePlayed-Auth"]
Proxy --> Core["ToBePlayed-Core"]
Core -->|"JWKS"| Auth
Auth --> Db[("PostgreSQL")]
Core --> Db
Core --> Steam["Steam Web API"]
Core --> Igdb["IGDB API"]
Core -->|"OAuth token"| Twitch["Twitch"]
Browser -.->|"game art"| Images["Steam and IGDB image hosts"]
```
- nginx serves the built app. It has no backend of its own: the browser calls Auth and Core directly
(`VITE_API_URL`, `VITE_CORE_API_URL`). The Content Security Policy allows only these two hosts and the image hosts.
- Auth and Core each have their own database. Core verifies Auth's tokens with Auth's public keys (JWKS).
- Calls for the logged-in user go through `src/utils/api.js`. `clientFetch` sends the HttpOnly cookies and the
`X-TBP-Client` header. `apiFetch` answers a `401` with one `POST /api/auth/refresh` and sends the request again.
Parallel requests and other tabs share this refresh (`navigator.locks`). When the second answer is still a
`401`, the page calls `useSessionExpired`, which opens the login page. Public pages (landing page, public
profile) use plain `fetch`.
- `useLibrarySync` polls Core's `/api/library/sync-status` while a Steam sync runs, then loads the data again.
## Project structure
```text