feat: update CLAUDE.md

This commit is contained in:
tiennm99 committed 2025-08-04 23:22:23 +07:00
1 parent ec85a43061
commit efb8a1663b
1 file changed
+238 -41
+238 -41
View File
@@ -2,59 +2,256 @@
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
## 🇻🇳 VNGeoGuessr - Project Configuration
This is **vngeoguessr** - a Next.js 15 application built with React 19, TypeScript, and Tailwind CSS. The project appears to be a GeoGuessr-like application (based on the name), currently in initial development stage with the default Next.js template.
A Vietnamese location-guessing game built with Next.js, featuring interactive maps, real-time multiplayer, and scoring systems focused on Vietnam geography.
## Development Commands
## 🛠️ Development Environment
### Core Development
- `npm run dev` or `pnpm dev` - Start development server with Turbopack (runs on http://localhost:3000)
- `npm run build` - Build the application for production
- `npm start` - Start production server
- `npm run lint` - Run ESLint for code quality checks
- **Language**: TypeScript (`^5.0.0`)
- **Framework**: Next.js 15 (App Router)
- **Styling**: Tailwind CSS v4
- **Component Library**: shadcn/ui
- **State Management**: Zustand
- **Maps**: Google Maps JavaScript API
- **Backend**: Supabase (Database, Auth, Storage, Realtime)
- **Geo Calculations**: Turf.js
- **Testing**: Jest + React Testing Library
- **Linting**: ESLint with `@typescript-eslint`
- **Formatting**: Prettier
- **Package Manager**: `pnpm` (preferred)
- **Hosting**: Vercel
- **Analytics**: Vercel Analytics
### Package Management
The project uses both npm (package-lock.json) and pnpm (pnpm-lock.yaml). Prefer `pnpm` commands when available.
## ⚙️ Development Commands
## Architecture & Structure
- **Dev server**: `pnpm dev` (with Turbopack, runs on http://localhost:3000)
- **Build**: `pnpm build`
- **Start**: `pnpm start`
- **Lint**: `pnpm lint`
- **Format**: `pnpm format`
- **Test**: `pnpm test`
- **Type check**: `pnpm type-check`
### Tech Stack
- **Framework**: Next.js 15 with App Router
- **React**: Version 19.1.0
- **TypeScript**: TypeScript 5 with strict mode enabled
- **Styling**: Tailwind CSS v4 with PostCSS
- **Fonts**: Geist Sans and Geist Mono from Google Fonts
- **Bundler**: Turbopack (enabled in dev mode)
## 📂 Project Structure
### Directory Structure
```
src/
app/ # Next.js App Router directory
layout.tsx # Root layout with font configuration
page.tsx # Home page component
globals.css # Global Tailwind styles
public/ # Static assets (SVG icons)
.
├── app/ # App Router structure
│ ├── layout.tsx
│ ├── page.tsx
│ ├── game/
│ │ ├── [gameId]/
│ │ └── create/
│ ├── leaderboard/
│ ├── profile/
│ └── api/
│ ├── games/
│ └── scores/
├── components/ # UI components
│ ├── ui/ # shadcn/ui components
│ ├── game/ # Game-specific components
│ │ ├── MapView.tsx
│ │ ├── GuessMarker.tsx
│ │ ├── ScoreDisplay.tsx
│ │ └── GameControls.tsx
│ ├── maps/ # Map-related components
│ └── auth/ # Authentication components
├── stores/ # Zustand stores
│ ├── gameStore.ts
│ ├── userStore.ts
│ └── mapStore.ts
├── hooks/ # Custom React hooks
│ ├── useSupabase.ts
│ ├── useGoogleMaps.ts
│ └── useGameLogic.ts
├── lib/ # Utilities and configurations
│ ├── supabase/
│ │ ├── client.ts
│ │ ├── auth.ts
│ │ └── realtime.ts
│ ├── maps/
│ │ ├── googleMaps.ts
│ │ └── streetView.ts
│ ├── game/
│ │ ├── scoring.ts
│ │ ├── distance.ts # Turf.js calculations
│ │ └── locations.ts
│ └── utils.ts
├── types/ # TypeScript type definitions
│ ├── game.ts
│ ├── user.ts
│ └── maps.ts
├── styles/ # Tailwind customizations
├── tests/ # Unit and integration tests
├── public/
├── .env.local.example
├── .eslintrc.js
├── tailwind.config.ts
├── tsconfig.json
├── postcss.config.js
├── next.config.js
├── package.json
└── README.md
```
### Key Configuration
- **TypeScript**: Configured with path mapping (`@/*` → `./src/*`)
- **ESLint**: Next.js config with modern ESLint 9
- **Target**: ES2017 with modern module resolution
## 📦 Required Dependencies
### Current State
The application is currently using the default Next.js template with Tailwind CSS. The main page displays the standard Next.js welcome screen with deployment and documentation links.
```bash
# Core dependencies
pnpm add @supabase/supabase-js @supabase/auth-helpers-nextjs
pnpm add zustand
pnpm add @turf/turf @turf/distance @turf/helpers
pnpm add @googlemaps/js-api-loader
## Development Notes
# Development dependencies
pnpm add -D @types/google.maps
```
### Font System
The app uses Geist font family (both Sans and Mono variants) loaded via `next/font/google` with CSS variables for consistent typography.
**Setup Requirements:**
- Tailwind CSS with PostCSS configuration
- shadcn/ui: `npx shadcn-ui@latest init`
- Google Maps API key in environment variables
- Supabase project with RLS policies configured
### Styling Approach
- Tailwind CSS v4 with modern configuration
- CSS variables for font families
- Dark mode support built into components
- Responsive design patterns (sm: breakpoints)
## 🌍 Environment Variables
### File Editing
The main entry point for development is `src/app/page.tsx`. The layout is configured in `src/app/layout.tsx` with global styles in `src/app/globals.css`.
```bash
# Google Maps
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=your_api_key_here
# Supabase
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
# Vercel Analytics (auto-configured on Vercel)
```
## 🎮 Game Logic Architecture
### Scoring System
- Use Turf.js `distance()` for geographical calculations
- Exponential scoring: closer guesses = exponentially higher points
- Store scoring logic in `lib/game/scoring.ts`
### State Management (Zustand)
- **GameStore**: Current game state, rounds, scores, guesses
- **UserStore**: Authentication state, user preferences, statistics
- **MapStore**: Map settings, current location, Street View state
### Real-time Features
- Supabase Realtime for multiplayer game rooms
- Live game state updates and synchronization
- Connection state handling and reconnection logic
## 🗺️ Google Maps Integration
### Street View Implementation
- Random locations with Street View coverage verification
- Panorama controls and movement restrictions
- Street View availability checks before game start
### Interactive Guessing Map
- World map for placing guesses with custom markers
- Distance visualization between guess and actual location
- Smooth animations and transitions between rounds
## 💾 Supabase Database Schema
```sql
-- Games table
games (
id uuid primary key,
created_by uuid references auth.users,
game_mode text,
max_rounds integer,
time_limit integer,
created_at timestamp,
status text
)
-- Game rounds table
game_rounds (
id uuid primary key,
game_id uuid references games,
round_number integer,
location_lat float,
location_lng float,
street_view_data jsonb
)
-- Player guesses table
player_guesses (
id uuid primary key,
game_id uuid references games,
player_id uuid references auth.users,
round_id uuid references game_rounds,
guess_lat float,
guess_lng float,
distance_km float,
score integer,
time_taken integer
)
```
## 🧪 Testing Strategy
- **Framework**: Jest + React Testing Library
- **Mocking**: Google Maps API calls, Supabase client interactions
- **Focus Areas**: Game logic (scoring, distance calculations), component rendering
- **Integration Tests**: Full game flow with mocked external services
## 📱 Development Guidelines
### Component Architecture
- Use shadcn/ui for base UI components (buttons, dialogs, forms)
- Game-specific components in `components/game/`
- Responsive design with mobile-first approach
- Handle loading states for maps and Street View
### Performance Optimization
- Lazy load Google Maps API
- React.memo for expensive game components
- Optimize Supabase queries with proper indexing
- Image optimization for location thumbnails
### Security Implementation
- Row Level Security (RLS) policies for all user data
- Server-side validation for all game inputs
- Rate limiting on game creation and submission endpoints
- Secure API routes with authentication middleware
## 💡 Common Development Patterns
```typescript
// Game state management with Zustand
const useGameStore = create<GameState>((set) => ({
currentRound: 1,
score: 0,
guesses: [],
updateScore: (points) => set((state) => ({ score: state.score + points }))
}))
// Distance calculation with Turf.js
import { distance } from '@turf/turf'
const calculateDistance = (guess: [number, number], actual: [number, number]) => {
return distance(guess, actual, { units: 'kilometers' })
}
// Supabase real-time subscription
const gameChannel = supabase
.channel('game-updates')
.on('postgres_changes', { event: '*', schema: 'public', table: 'games' },
(payload) => handleGameUpdate(payload))
.subscribe()
```
## 🧩 Custom Development Commands
For future implementation in `.claude/commands/`:
- `/create-game-component` - Scaffold game component with TypeScript
- `/setup-map-integration` - Configure Google Maps with Street View
- `/add-zustand-store` - Create new Zustand store with proper typing
- `/implement-scoring` - Add scoring logic with Turf.js calculations
- `/setup-realtime` - Configure Supabase Realtime features