Daily GeoGame is built as a full-stack Next.js application using the App Router pattern. The architecture follows a client-server model with React Server Components and API routes.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/igorek05m/daily-geogame/llms.txt
Use this file to discover all available pages before exploring further.
High-level overview
The application is structured as a monolithic Next.js app with:- Frontend: React 19 components with TypeScript
- Backend: Next.js 15 API routes
- Database: MongoDB Atlas for persistent storage
- External APIs: RestCountries and CIA World Factbook
- Session management: HTTP-only cookies with UUID-based sessions
Frontend architecture
Component hierarchy
The main page (app/page.tsx) uses a suspense-wrapped component structure:
- Main page:
app/page.tsx:15-119 - Components in
app/components/
State management
TheuseDailyGame hook (app/hooks/useDailyGame.ts) centralizes all game state:
- Fetches game data on mount via parallel API calls
- Manages URL query params (
?date=YYYY-MM-DD) - Handles guess submission with optimistic updates
- Calculates day numbers from
GAME_START_DATE
app/hooks/useDailyGame.ts:6-235
Data fetching pattern
The hook usesPromise.all for parallel requests on load:
app/hooks/useDailyGame.ts:89-93
Backend architecture
API routes
Four Next.js API routes handle all server-side logic:| Route | Method | Purpose |
|---|---|---|
/api/daily | GET | Returns daily game data (target country, hints) |
/api/progress | GET/POST | Loads/saves user progress for a date |
/api/stats | GET | Fetches global stats for a date |
/api/country | GET | Proxies RestCountries API with caching |
app/api/*/route.ts.
Daily game generation
The/api/daily route generates a new game if one doesn’t exist for the requested date:
app/api/daily/route.ts:72-136
Hint reveal logic
Hints are progressively revealed based on guess count:app/api/daily/route.ts:139-156
Guess processing
The/api/progress POST endpoint calculates distance, bearing, and connection for each guess:
app/api/progress/route.ts:35-63
Database schema
MongoDB collections
daily_games
Stores one document per game date:
user_progress
Tracks progress for each session + date combination:
{ sessionId: 1, date: 1 }
Connection pooling
The MongoDB client uses a singleton pattern to reuse connections:clientPromise to share the same connection pool.
Reference: app/lib/mongodb.ts:1-22
Data flow
User guess submission
Page load sequence
- Initial render: Show loading state
- Parallel fetch: Request
/api/progress,/api/daily,/api/stats - Progress check: Restore previous guesses from MongoDB
- Daily game: Get target country and hints (masked if not game over)
- Stats fetch: Load global player statistics
- State update: Render game with all data
app/hooks/useDailyGame.ts:84-133
Session management
Users are identified by ageo_session cookie containing a UUIDv4:
- Is created on first guess submission
- Persists for 10 years
- Links all user progress across games
- Enables anonymous stat tracking
app/api/progress/route.ts:17-86
External integrations
RestCountries API
Fetched via the/api/country proxy route with Next.js caching:
app/api/country/route.ts:11-13
CIA World Factbook
Fetched server-side during game generation. ThefetchFactbookData function tries 11 regional endpoints:
app/lib/factbook.ts:28-42
Performance considerations
- Parallel fetching: All initial data loads use
Promise.all - Static map data: SVG map bundled at build time
- API caching: RestCountries responses cached indefinitely
- Database indexes: Compound index on
sessionId + date - Connection pooling: Shared MongoDB client across requests
- Suspense boundaries: Prevent layout shifts during loading
Error handling
The app gracefully degrades when external services fail:- MongoDB unavailable: Game generation works in-memory
- RestCountries timeout: Falls back to local
countries.json - Factbook missing: Retries with different countries
- Hint generation error: Returns empty array
app/api/daily/route.ts:40-44