diff --git a/CHANGELOG.md b/CHANGELOG.md
index fbbf08f5..0f93f18e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,7 +9,7 @@ Since the `1.0.0-beta` release, the version in `package.json` has stayed at `1.0
**Monthly batching (agents):** Use **one** `## [1.0.0-ci] - YYYY-MM-DD` header per calendar month. Before editing, search this file for `- YYYY-MM-` (today’s year-month); if a section exists, append bullets under `### Added` / `### Changed` / `### Fixed` there and set that header’s date to today — do **not** add a second `##` for the same month. A new ship day is not a new section.
-## [1.0.0-ci] - 2026-11-06
+## [1.0.0-ci] - 2026-11-07
### Added
@@ -20,6 +20,7 @@ Since the `1.0.0-beta` release, the version in `package.json` has stayed at `1.0
### Changed
- **Dashboard tables:** tournament game rows no longer use bold text; the Event column badge identifies ladder, tournament, and organized-event games.
+- **Open challenges:** clicking a game name in the site-wide list now opens the game page instead of a list of that game's challenges, which remain available on the game page's **Challenges** tab.
### Fixed
diff --git a/docs/guides/routing.md b/docs/guides/routing.md
index 15a69778..68d5b86d 100644
--- a/docs/guides/routing.md
+++ b/docs/guides/routing.md
@@ -10,7 +10,7 @@ All routes are defined in [`src/pages/Skeleton.js`](../src/pages/Skeleton.js) in
| `/move/:metaGame/:cbits/:gameID` | `GameMoveWrapper` | Live game |
| `/games/:metaGame?` | `Explore` | Lazy-loaded |
| `/player/:userid` | `Player` | Lazy-loaded |
-| `/challenges/:metaGame` | `StandingChallenges` | |
+| `/challenges/:metaGame?` | `StandingChallenges` | Site-wide list when `:metaGame` is omitted |
| `/listgames/:gameState/:metaGame` | `ListGames` | |
| `/ratings/:metaGame` | `Ratings` | |
| `/tournaments/:tab?/:metaGame?` | `Tournaments` | Tabbed list (`open`, `current`, `completed`); optional game filter |
diff --git a/docs/subsystems/challenges.md b/docs/subsystems/challenges.md
index 92ebc731..c0df6385 100644
--- a/docs/subsystems/challenges.md
+++ b/docs/subsystems/challenges.md
@@ -1,6 +1,8 @@
# Challenges
-Standing challenges let players post open invitations for a specific meta-game. Route: `/challenges/:metaGame`.
+Standing challenges let players post open invitations for a specific meta-game. Routes: `/challenges` (site-wide) and `/challenges/:metaGame` (single game).
+
+In the site-wide list, the game name links to the game page (`/games/:metaGame`) so players browsing challenges can read about a game. That page's **Challenges** tab lists the same per-game challenges.
## Key files
diff --git a/src/components/StandingChallenges.js b/src/components/StandingChallenges.js
index 306f237a..76604fed 100644
--- a/src/components/StandingChallenges.js
+++ b/src/components/StandingChallenges.js
@@ -565,7 +565,7 @@ function StandingChallenges(props) {
header: t("tables.game"),
sortingFn: stringColumnSortingFn(i18n.language),
cell: (props) => (
-
+
{props.getValue()}
),
diff --git a/src/components/StandingChallenges.test.js b/src/components/StandingChallenges.test.js
new file mode 100644
index 00000000..4c369fb1
--- /dev/null
+++ b/src/components/StandingChallenges.test.js
@@ -0,0 +1,57 @@
+import { render, screen } from "@testing-library/react";
+import { HelmetProvider } from "react-helmet-async";
+import { MemoryRouter } from "react-router-dom";
+import { beforeEach, describe, expect, it, vi } from "vitest";
+import StandingChallenges from "./StandingChallenges";
+import { useStore } from "../stores";
+
+vi.mock("react-i18next", async (importOriginal) => ({
+ ...(await importOriginal()),
+ useTranslation: () => ({
+ t: (key) => key,
+ i18n: { language: "en", changeLanguage: vi.fn() },
+ }),
+}));
+
+vi.mock("../hooks/useAuthSession", () => ({
+ useAuthSession: () => ({ status: "anonymous" }),
+}));
+
+vi.mock("./Me/ChallengeResponseModal", () => ({ default: () => null }));
+
+const challenge = {
+ id: "challenge-1",
+ metaGame: "homeworlds",
+ challenger: { id: "player-1", name: "Player One" },
+ players: [{ id: "player-1", name: "Player One" }],
+ variants: [],
+ numPlayers: 2,
+ seating: "random",
+ rated: true,
+ clockStart: 72,
+ clockInc: 24,
+ clockMax: 240,
+};
+
+describe("StandingChallenges (site-wide)", () => {
+ beforeEach(() => {
+ useStore.setState({ globalMe: null, users: [] });
+ vi.stubGlobal(
+ "fetch",
+ vi.fn(async () => new Response(JSON.stringify([challenge])))
+ );
+ });
+
+ it("links the game name to the game page", async () => {
+ render(
+
+
+
+
+
+ );
+
+ const link = await screen.findByRole("link", { name: "Homeworlds" });
+ expect(link).toHaveAttribute("href", "/games/homeworlds");
+ });
+});