mirror of
https://github.com/tiennm99/vngeoguessr.git
synced 2026-10-13 12:15:14 +00:00
711ef863a6148317aa92aa51b200bf3ce4c61c4b
/game?region=TPHCM becomes /game/tphcm, backed by an app/game/[region] dynamic segment. The region is a property of the page, so it belongs in the path: the URL is now shareable and honest, an unknown region is a real 404 instead of silently rendering as "Vietnam", and the page no longer needs useSearchParams or its Suspense boundary. It also makes per-region traffic visible. Vercel's Pages dimension strips query parameters on every plan, so ?region= was invisible; one row per region falls out of correct routing. Slugs are lowercase, and regionSlug/regionFromSlug in lib/regions.js own the conversion. Three call sites build these URLs -- the picker, generateStaticParams, and the legacy redirect -- and a casing mismatch between any two would split one region across two rows, which is the whole point of the move. An unusual casing renders rather than redirecting to the canonical form. A redirect on a prerendered route gets cached as that route's response: on a case-insensitive filesystem the ISR cache folds /game/DNA onto /game/dna, and a cached redirect that has lost its Location header then answers the canonical URL with a 307 to nowhere for the life of the process. Reproduced on Windows against next start; no redirect on the route means no such mechanism anywhere. Legacy ?region= and ?location= redirect from app/game/page.js rather than next.config.mjs, because a config redirect forwards the source query to the destination and would park ?region= on /game/tphcm permanently. The legacy value is encodeURIComponent'd: it reaches a Location header unvalidated, where a raw CRLF makes Node throw a 500 instead of the honest 404, and a raw ../ would be normalised onto another path. A region-less /game now plays the country rather than defaulting to TPHCM, which was never a stated default -- just where the old query chain happened to end. API routes keep their query params. They are fetch calls, not navigations, so a path segment buys nothing there. Also repairs four specs that were already failing on main: three asserted that the landing page shows no username prompt, which the landing-prompt change contradicted, and one expected the build sha and its copy button to be a single element, which splitting them contradicted.
VNGeoGuessr
A GeoGuessr clone focused on Vietnamese locations with accurate boundary detection and anti-cheat security. Play geolocation guessing games across a region tree covering the whole country using real street-level imagery.
🎮 Features
- Region Tree: Whole country, 5 provinces, 61 districts — including Da Lat (Lam Dong) and Duc Hoa (Long An)
- 360° Street View: Mapillary panoramic images with PhotoSphere viewer
- Anti-Cheat Security: Server-side session management prevents cheating
- Distance-Based Scoring: 0-5 point system based on accuracy
- Persistent Leaderboards: Redis-powered top 200 player rankings
- Accurate Boundaries: Nominatim API + Turf.js for precise city detection
📚 Documentation
For detailed information about this project, see the documentation in /docs/:
- Project Overview - Project summary and key characteristics
- Features - Complete feature list and game mechanics
- Tech Stack - Technology stack and dependencies
- Development Guidelines - Development setup and coding standards
- Game Flow - Complete gameplay flow documentation
- Project Structure - Codebase organization and architecture
🚀 Getting Started
Prerequisites
- Node.js 24+
- npm 11+
- Redis server (sessions and leaderboards)
- Postgres database (panorama index; Neon in production)
Development
# Install dependencies
npm install
# Start development server
npm run dev
# Build for production
npm run build
# Start production server
npm start
# Run linting
npm run lint
Open http://localhost:3000 to play the game.
🏗️ Built With
- Frontend: Next.js 16 + React 19 + Tailwind CSS 4
- Street View: Mapillary API + PhotoSphere Viewer
- Maps: Leaflet + OpenStreetMap
- Geographic Data: Nominatim API + Turf.js
- Storage: Neon Postgres (panorama index) + Upstash Redis (leaderboards and game sessions)
- UI Components: shadcn/ui
🎯 How to Play
- Enter your username
- Pick a region from the country/province/district tree
- View the 360° street panorama
- Place your guess on the map
- Earn points based on accuracy (closer = more points)
- Compete for the top 200 leaderboard spots!
📋 Development Notes
- JavaScript Only: No TypeScript files
- Individual Parameters: Functions use separate parameters, not object destructuring
- Server-Side Security: Game coordinates never sent to client
- Session Management: Automatic cleanup after 30 minutes
🤝 Contributing
This project follows specific development guidelines. Please read the Development Guidelines before contributing.
Description
GeoGuessr clone for Vietnamese locations — Mapillary panoramas, Turf.js boundaries, Upstash REST leaderboards
Readme
Apache-2.0
14 MiB
0 Stars
1 Watchers
0 Forks
Languages
JavaScript
98.2%
CSS
1.8%