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.
Saves the user’s guesses for a specific date, calculates geographic relationships, and manages session state. This endpoint handles both creating new sessions and updating existing progress.
Endpoint
Request body
The game date in YYYY-MM-DD format
Array of country guesses. Each guess should include basic country data that will be enriched with calculated fields. Show Guess object properties
ISO 3166-1 alpha-3 code (used for relationship calculation)
Coordinates as [latitude, longitude]
Response
Indicates if the progress was saved successfully
The user’s session ID (UUID v4 format)
Whether the user has won the game (guessed correctly)
The enriched array of guesses with calculated fields Show Enriched guess properties
Coordinates as [latitude, longitude]
Distance in kilometers from the guess to the target country (rounded)
Bearing angle in degrees from the guess to the target country (0-360)
Relationship to target country. One of:
"guess" - Exact match (correct answer)
"neighbor" - Shares a border with target
"subregion" - Same subregion as target
"region" - Same region as target
"none" - No special relationship
Geographic calculations
The endpoint enriches each guess with calculated geographic data:
Distance calculation uses the Haversine formula:
const distance = Math . round (
getDistanceFromLatLonInKm ( lat , lng , targetLat , targetLng )
);
From app/api/progress/route.ts:39
Bearing calculation computes the angle from guess to target:
const bearing = Math . round (
getBearingAngle ( lat , lng , targetLat , targetLng )
);
From app/api/progress/route.ts:40
Connection logic determines geographic relationships:
if ( dailyGame . targetCountry . alpha3Code === g . alpha3Code ) {
connection = "guess" ; // Exact match
} else if ( dailyGame . targetCountry . borders ?. includes ( g . alpha3Code )) {
connection = "neighbor" ; // Shares border
} else if ( dailyGame . targetCountry . subregion === g . subregion ) {
connection = "subregion" ; // Same subregion
} else if ( dailyGame . targetCountry . region === g . region ) {
connection = "region" ; // Same region
}
From app/api/progress/route.ts:44-49
Session management
The endpoint automatically creates and manages user sessions:
Checks for existing geo_session cookie
Generates new UUID v4 session ID if not present
Sets HTTP-only cookie with 10-year expiration
Associates all progress with the session ID
if ( ! sessionId ) {
sessionId = uuidv4 ();
}
From app/api/progress/route.ts:20-22
Win detection
The game is marked as won when the newest guess matches the target country name (case-insensitive):
const newestGuess = guesses [ 0 ];
if ( newestGuess . name ?. toLowerCase () === dailyGame . targetCountry . name . toLowerCase ()) {
isWon = true ;
}
From app/api/progress/route.ts:65-68
Example request
curl -X POST https://yourdomain.com/api/progress \
-H "Content-Type: application/json" \
-d '{
"date": "2026-03-02",
"guesses": [
{
"name": "Germany",
"alpha2Code": "DE",
"alpha3Code": "DEU",
"flag": "https://flagcdn.com/de.svg",
"latlng": [51, 9],
"region": "Europe",
"subregion": "Western Europe"
}
]
}'
Example response
{
"success" : true ,
"sessionId" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890" ,
"won" : false ,
"guesses" : [
{
"name" : "Germany" ,
"alpha2Code" : "DE" ,
"flag" : "https://flagcdn.com/de.svg" ,
"latlng" : [ 51 , 9 ],
"distance" : 516 ,
"bearing" : 78 ,
"connection" : "neighbor"
}
]
}
The guesses array in the response is enriched with distance, bearing, and connection fields calculated on the server.
Error responses
Invalid payload:
{
"error" : "Invalid payload"
}
Status: 400
This occurs when:
date is missing
guesses is not an array
Failed to save:
{
"error" : "Failed to save"
}
Status: 500
This occurs when the database operation fails.
Code example
// Save progress after a guess
const saveProgress = async ( date : string , guesses : Country []) => {
const response = await fetch ( '/api/progress' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({ date , guesses })
});
const result = await response . json ();
if ( result . won ) {
console . log ( 'Congratulations! You won!' );
}
return result . guesses ; // Now includes distance, bearing, connection
};
GET /api/progress
Retrieves the user’s progress for a specific date, including guess history and personal statistics.
Endpoint
Query parameters
The game date in YYYY-MM-DD format. Validation : Must match the pattern ^\d{4}-\d{2}-\d{2}$
Authentication
Requires geo_session cookie. If no session exists, returns empty progress.
Response
Array of the user’s guesses for this date (enriched with distance/bearing/connection)
Whether the user won this game
User’s overall statistics across all games Total number of games played by this user
Total number of games won
Win percentage (0-100), rounded to nearest integer
Example request
curl https://yourdomain.com/api/progress?date=2026-03-02 \
-H "Cookie: geo_session=a1b2c3d4-e5f6-7890-abcd-ef1234567890"
Example response
With existing progress:
{
"guesses" : [
{
"name" : "Germany" ,
"alpha2Code" : "DE" ,
"flag" : "https://flagcdn.com/de.svg" ,
"latlng" : [ 51 , 9 ],
"distance" : 516 ,
"bearing" : 78 ,
"connection" : "neighbor"
}
],
"won" : false ,
"stats" : {
"gamesPlayed" : 5 ,
"wins" : 3 ,
"winRate" : 60
}
}
No session or no progress:
{
"guesses" : [],
"winStreak" : 0 ,
"gamesPlayed" : 0
}
Error responses
Invalid date:
{
"error" : "Valid date required"
}
Status: 400
Server error:
{
"error" : "Failed to load"
}
Status: 500
Code example
// Load user progress for today
const loadProgress = async ( date : string ) => {
const response = await fetch ( `/api/progress?date= ${ date } ` );
const progress = await response . json ();
console . log ( `Played ${ progress . stats . gamesPlayed } games` );
console . log ( `Win rate: ${ progress . stats . winRate } %` );
return progress ;
};