diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..00770bc --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,464 @@ +# AI Agent Guidelines for MineSeeker + +This document provides guidelines and context for AI coding agents working on the MineSeeker project. + +## Project Overview + +**MineSeeker** is a real-time multiplayer 1v1 minesweeper game built with Symfony (PHP) and React. Players compete to claim mines on a shared 16×16 grid, with the first to reach 26 mines winning. + +### Tech Stack + +- **Backend:** Symfony 7.2 (PHP 8.3) +- **Frontend:** React 18, Vite 6 +- **Database:** PostgreSQL 17 with materialized views +- **Storage:** MinIO (S3-compatible) +- **Real-time:** Mercure (Server-Sent Events) +- **Styling:** SCSS, MUI (Material-UI), Emotion +- **Fonts:** @fontsource packages (web), Carlito-Bold.ttf (server-side images) + +### Key Features + +**Core Gameplay:** +- **Multiplayer-focused:** 1v1 competitive gameplay where players race to claim more mines than their opponent +- **Win condition:** First player to claim 26 out of 51 mines wins +- **Real-time updates:** WebSocket-like gameplay using Mercure (Server-Sent Events) +- **Game restoration:** Players can resume unfinished games from where they left off +- **Bonus points system:** Rewards skilled play (blind hits, chain combos, edge mines, endgame mines, safe cell reveals) + +**User Features:** +- **Authentication:** Password + optional TOTP + optional WebAuthn passkeys +- **Anonymous play:** Guest players can play without creating an account +- **Profile statistics:** Detailed stats including wins, losses, draws, win rate, average score, total mines hit, and bonus points +- **Battle history:** View and replay past games move-by-move + +**Sharing & Social:** +- **Battle reports:** Shareable public pages for each completed game (`/battle/{uuid}`) +- **OG image generation:** Automatic creation of 1200×630 PNG images for social media sharing (using PHP GD) +- **Open Graph tags:** Battle share pages include rich preview cards with player names, avatars, scores, and bonus points + +--- + +## Architecture Overview + +### Backend (Symfony) + +``` +src/ +├── Controller/ # HTTP endpoints (game, profile, battle sharing) +├── Entity/ # Doctrine ORM entities +├── Repository/ # Database queries (uses QueryBuilder, not raw SQL) +├── Service/ # Business logic (BattleCardGenerator, WebAuthn, Email) +├── Dto/ # Data Transfer Objects (immutable, readonly) +├── Util/ # Game logic (TopicManager for Mercure) +└── Migrations/ # Database schema changes +``` + +**Important patterns:** +- Use Doctrine ORM QueryBuilder (not raw SQL) in repositories +- DTOs are `final readonly` classes with constructor property promotion +- Services use dependency injection via `config/services.yaml` +- Materialized views for performance (auto-refreshed via triggers) + +### Frontend (React) + +``` +assets/ +├── js/ +│ ├── mine-seeker/ # Main game bundle (self-contained) +│ │ ├── MineSeeker.jsx # Root component, wraps GameProvider + QueryClientProvider +│ │ ├── components/ # Game-specific components +│ │ │ ├── GameBoard.jsx # Main game board grid +│ │ │ ├── GameTimer.jsx # Game timer display +│ │ │ ├── BonusBox.jsx # Bonus points indicator +│ │ │ ├── BonusStatsDialog.jsx # Bonus statistics modal +│ │ │ ├── CaptchaOverlay.jsx # Captcha challenge overlay +│ │ │ ├── ChallengeCountdown.jsx # Challenge timer +│ │ │ ├── OnlinePlayersDialog.jsx # Online players list +│ │ │ ├── WaitingOverlayContent.jsx # Waiting for opponent +│ │ │ ├── grid/ # Grid-related components (cells, mines) +│ │ │ ├── profile/ # In-game profile components (PlayerColumn) +│ │ │ ├── timer/ # Timer-related components +│ │ │ └── user/ # User-related components +│ │ ├── contexts/ # React Context API +│ │ │ ├── GameContext.jsx # Game state context +│ │ │ └── GameProvider.jsx # Context provider with state logic +│ │ ├── hooks/ # Custom React hooks +│ │ │ ├── useGameDataProvider.js # React Query data provider +│ │ │ ├── useGameRefs.jsx # Refs for DOM elements +│ │ │ ├── useGameState.jsx # Game state management +│ │ │ ├── useServerCommunication.jsx # Mercure SSE connection +│ │ │ └── useStepTimer.jsx # Step-by-step timer +│ │ └── utils/ # Game-specific utilities +│ │ └── constants.jsx # Game constants, colors, defaults +│ ├── components/ # Shared UI components +│ ├── utils/ # Shared utilities +│ ├── profile.jsx # Profile page entry +│ ├── passkey.jsx # Passkey management entry +│ └── contact.jsx # Contact form entry +├── css/ +│ └── homepage/ # SCSS partials (imported by style.homepage.scss) +└── fonts/ + └── Carlito-Bold.ttf # TTF font for PHP GD image generation +``` + +**Important patterns:** +- Vite aliases: `@mine-components`, `@mine-contexts`, `@mine-hooks`, `@mine-utils`, `@global-components`, `@global-utils` +- React Query only available inside `mine-seeker` bundle +- Avoid circular dependencies (e.g., don't import from `@global-components` inside `components/` directory) +- PropTypes required on all components + +--- + +## Common Tasks + +### Adding a New Feature + +1. **Backend:** + - Create migration for schema changes + - Add/update entities and repositories + - Create DTOs for data transfer + - Add controller endpoints + - Update service configuration if needed + +2. **Frontend:** + - Create components in appropriate bundle + - Add PropTypes to all components + - Use existing hooks and utilities + - Follow styled-components pattern for MUI customization + +3. **Documentation:** + - Update relevant docs in `docs/` folder + - Add examples if introducing new patterns + +### Database Changes + +- Always create migrations: `bin/console make:migration` +- Use Doctrine QueryBuilder in repositories (not raw SQL) +- For PostgreSQL-specific features (materialized views, triggers), use raw SQL in migrations only +- Materialized views should auto-refresh via triggers + +### Styling + +- **Web fonts:** Use `@fontsource` packages (WOFF/WOFF2) +- **Server-side images:** Use TTF fonts in `assets/fonts/` (PHP GD requires TTF) +- **CSS:** Create SCSS partials in `assets/css/homepage/`, import in main file +- **Components:** Use Emotion styled-components or CSS classes + +### File Headers + +All PHP and JS/JSX files should have this header: + +```php +` +- **Formatting:** 4-space indentation, opening braces on same line for methods/classes + +**Example DTO:** + +```php +final readonly class ProfileGameDto implements JsonSerializable +{ + public function __construct( + public ?int $id, + public string $redName, + public string $blueName, + public bool $bothRegistered, + ) {} +} +``` + +### JavaScript/React + +- **Components:** Functional components with hooks +- **PropTypes:** Required on all components +- **Imports:** Use aliases (`@global-components`, `@mine-hooks`, etc.) +- **State:** Use `useState`, `useEffect`, `useCallback`, `useMemo` appropriately +- **Avoid:** Circular dependencies, especially with barrel exports + +**Example component:** + +```javascript +import React, { useState } from 'react'; +import { string, number } from 'prop-types'; + +export const MyComponent = ({ title, count }) => { + const [value, setValue] = useState(0); + + return