Skip to content

Commit 4b3741d

Browse files
authored
Merge pull request #430 from TaloDev/develop
Release 0.64.0
2 parents 91f3bb6 + 73eb5a9 commit 4b3741d

File tree

9 files changed

+333
-33
lines changed

9 files changed

+333
-33
lines changed

.github/workflows/claude-code-review.yml

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,65 @@ jobs:
3737
with:
3838
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
3939
prompt: |
40-
Please review this pull request and provide feedback on:
41-
- Code quality and best practices
42-
- Potential bugs or issues
43-
- Performance considerations
44-
- Security concerns
45-
46-
Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.
47-
Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
48-
49-
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
50-
# or https://docs.anthropic.com/en/docs/claude-code/sdk#command-line for available options
51-
claude_args: '--model sonnet --allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'
52-
use_sticky_comment: true
40+
You are reviewing PR #${{ github.event.pull_request.number }} in the repository ${{ github.repository }}.
41+
42+
Review this pull request and provide feedback focused only on improvements needed (not what works well):
43+
44+
**Categories to check:**
45+
1. Code quality and best practices
46+
2. Potential bugs or issues
47+
3. Performance considerations
48+
4. Security concerns
49+
50+
**Process:**
51+
- The PR number is: ${{ github.event.pull_request.number }}
52+
- View the PR using: `gh pr view ${{ github.event.pull_request.number }} --repo ${{ github.repository }}`
53+
- Read CLAUDE.md to understand best practices
54+
- View the PR diff using: `gh pr diff ${{ github.event.pull_request.number }} --repo ${{ github.repository }}`
55+
- If an issue spans multiple categories, list it only once in the most relevant section
56+
- Prioritize by severity: 🔴 Critical → 🟡 Major → 🔵 Minor
57+
- Focus only on changes introduced in this PR, not pre-existing code issues
58+
59+
**Review Workflow (Follow these steps):**
60+
1. **Analysis Phase**: Review the PR diff and identify potential issues
61+
2. **Validation Phase**: For each issue you find, verify it by:
62+
- Re-reading the relevant code carefully
63+
- Checking if your suggested fix is actually different from the current code
64+
- Confirming the issue violates documented standards (check CLAUDE.md)
65+
- Ensuring your criticism is actionable and specific
66+
3. **Draft Phase**: Write your review only after validating all issues
67+
4. **Quality Check**: Before posting, remove any issues where:
68+
- Your "before" and "after" code snippets are identical
69+
- You're uncertain or use phrases like "appears", "might", "should verify"
70+
- The issue is theoretical without clear impact
71+
5. **Post Phase**: Only post the review if you have concrete, validated feedback
72+
73+
**Edge Case Policy:**
74+
Only flag edge cases that meet ALL of these criteria:
75+
1. Realistic: Could happen in normal usage or common error scenarios
76+
2. Impactful: Would cause bugs, security issues, or data problems (not just "it's not perfect")
77+
3. Actionable: Can be fixed with reasonable effort in this PR's scope
78+
79+
Ignore theoretical issues that require multiple unlikely conditions or malicious input patterns.
80+
Use the "would this bother a pragmatic senior developer?" test.
81+
82+
Maximum chain of assumptions: 2 levels deep. Skip exotic input combinations that violate documented assumptions.
83+
84+
**Feedback style:**
85+
- Provide specific code examples or line references showing the issue
86+
- Suggest concrete fixes with code snippets where helpful
87+
- Keep total feedback under 500 words
88+
- Use section headers with emojis and horizontal dividers (---)
89+
- If no improvements needed in a category, simply state "No issues found"
90+
- Use neutral language; focus on the code, not the author
91+
- If the PR looks good overall, say so clearly rather than forcing criticism
92+
93+
**Comment Management (IMPORTANT):**
94+
Post your review using this command, which will edit your last comment if one exists, or create a new one:
95+
```bash
96+
gh pr comment ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --edit-last --create-if-none --body "<review>"
97+
```
98+
99+
Ensure proper escaping of quotes and special characters in the comment body. Use single quotes around the body and escape any single quotes inside with '\''
100+
claude_args: |
101+
--allowedTools "Read,Bash(gh pr:*),Grep,Glob"

CLAUDE.md

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
Talo is a self-hostable game dev dashboard. This is the frontend React application that provides a web interface for managing players, leaderboards, events, stats, game saves, and other game backend features. The frontend communicates with the Talo backend API.
8+
9+
## Development Commands
10+
11+
### Running the application
12+
```bash
13+
npm run dev # Start dev server on http://localhost:8080
14+
npm run dev:e2e # Start dev server in e2e mode for Cypress tests
15+
npm run build # Build for production (runs tsc + vite build)
16+
```
17+
18+
### Testing
19+
```bash
20+
npm test # Run all Vitest unit tests (runs with TZ=UTC)
21+
npm test -- <pattern> # Run specific test file(s) matching pattern
22+
npm run test:e2e # Start dev server and open Cypress for e2e tests
23+
npm run cypress:open # Open Cypress (dev server must be running)
24+
```
25+
26+
### Code Quality
27+
```bash
28+
npm run lint # Run ESLint on src/**/*.{js,jsx,ts,tsx}
29+
```
30+
31+
### Testing Notes
32+
- Unit tests use Vitest with jsdom environment
33+
- Test files are co-located with source in `__tests__/` directories
34+
- E2E tests are in `cypress/e2e/pages/` and use Cypress
35+
- Coverage excludes `src/api/`, `src/entities/`, `src/constants/`, and `src/utils/canViewPage.ts`
36+
- Tests must run with `TZ=UTC` for consistent date handling
37+
38+
## Architecture Overview
39+
40+
### Tech Stack
41+
- React 18 with TypeScript
42+
- Vite for build tooling
43+
- React Router v6 for routing
44+
- Recoil for global state management
45+
- Axios for HTTP requests
46+
- SWR for data fetching and caching
47+
- Zod for runtime validation
48+
- Tailwind CSS v4 for styling
49+
- Recharts for charts
50+
- React Hook Form for forms
51+
52+
### Directory Structure
53+
54+
```
55+
src/
56+
├── api/ # SWR hooks and API functions (91 files)
57+
├── components/ # Reusable UI components
58+
│ ├── billing/
59+
│ ├── charts/
60+
│ ├── events/
61+
│ ├── saves/
62+
│ ├── tables/
63+
│ ├── toast/
64+
│ └── toggles/
65+
├── constants/ # App constants (routes, nav, user types)
66+
├── entities/ # TypeScript types and Zod schemas (29 domain models)
67+
├── modals/ # Modal dialog components
68+
├── pages/ # Page components (39 pages)
69+
├── services/ # Business logic (AuthService)
70+
├── state/ # Recoil atoms (8 state files)
71+
├── styles/ # CSS files
72+
├── utils/ # Utilities and custom hooks
73+
│ ├── group-rules/
74+
│ └── validation/
75+
├── App.tsx # Main app component (handles auth and routing)
76+
├── Router.tsx # Route definitions with lazy loading
77+
└── index.tsx # App entry point
78+
```
79+
80+
### Routing
81+
- Routes are defined in [Router.tsx](src/Router.tsx) using React Router v6
82+
- Route paths are constants in [src/constants/routes.ts](src/constants/routes.ts)
83+
- All pages use lazy loading via `React.lazy()` for code splitting
84+
- Routes are split into unauthenticated (login, register) and authenticated sections
85+
- Permission checks use `canViewPage()` utility before rendering routes
86+
- Many routes only render when an `activeGame` is selected
87+
88+
### State Management
89+
- Global state uses Recoil with atoms in [src/state/](src/state/)
90+
- Key atoms:
91+
- `userState` - Current authenticated user
92+
- `activeGameState` - Currently selected game (persisted to localStorage)
93+
- `gamesState` - User's games list
94+
- `organisationState` - Organization data
95+
- `devDataState` - Dev data inclusion flag
96+
- State consumed via `useRecoilValue()`, `useRecoilState()`, `useSetRecoilState()`
97+
98+
### API Layer
99+
- Base Axios instance configured in [src/api/api.ts](src/api/api.ts)
100+
- Request interceptor adds Bearer token and dev data header
101+
- Response interceptor handles 401s with automatic token refresh
102+
- Base URL from `VITE_API_URL` environment variable
103+
104+
**Data fetching patterns:**
105+
106+
1. **SWR hooks** (23 hooks): Pattern is `use{Entity}(game, params)` returning `{ data, loading, error }`
107+
- Examples: `useEvents`, `useLeaderboards`, `useStats`
108+
- Uses `makeValidatedGetRequest()` for Zod validation
109+
- Automatic caching, revalidation, and deduplication
110+
111+
2. **Mutation functions** (68 functions): Named after action (e.g., `createLeaderboard`, `updatePlayer`)
112+
- Uses `makeValidatedRequest()` wrapper for Zod validation
113+
- Returns validated, typed responses
114+
115+
### Component Patterns
116+
- Functional components with TypeScript
117+
- Composition over inheritance
118+
- Context for cross-cutting concerns (EventsContext, ToastProvider)
119+
- Form handling with React Hook Form
120+
- Tables use composable system: `Table` > `TableHeader`/`TableBody` > `TableCell`
121+
122+
### Key Utilities and Hooks
123+
Located in [src/utils/](src/utils/):
124+
125+
- `useTimePeriod` - Date range calculation from period strings ('1d', '7d', '30d', 'w', 'm', 'y')
126+
- `useTimePeriodAndDates` - Combined time period and date management
127+
- `useLocalStorage` - localStorage with React state sync
128+
- `usePlayer` - Extract player from URL params
129+
- `useSortedItems` - Client-side sorting
130+
- `useSearch` - Client-side search filtering
131+
- `useNodeGraph` - Graph visualization for save data (using @xyflow/react)
132+
- `buildError` - Normalize error objects
133+
- `canPerformAction` / `canViewPage` - Permission checking
134+
- `getEventColour` - Consistent color assignment for events
135+
136+
## Important Patterns
137+
138+
### Authentication
139+
- Managed by [AuthService](src/services/AuthService.ts) singleton
140+
- Token-based with automatic refresh on 401 responses
141+
- Token stored in memory (not localStorage for security)
142+
- Login redirects handled via `useIntendedRoute` hook
143+
144+
### Authorization
145+
- Route-level checks with `canViewPage()` in Router
146+
- Action-level checks with `canPerformAction()` throughout components
147+
- Based on user type (ADMIN, OWNER, DEV, DEMO)
148+
149+
### Validation
150+
- Zod schemas defined alongside entities in [src/entities/](src/entities/)
151+
- `makeValidatedRequest()` and `makeValidatedGetRequest()` wrappers ensure type safety
152+
- Validation errors logged and sent to Sentry
153+
154+
### Error Handling
155+
- Centralized error normalization via `buildError()`
156+
- API errors show user-friendly messages via toast notifications
157+
- Sentry integration for error tracking
158+
159+
### Date Handling
160+
- All API dates must be UTC
161+
- Use `convertDateToUTC()` when sending dates to API
162+
- Tests run with `TZ=UTC` to ensure consistency
163+
164+
### Active Game Context
165+
- Most features require an active game to be selected
166+
- Active game stored in Recoil state and persisted to localStorage
167+
- Routes conditionally render based on `activeGame` availability
168+
169+
## Environment Variables
170+
171+
Required environment variables (set via `.env` files):
172+
- `VITE_API_URL` - Backend API base URL (e.g., `http://localhost:3000`)
173+
174+
## Node Version
175+
176+
This project requires Node.js 22.x (see package.json engines).
177+
178+
## Git Workflow
179+
180+
Main branch for PRs: `develop`

0 commit comments

Comments
 (0)