This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is a Quantum Gate Card Game (Qards) - an educational card game about quantum computing based on the Japanese game "Shichinarabe" (七並べ). Built with Next.js 15, React 19, TypeScript, and Tailwind CSS v4.
npm run dev # Start development server with Turbopack
npm run build # Build for production
npm run start # Start production server
npm run lint # Run ESLintnpm test # Run Jest tests (unit and integration tests)
npm run e2e # Run Cypress E2E tests interactively
npm run e2e:headless # Run Cypress E2E tests headlessly
npm run cypress:open # Open Cypress Test Runner (dev server must be running)
npm run cypress:run # Run Cypress tests headlessly (dev server must be running)/src/app/- Next.js App Router pages and layouts/src/components/- React components with 'use client' directiveGameScreen.tsx- Main game containerGameBoard.tsx- Game board displayPlayerHand.tsx- Player hand management
/src/game/- Core game logic (pure functions, no UI dependencies)types.ts- All TypeScript types and interfacesgameLogic.ts- Game state management and rules
/test/- Jest unit tests mirroring/src/structure/cypress/- Cypress E2E tests/cypress/e2e/- End-to-end test scenarios/cypress/fixtures/- Test data and mock data/cypress/support/- Custom commands and utilities
-
Separation of Concerns: Game logic (
/src/game/) is completely separated from UI components (/src/components/). This allows testing game rules independently of React. -
Type Safety: All game entities (Player, Card, GameState) are strongly typed in
types.ts. The game uses discriminated unions for card types (NumberCard | QuantumCard). -
State Management: Game state is managed in React components using useState hooks. No external state management library is used.
-
Component Pattern: Components use the 'use client' directive and are functional components with hooks.
- Cards: Various quantum computing cards including:
- QUBIT Cards: Initial quantum states (|0⟩, |1⟩, |+⟩, |-⟩)
- GATE Cards: Quantum gates (I, X, Z, H)
- CONTROL Cards: Used to create controlled operations (C)
- TARGET Cards: Auto-generated targets for controlled gates, displayed as 'O' (any Operation)
- UNITARY Cards: General unitary operations (U)
- MEASUREMENT Cards: Measurement operations (⟨0|, ⟨1|, ⟨+|, ⟨-|)
- Players: 3-6 players with elimination system for players who pass 4 times
- Board: 4-lane quantum circuit board
- Win Condition: Based on measurement points minus hand penalties when game ends
- Elimination System: Players who pass 4 times are eliminated individually; game continues with remaining players
TARGET cards are displayed with the symbol 'O' rather than 'T' to represent "any Operation". This design choice reflects that TARGET cards represent positions where any quantum operation can be applied as the target of a controlled gate, making 'O' a more intuitive and semantically correct representation than 'T'.
- Game initialization in
gameLogic.ts:initializeGame() - Card placement validation in
isValidPlay() - Turn management through
gameState.currentPlayerIdwith active player filtering - Player elimination system when passing 4 times
- Game ends when insufficient active players remain or other end conditions are met
- Measurement Cards: When a measurement card is played, points are awarded based on the quantum measurement outcome:
- Measurement result '1': +3 points
- Measurement result '0': +1 point
- Hand Penalty System: Remaining cards in hand apply penalties at game end:
- Quantum Gate Cards (I, X, Z, H): 2 cards per -1 point (rounded up)
- Examples: 1-2 cards = -1 pt, 3-4 cards = -2 pts, 5-6 cards = -3 pts
- All Other Cards (Qubit, Measurement, Unitary, Control, Target): 1 card per -2 points
- Examples: 1 card = -2 pts, 3 cards = -6 pts, 5 cards = -10 pts
- Quantum Gate Cards (I, X, Z, H): 2 cards per -1 point (rounded up)
- Quantum Integration: The game includes real quantum computation when possible, falling back to classical simulation
- Final Scoring: Measurement points minus hand penalty determines the winner
- TypeScript: Use strict type checking. Import types from
/src/game/types.ts - Testing:
- Write unit tests for any new game logic in
/test/game/ - Write component tests in
/test/components/ - Write E2E tests using Cypress in
/cypress/e2e/
- Write unit tests for any new game logic in
- Path Imports: Use
@/alias for imports (maps to./src/) - Client Components: Add 'use client' directive for interactive components
- Styling: Use Tailwind CSS v4 classes for all styling
- E2E Testing: Use data-* attributes to make it easier to target elements for E2E testing with Cypress
- All interactive elements should have unique
data-testidattributes - Use semantic naming for data-testid values (e.g.,
data-testid="start-game-button") - Avoid using text content or CSS classes as selectors in tests
- This ensures tests remain stable even when UI text or styling changes
- All interactive elements should have unique
- Feature branches → develop branch → main branch
- Create feature branches from
developfor new features and bug fixes - Merge feature branches into
developvia pull requests - Merge
developintomainfor releases mainbranch contains stable, production-ready code
- Always run tests before committing: Execute
npm testto ensure all tests pass - Never commit broken code: Verify that your changes don't break existing functionality
- Pre-commit checklist:
- Run
npm test- all tests must pass - Run
npm run lint- fix any linting errors - Run
npm run build- ensure the build succeeds - Review your changes with
git diff
- Run
This project is licensed under the MIT License. All source code files include SPDX license identifiers for compliance and clarity.
- All source files (.ts, .tsx, .js, .jsx, .css) must include both SPDX headers
- Header format:
For CSS files use
// SPDX-License-Identifier: MIT // SPDX-FileCopyrightText: Copyright 2025 OpenQL Project/* */comment style instead of// - Placement: SPDX headers must be the very first lines of each file
- JSON files: Skip JSON files as they don't support comments
- Generated files: Skip auto-generated files like
next-env.d.ts
The project uses a lightweight custom i18n implementation using React Context API instead of external libraries. This approach is chosen for:
- Limited translation scope (UI elements and game terms only)
- Support for only 2 languages (Japanese and English)
- Static content without dynamic translation requirements
- Minimal dependencies for better performance
src/i18n/
├── translations/
│ ├── ja.json # Japanese translations (default)
│ └── en.json # English translations
├── context.tsx # Language Context definition
├── provider.tsx # Language Provider component
└── useTranslation.ts # Custom hook for translations
import { useTranslation } from '@/i18n/useTranslation';
function Component() {
const { t } = useTranslation();
return <h1>{t('common.gameTitle')}</h1>;
}common.*- Common UI elements (buttons, titles)game.*- Game-specific terms (turn, score, etc.)cards.*- Card type names and descriptionssettings.*- Settings screen labelsrules.*- Game rules and instructionsmessages.*- System messages and notifications
- Quantum notation symbols (|0⟩, |1⟩, etc.) remain unchanged across languages
- Number formatting is consistent across languages
- Language preference is stored in localStorage
- Language changes apply immediately without page reload
- to memorize