Rework the site navigation, the account page, the Game page and My games #400

Closed
opened 2026-10-14 14:30:12 +00:00 by root · 21 comments
root commented 2026-10-14 14:30:12 +00:00 (Migrated from gitlab.core-project.space)

Problem Statement

After accounts v1 (#364, !523), four screens work but read badly. The owner's verdict, from #399: the problem is layout and hierarchy, not the look.

  • Site navigation. A narrow 192px column of bare text links. The Username looks like any other link, "Sign out" is always showing, and a lone settings cog holds only Language. Nothing marks how to start a Game. "My games" shows even to a Player who has never played.
  • Account page. A narrow centred column with no hierarchy. The password field that deletes the Account sits open on the page with no step before it.
  • Game page. A bare "Finished game" label says nothing about which Game this is. The actions sit apart from what they act on.
  • My games. A plain list that feels odd on desktop. It has no way to narrow the list by result, and it silently stops at the latest 50 Games, so older Games can't be reached.

Solution

A design pass on the four screens, chosen from a throwaway prototype in the running app (branch prototype/399-front-screens). The chosen variants are navigation D, account page C, Game page C and My games D.

  • Navigation. A 256px sidebar with one emphasised action, New game, as the first item. "My games" appears once the Player owns a Game. The account sits in the footer: a Username menu, or Sign in for a Player without a Session. On a phone it becomes a slim bar with the same priorities.
  • Account page. The Username and join date head the page. Side tabs (Profile, Your data, Delete account) show one section at a time, and the open section is in the URL. Deleting goes through a dialog that lists what is lost and then asks for the password.
  • Game page. The board and move list stay as they are. The rail's header names the Game ("You vs Username", or "Guest", with the date). Copy link and Export PGN move into the rail's footer, and Copy link says "Copied" on the button.
  • My games. It takes the account page's frame. Result filters with counts sit on the left (All games, Won, Lost, Draw), and the chosen filter is in the URL. Rich rows sit on the right, and Show more pages through every Game, not just the latest 50.

Everything is presentation except one contract change. game.list gains a result filter, a cursor and per-result counts. account.me gains hasGames, so the navigation still asks the server one thing per page.

User Stories

Navigation

  1. As a Player on a desktop, I want the navigation as a sidebar of comfortable width, with an icon and a label on each item, so that I can scan it at a glance.
  2. As a Player, I want New game as the first, highlighted item of the navigation, so that starting a Game is always the obvious next step.
  3. As a Player, I want New game to take me to the home page, so that I choose there between a Local game, an Online game with a friend, or joining with a code.
  4. As a Player whose browser owns no Game, I don't want a "My games" item, so that the navigation offers nothing I can't use yet.
  5. As a Player who owns at least one Game, as a Guest or an Account, I want a "My games" item marked active on that page, so that I can always get back to my Games and see where I am.
  6. As a Player whose Session is still being read, I want the navigation's footer to keep its space empty, so that "Sign in" never flashes before my Username and nothing jumps.
  7. As a Player with no Session, I want "Sign in" and a Language control in the navigation's footer, so that both stay reachable without a settings menu.
  8. As a Guest who owns Games, I want a short note in the navigation saying my Games live on this browser only, with a link to create an Account, so that I know how to keep them.
  9. As a signed-in Player, I want my Username in the navigation's footer as a button, so that I can see who I am signed in as.
  10. As a signed-in Player, I want that button to open a menu with Account, Language and Sign out, so that the account actions are grouped and Sign out isn't one stray click away.
  11. As a Player, I want to switch Language from the navigation, each language named in itself, so that I find mine whatever language the page is in.
  12. As a Player on a phone, I want a slim top bar with the site name, New game, and Sign in or my account menu, so that the board keeps the screen.
  13. As a Player on a phone who owns Games, I want a "My games" icon button in the top bar, so that my Games are one tap away.
  14. As a Player on a Local game, I want the navigation to ask the server nothing beyond who I am, so that a Local game never depends on the network.

Account page

  1. As a signed-in Player, I want the account page headed by my Username and the day I joined, so that I see whose Account this is at once.
  2. As a signed-in Player, I want the account page split into Profile, Your data and Delete account tabs, so that each concern stands on its own.
  3. As a signed-in Player, I want the open tab in the URL, so that Back, a reload or a shared link brings me to the same tab.
  4. As a signed-in Player, I want the Profile tab to list my Username, email and join date, and to say a Username can't be changed, so that I know what is fixed.
  5. As a signed-in Player, I want the Your data tab to say what the export holds and offer "Download my data", so that I can keep a copy of my Account.
  6. As a signed-in Player, I want to be told when the download fails, so that I can try again.
  7. As a signed-in Player, I want the Delete account tab to show its consequence in a red-bordered area, so that I can't mistake it for a routine setting.
  8. As a signed-in Player, I want "Delete account…" to open a dialog that lists what is lost before asking for my password, so that I confirm knowing exactly what happens.
  9. As a signed-in Player, I want the dialog's delete button disabled until I type a password, with Cancel beside it, so that I can't delete by accident.
  10. As a signed-in Player, I want a wrong password refused inside the dialog, with the field marked, so that I can retry without losing my place.
  11. As a signed-in Player, I want to be told inside the dialog when deletion fails for another reason, so that I know it didn't happen.
  12. As a signed-in Player who deletes their Account, I want to land on the home page signed out, as today, so that the outcome is plain.
  13. As a Player with no Session who opens the account page, I want a centred message with Sign in and Create an account, so that I have a way forward.
  14. As a Player on a phone, I want the account tabs as a row above the section, so that the page fits the screen.

Game page

  1. As a Player reading a Game I played, I want the rail's header to say "You vs ", my side first, and the date it ended, so that I know which Game this is.
  2. As a Player reading someone else's Game, I want the header to name White then Black, by Username or "Guest", so that the Game is identified without a "you".
  3. As a Player, I want "Copy link" and "Export PGN" in the rail's footer, under the moves, so that the actions sit with the Game they act on.
  4. As a Player, I want "Copy link" to say "Copied" on the button for a moment, so that I know it worked without a separate toast.
  5. As a Player, I want "Copy link" shown as a secondary action and "Export PGN" as a tertiary one, so that neither outweighs reading the Game.
  6. As a Player, I want the board, the player rows and the move list unchanged, so that reading a Game here feels like playing in a Room.

My games

  1. As a Player with Games, I want My games laid out like the account page, so that the two pages feel like one site.
  2. As a Player with Games, I want each row to lead with a big W, L or D, then "vs " with my Color, how the Game ended, and when, so that I can scan my results quickly.
  3. As a Player, I want each row's date relative ("3 days ago"), with the full date on hover, so that recent Games read naturally.
  4. As a Player, I want the whole row to open the Game, so that the target is large.
  5. As a Player, I want filters for All games, Won, Lost and Draw, each with its count across all my Games, so that I can see my record and narrow the list.
  6. As a Player, I want the chosen filter in the URL, so that Back, a reload or a shared link keeps it.
  7. As a Player with more Games than one page holds, I want a "Show more" button and a "Showing n of N" line, so that I can reach every Game I own, not just the latest 50.
  8. As a Player who opens a Game from My games and comes back, I want the list where I left it, so that paging isn't lost.
  9. As a Player, I want a filter with no Games to say so, so that an empty result isn't mistaken for a broken page.
  10. As a Player who opens My games owning no Game, I want "No games yet", why, and a New game button, so that I have a way forward. If this browser has never played, I also want Sign in, in case my Games are on an Account.
  11. As a Player on a phone, I want the filters as a row of tabs above the list, so that the page fits the screen.
  12. As a Player, I don't want a "New game" button in the My games heading, since the navigation already offers it.

Everywhere

  1. As a French-speaking Player, I want every new word on these screens in French, so that the site reads in my language.
  2. As a Player using a screen reader, I want the navigation, the tabs, the filters and the dialog to keep proper roles and names, so that I can use them without seeing them.

Seams

  • S1 — the app shell through the router harness (front view test). Covers 1–14 and their French copy (47–48 for the navigation). Asserts the four navigation states, the "My games" item tied to hasGames, the Guest note, the account menu, Language, the phone bar, and that / and /local still ask nothing but account.me.
  • S2 — AccountPageView with the auth harness and MSW (front view test). Covers 15–28 and their French copy.
  • S3 — GamePageView with the games harness (front view test). Covers 29–34 and their French copy.
  • S4 — MyGamesView with the games harness and MSW serving the new game.list (front view test). Covers 35–46 and their French copy.
  • S5 — the game.list and account.me procedures through RPC against a real database (API integration). Covers the server half of 4–5, 8, 39 and 41: the cursor, the result filter, the counts and hasGames, for a Guest, for an Account, and for a browser with neither.
  • S6 — apps/e2e (e2e). Extends my-games.spec to reach My games from the navigation after a Game and filter it (5, 39). Adds one test to accounts.spec that reaches the account page from the Username menu and deletes the Account through the dialog (10, 22, 26).

Implementation Decisions

Contract and API (the one behaviour change)

  • game.list takes an optional result (won | lost | drawn, from the caller's side) and an optional opaque cursor. It answers one page newest first, nextCursor when more remain, and the caller's counts per result across all their Games, regardless of the filter. This replaces today's bare array capped at 50.
    // shape agreed in the grilling; names may be refined in the ticket
    input:  { result?: "won" | "lost" | "drawn"; cursor?: string }
    output: { games: GameSummary[]; nextCursor: string | null;
              counts: { won: number; lost: number; drawn: number } }
    
  • The cursor encodes the last row's end time and Game id, so Games ending at the same instant page stably. The page size is a server constant (20).
  • account.me answers hasGames: boolean beside kind, for a signed-out browser (true when its Guest owns a Game) and for an Account. A claimed Guest's Games count as the Account's (ADR 0035).
  • Who owns what, and how a Guest or an Account is proven, are unchanged (ADR 0033, 0034).

Front

  • Verticals (ADR 0011, 0026). The navigation stays composed in app/, with the account part in the auth vertical; the Game page and My games stay in games. Each screen keeps one .view.tsx holding the hooks and one .ui.tsx holding the layout.
  • The sidebar is shadcn's Sidebar, added to design-system/ui. It is 256px wide on desktop, with a sticky header, content and footer. Below lg it gives way to a slim top bar, with no menu sheet. The settings cog is removed; Language moves into the account menu, or beside Sign in for a Player with no Session.
  • The navigation reads only account.me. "My games" is shown when hasGames is true, and nothing else is fetched.
  • The Guest note shows on desktop for a Player with no Session whose hasGames is true. It links to sign-up, which already claims the Guest.
  • The account page's tab is a validated search parameter on its route (section: profile | data | delete, default profile). So is My games' filter (result, absent meaning all). Both are written through TanStack Router; view state that a link should carry belongs in the URL.
  • The delete dialog is the design system's Dialog. The password field and the refusal message move inside it, and the deletion itself is unchanged.
  • The Game page passes the side names and end date into the shared Game screen's existing rail header and footer slots. The Game screen itself is untouched, so the Room and Local screens don't change.
  • My games uses an infinite query keyed by result, built by the games vertical's query-options factory (ADR 0012). The counts come from the first page.
  • Copy (ADR 0025). Every new string goes into the Paraglide catalogue in English and French; the prototype's hard-coded English is not carried over. Words reused from the catalogue keep their keys.
  • e2e (ADR 0022). The accessible names the suite binds to stay: the "My games" link and the list named "My games". New controls get names a Player perceives.

Merge requests

  1. Back end: the game.list page, filter and counts, and account.me's hasGames. (S5)
  2. Navigation D, blocked by 1. (S1, plus the S6 navigation steps)
  3. Account page C. (S2, plus the S6 deletion test)
  4. Game page C. (S3)
  5. My games D, blocked by 1. (S4, plus the S6 My games steps)

Testing Decisions

  • Front tests go through the view with the vertical's harness and MSW, never into a .ui.tsx (front CODING_STANDARDS). They assert what a Player perceives: roles, accessible names, text, URL.
  • Prior art:
    • app-shell.test.tsx: sidebar and phone-bar layout, language switch.
    • router.test.tsx: / and /local ask nothing but who is signed in. It must stay green unchanged.
    • account-page.test.tsx: details, download, deletion refusals and success, French.
    • game-page.test.tsx.
    • my-games.test.tsx.
    • rpc-account-games.integration.test.ts and rpc-game-reads.integration.test.ts: game.list as a Guest and as an Account.
    • my-games.spec.ts and accounts.spec.ts in apps/e2e.
  • Edge and unhappy paths to cover:
    • hasGames false for a browser with no Guest and no Session.
    • A Guest's Games counted for the Account after a claim.
    • Paging across Games that ended at the same instant.
    • A filter with zero Games.
    • Exactly one page of Games, so no "Show more".
    • Counts unchanged when a filter is applied.
    • A section or result search parameter outside the allowed values falls back to the default.
    • A wrong password in the dialog keeps the dialog open.
    • Cancel closes the dialog without a request.
    • "Copied" returns to "Copy link".
    • A reader with no side sees White before Black.
    • French copy on each screen.
  • Existing tests that bind to the removed settings cog, or to the old account and Game page layout, are rewritten to the new layout, not deleted.

Out of Scope

  • The shared Game screen (board, player rows, move list) and the Room and Local screens.
  • The home, sign-in, sign-up and password-reset pages.
  • A new visual identity: tokens, palette and type stay.
  • Collapsing the sidebar on desktop; the owner finds desktop space sufficient.
  • Thumbnails of the final position in My games, and sorting other than newest first.
  • Changing what a Username, a Guest or a Session is, or how deletion works (#364).

Further Notes

  • Prototype: branch prototype/399-front-screens (never merged). Run pnpm dev and use the floating "Prototype #399" panel. ?nav=D, ?page=C on /account and /games/<id>, and ?page=D&many=1 on /games show the chosen variants.
  • Research behind the choices: NN/g vertical navigation, mobile navigation, confirmation dialogs and empty states; Laws of UX (Hick, Fitts, serial position, Von Restorff, common region); shadcn Sidebar proportions; the Lichess analysis layout; GitHub's account deletion.
  • Proposed rule, for a dedicated change the owner asks for: view state a link should carry (a tab, a filter) lives in TanStack Router search parameters. It is not edited into CODING_STANDARDS.md here.
  • Supersedes the "To decide first" list on #399.
## Problem Statement After accounts v1 (#364, !523), four screens work but read badly. The owner's verdict, from #399: the problem is layout and hierarchy, not the look. - **Site navigation.** A narrow 192px column of bare text links. The Username looks like any other link, "Sign out" is always showing, and a lone settings cog holds only Language. Nothing marks how to start a Game. "My games" shows even to a Player who has never played. - **Account page.** A narrow centred column with no hierarchy. The password field that deletes the Account sits open on the page with no step before it. - **Game page.** A bare "Finished game" label says nothing about which Game this is. The actions sit apart from what they act on. - **My games.** A plain list that feels odd on desktop. It has no way to narrow the list by result, and it silently stops at the latest 50 Games, so older Games can't be reached. ## Solution A design pass on the four screens, chosen from a throwaway prototype in the running app (branch `prototype/399-front-screens`). The chosen variants are navigation D, account page C, Game page C and My games D. - **Navigation.** A 256px sidebar with one emphasised action, **New game**, as the first item. "My games" appears once the Player owns a Game. The account sits in the footer: a Username menu, or Sign in for a Player without a Session. On a phone it becomes a slim bar with the same priorities. - **Account page.** The Username and join date head the page. Side tabs (Profile, Your data, Delete account) show one section at a time, and the open section is in the URL. Deleting goes through a dialog that lists what is lost and then asks for the password. - **Game page.** The board and move list stay as they are. The rail's header names the Game ("You vs Username", or "Guest", with the date). Copy link and Export PGN move into the rail's footer, and Copy link says "Copied" on the button. - **My games.** It takes the account page's frame. Result filters with counts sit on the left (All games, Won, Lost, Draw), and the chosen filter is in the URL. Rich rows sit on the right, and **Show more** pages through every Game, not just the latest 50. Everything is presentation except one contract change. `game.list` gains a result filter, a cursor and per-result counts. `account.me` gains `hasGames`, so the navigation still asks the server one thing per page. ## User Stories ### Navigation 1. As a Player on a desktop, I want the navigation as a sidebar of comfortable width, with an icon and a label on each item, so that I can scan it at a glance. 2. As a Player, I want **New game** as the first, highlighted item of the navigation, so that starting a Game is always the obvious next step. 3. As a Player, I want **New game** to take me to the home page, so that I choose there between a Local game, an Online game with a friend, or joining with a code. 4. As a Player whose browser owns no Game, I don't want a "My games" item, so that the navigation offers nothing I can't use yet. 5. As a Player who owns at least one Game, as a Guest or an Account, I want a "My games" item marked active on that page, so that I can always get back to my Games and see where I am. 6. As a Player whose Session is still being read, I want the navigation's footer to keep its space empty, so that "Sign in" never flashes before my Username and nothing jumps. 7. As a Player with no Session, I want "Sign in" and a Language control in the navigation's footer, so that both stay reachable without a settings menu. 8. As a Guest who owns Games, I want a short note in the navigation saying my Games live on this browser only, with a link to create an Account, so that I know how to keep them. 9. As a signed-in Player, I want my Username in the navigation's footer as a button, so that I can see who I am signed in as. 10. As a signed-in Player, I want that button to open a menu with Account, Language and Sign out, so that the account actions are grouped and Sign out isn't one stray click away. 11. As a Player, I want to switch Language from the navigation, each language named in itself, so that I find mine whatever language the page is in. 12. As a Player on a phone, I want a slim top bar with the site name, New game, and Sign in or my account menu, so that the board keeps the screen. 13. As a Player on a phone who owns Games, I want a "My games" icon button in the top bar, so that my Games are one tap away. 14. As a Player on a Local game, I want the navigation to ask the server nothing beyond who I am, so that a Local game never depends on the network. ### Account page 15. As a signed-in Player, I want the account page headed by my Username and the day I joined, so that I see whose Account this is at once. 16. As a signed-in Player, I want the account page split into Profile, Your data and Delete account tabs, so that each concern stands on its own. 17. As a signed-in Player, I want the open tab in the URL, so that Back, a reload or a shared link brings me to the same tab. 18. As a signed-in Player, I want the Profile tab to list my Username, email and join date, and to say a Username can't be changed, so that I know what is fixed. 19. As a signed-in Player, I want the Your data tab to say what the export holds and offer "Download my data", so that I can keep a copy of my Account. 20. As a signed-in Player, I want to be told when the download fails, so that I can try again. 21. As a signed-in Player, I want the Delete account tab to show its consequence in a red-bordered area, so that I can't mistake it for a routine setting. 22. As a signed-in Player, I want "Delete account…" to open a dialog that lists what is lost before asking for my password, so that I confirm knowing exactly what happens. 23. As a signed-in Player, I want the dialog's delete button disabled until I type a password, with Cancel beside it, so that I can't delete by accident. 24. As a signed-in Player, I want a wrong password refused inside the dialog, with the field marked, so that I can retry without losing my place. 25. As a signed-in Player, I want to be told inside the dialog when deletion fails for another reason, so that I know it didn't happen. 26. As a signed-in Player who deletes their Account, I want to land on the home page signed out, as today, so that the outcome is plain. 27. As a Player with no Session who opens the account page, I want a centred message with Sign in and Create an account, so that I have a way forward. 28. As a Player on a phone, I want the account tabs as a row above the section, so that the page fits the screen. ### Game page 29. As a Player reading a Game I played, I want the rail's header to say "You vs <opponent>", my side first, and the date it ended, so that I know which Game this is. 30. As a Player reading someone else's Game, I want the header to name White then Black, by Username or "Guest", so that the Game is identified without a "you". 31. As a Player, I want "Copy link" and "Export PGN" in the rail's footer, under the moves, so that the actions sit with the Game they act on. 32. As a Player, I want "Copy link" to say "Copied" on the button for a moment, so that I know it worked without a separate toast. 33. As a Player, I want "Copy link" shown as a secondary action and "Export PGN" as a tertiary one, so that neither outweighs reading the Game. 34. As a Player, I want the board, the player rows and the move list unchanged, so that reading a Game here feels like playing in a Room. ### My games 35. As a Player with Games, I want My games laid out like the account page, so that the two pages feel like one site. 36. As a Player with Games, I want each row to lead with a big W, L or D, then "vs <opponent>" with my Color, how the Game ended, and when, so that I can scan my results quickly. 37. As a Player, I want each row's date relative ("3 days ago"), with the full date on hover, so that recent Games read naturally. 38. As a Player, I want the whole row to open the Game, so that the target is large. 39. As a Player, I want filters for All games, Won, Lost and Draw, each with its count across all my Games, so that I can see my record and narrow the list. 40. As a Player, I want the chosen filter in the URL, so that Back, a reload or a shared link keeps it. 41. As a Player with more Games than one page holds, I want a "Show more" button and a "Showing n of N" line, so that I can reach every Game I own, not just the latest 50. 42. As a Player who opens a Game from My games and comes back, I want the list where I left it, so that paging isn't lost. 43. As a Player, I want a filter with no Games to say so, so that an empty result isn't mistaken for a broken page. 44. As a Player who opens My games owning no Game, I want "No games yet", why, and a New game button, so that I have a way forward. If this browser has never played, I also want Sign in, in case my Games are on an Account. 45. As a Player on a phone, I want the filters as a row of tabs above the list, so that the page fits the screen. 46. As a Player, I don't want a "New game" button in the My games heading, since the navigation already offers it. ### Everywhere 47. As a French-speaking Player, I want every new word on these screens in French, so that the site reads in my language. 48. As a Player using a screen reader, I want the navigation, the tabs, the filters and the dialog to keep proper roles and names, so that I can use them without seeing them. ## Seams - **S1 — the app shell through the router harness** (front view test). Covers 1–14 and their French copy (47–48 for the navigation). Asserts the four navigation states, the "My games" item tied to `hasGames`, the Guest note, the account menu, Language, the phone bar, and that `/` and `/local` still ask nothing but `account.me`. - **S2 — `AccountPageView` with the auth harness and MSW** (front view test). Covers 15–28 and their French copy. - **S3 — `GamePageView` with the games harness** (front view test). Covers 29–34 and their French copy. - **S4 — `MyGamesView` with the games harness and MSW serving the new `game.list`** (front view test). Covers 35–46 and their French copy. - **S5 — the `game.list` and `account.me` procedures through RPC against a real database** (API integration). Covers the server half of 4–5, 8, 39 and 41: the cursor, the result filter, the counts and `hasGames`, for a Guest, for an Account, and for a browser with neither. - **S6 — `apps/e2e`** (e2e). Extends `my-games.spec` to reach My games from the navigation after a Game and filter it (5, 39). Adds one test to `accounts.spec` that reaches the account page from the Username menu and deletes the Account through the dialog (10, 22, 26). ## Implementation Decisions ### Contract and API (the one behaviour change) - `game.list` takes an optional `result` (`won` | `lost` | `drawn`, from the caller's side) and an optional opaque `cursor`. It answers one page newest first, `nextCursor` when more remain, and the caller's counts per result across all their Games, regardless of the filter. This replaces today's bare array capped at 50. ```ts // shape agreed in the grilling; names may be refined in the ticket input: { result?: "won" | "lost" | "drawn"; cursor?: string } output: { games: GameSummary[]; nextCursor: string | null; counts: { won: number; lost: number; drawn: number } } ``` - The cursor encodes the last row's end time and Game id, so Games ending at the same instant page stably. The page size is a server constant (20). - `account.me` answers `hasGames: boolean` beside `kind`, for a signed-out browser (true when its Guest owns a Game) and for an Account. A claimed Guest's Games count as the Account's (ADR 0035). - Who owns what, and how a Guest or an Account is proven, are unchanged (ADR 0033, 0034). ### Front - **Verticals (ADR 0011, 0026).** The navigation stays composed in `app/`, with the account part in the `auth` vertical; the Game page and My games stay in `games`. Each screen keeps one `.view.tsx` holding the hooks and one `.ui.tsx` holding the layout. - **The sidebar** is shadcn's `Sidebar`, added to `design-system/ui`. It is 256px wide on desktop, with a sticky header, content and footer. Below `lg` it gives way to a slim top bar, with no menu sheet. The settings cog is removed; Language moves into the account menu, or beside Sign in for a Player with no Session. - **The navigation reads only `account.me`.** "My games" is shown when `hasGames` is true, and nothing else is fetched. - **The Guest note** shows on desktop for a Player with no Session whose `hasGames` is true. It links to sign-up, which already claims the Guest. - **The account page's tab** is a validated search parameter on its route (`section`: `profile` | `data` | `delete`, default `profile`). So is My games' filter (`result`, absent meaning all). Both are written through TanStack Router; view state that a link should carry belongs in the URL. - **The delete dialog** is the design system's `Dialog`. The password field and the refusal message move inside it, and the deletion itself is unchanged. - **The Game page** passes the side names and end date into the shared Game screen's existing rail header and footer slots. The Game screen itself is untouched, so the Room and Local screens don't change. - **My games** uses an infinite query keyed by `result`, built by the `games` vertical's query-options factory (ADR 0012). The counts come from the first page. - **Copy (ADR 0025).** Every new string goes into the Paraglide catalogue in English and French; the prototype's hard-coded English is not carried over. Words reused from the catalogue keep their keys. - **e2e (ADR 0022).** The accessible names the suite binds to stay: the "My games" link and the list named "My games". New controls get names a Player perceives. ### Merge requests 1. **Back end:** the `game.list` page, filter and counts, and `account.me`'s `hasGames`. (S5) 2. **Navigation D**, blocked by 1. (S1, plus the S6 navigation steps) 3. **Account page C.** (S2, plus the S6 deletion test) 4. **Game page C.** (S3) 5. **My games D**, blocked by 1. (S4, plus the S6 My games steps) ## Testing Decisions - Front tests go through the view with the vertical's harness and MSW, never into a `.ui.tsx` (front `CODING_STANDARDS`). They assert what a Player perceives: roles, accessible names, text, URL. - **Prior art:** - `app-shell.test.tsx`: sidebar and phone-bar layout, language switch. - `router.test.tsx`: `/` and `/local` ask nothing but who is signed in. It must stay green unchanged. - `account-page.test.tsx`: details, download, deletion refusals and success, French. - `game-page.test.tsx`. - `my-games.test.tsx`. - `rpc-account-games.integration.test.ts` and `rpc-game-reads.integration.test.ts`: `game.list` as a Guest and as an Account. - `my-games.spec.ts` and `accounts.spec.ts` in `apps/e2e`. - **Edge and unhappy paths to cover:** - `hasGames` false for a browser with no Guest and no Session. - A Guest's Games counted for the Account after a claim. - Paging across Games that ended at the same instant. - A filter with zero Games. - Exactly one page of Games, so no "Show more". - Counts unchanged when a filter is applied. - A `section` or `result` search parameter outside the allowed values falls back to the default. - A wrong password in the dialog keeps the dialog open. - Cancel closes the dialog without a request. - "Copied" returns to "Copy link". - A reader with no side sees White before Black. - French copy on each screen. - Existing tests that bind to the removed settings cog, or to the old account and Game page layout, are rewritten to the new layout, not deleted. ## Out of Scope - The shared Game screen (board, player rows, move list) and the Room and Local screens. - The home, sign-in, sign-up and password-reset pages. - A new visual identity: tokens, palette and type stay. - Collapsing the sidebar on desktop; the owner finds desktop space sufficient. - Thumbnails of the final position in My games, and sorting other than newest first. - Changing what a Username, a Guest or a Session is, or how deletion works (#364). ## Further Notes - Prototype: branch `prototype/399-front-screens` (never merged). Run `pnpm dev` and use the floating "Prototype #399" panel. `?nav=D`, `?page=C` on `/account` and `/games/<id>`, and `?page=D&many=1` on `/games` show the chosen variants. - Research behind the choices: NN/g vertical navigation, mobile navigation, confirmation dialogs and empty states; Laws of UX (Hick, Fitts, serial position, Von Restorff, common region); shadcn `Sidebar` proportions; the Lichess analysis layout; GitHub's account deletion. - Proposed rule, for a dedicated change the owner asks for: view state a link should carry (a tab, a filter) lives in TanStack Router search parameters. It is not edited into `CODING_STANDARDS.md` here. - Supersedes the "To decide first" list on #399.
root commented 2026-10-14 14:30:26 +00:00 (Migrated from gitlab.core-project.space)

marked this issue as related to #399

marked this issue as related to #399
root commented 2026-10-14 14:30:28 +00:00 (Migrated from gitlab.core-project.space)

mentioned in issue #399

mentioned in issue #399
root commented 2026-10-14 14:37:15 +00:00 (Migrated from gitlab.core-project.space)

mentioned in issue #401

mentioned in issue #401
root commented 2026-10-14 14:37:31 +00:00 (Migrated from gitlab.core-project.space)

mentioned in issue #402

mentioned in issue #402
root commented 2026-10-14 14:37:33 +00:00 (Migrated from gitlab.core-project.space)

mentioned in issue #403

mentioned in issue #403
root commented 2026-10-14 14:37:50 +00:00 (Migrated from gitlab.core-project.space)

mentioned in issue #404

mentioned in issue #404
root commented 2026-10-14 14:37:51 +00:00 (Migrated from gitlab.core-project.space)

mentioned in issue #405

mentioned in issue #405
root commented 2026-10-14 14:37:54 +00:00 (Migrated from gitlab.core-project.space)

marked this issue as related to #401

marked this issue as related to #401
root commented 2026-10-14 14:37:55 +00:00 (Migrated from gitlab.core-project.space)

marked this issue as related to #402

marked this issue as related to #402
root commented 2026-10-14 14:37:56 +00:00 (Migrated from gitlab.core-project.space)

marked this issue as related to #403

marked this issue as related to #403
root commented 2026-10-14 14:37:57 +00:00 (Migrated from gitlab.core-project.space)

marked this issue as related to #404

marked this issue as related to #404
root commented 2026-10-14 14:37:58 +00:00 (Migrated from gitlab.core-project.space)

marked this issue as related to #405

marked this issue as related to #405
root commented 2026-10-14 14:52:27 +00:00 (Migrated from gitlab.core-project.space)

mentioned in merge request !527

mentioned in merge request !527
root commented 2026-10-14 15:46:04 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit 801eee8c75

mentioned in commit 801eee8c756016924e16c8f1d421c5ba654e4a5f
root commented 2026-10-14 15:46:04 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit 584b8ec1ae

mentioned in commit 584b8ec1ae41d4b503340db1c9f1ae5c0d5dda20
root commented 2026-10-14 15:46:04 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit 93aae90d64

mentioned in commit 93aae90d64fa62c514a450cb85dc31a4512f2662
root commented 2026-10-14 15:46:05 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit c0a41f20b6

mentioned in commit c0a41f20b608f5696e922e2ed0c22e7d7ad6523c
root commented 2026-10-14 15:56:43 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit 58d7de47c7

mentioned in commit 58d7de47c7f78a3bc39782f15c9623ec55de6671
root commented 2026-10-14 15:56:44 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit 86bf5c9957

mentioned in commit 86bf5c9957e6f657543fae96a7691fac656c9ed5
root commented 2026-10-14 15:56:44 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit 7abece0947

mentioned in commit 7abece0947fa346b83ea986cde6d2e51bcd0955e
root commented 2026-10-14 15:56:44 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit 484481eebe

mentioned in commit 484481eebed81c40f8390a1e362ae77bcbbc5ab1
root (Migrated from gitlab.core-project.space) closed this issue 2026-10-14 16:05:11 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amaurycoudr/chess-project#400
No description provided.