mirror of
https://github.com/tiennm99/vngeoguessr.git
synced 2026-10-16 02:15:59 +00:00
478e62a085406141c74eccd13ee4aafb8964b009
Two threads that could not be separated: they share globals.css, page.js and GameClient.js, and their edits interleave inside those files. THEME SWITCHING Light, dark and system, chosen from a control in both headers and remembered in localStorage. An inline script in the document head resolves the choice before first paint, so a dark-theme visitor never sees a white flash. The dark palette moves out of a prefers-color-scheme media query and onto a class, because a media query cannot be overridden by an explicit choice. That also repairs every dark: utility in the app: the variant keys off a .dark class that nothing had ever set, so rules like dark:text-green-400 had never once applied. The palette is declared as :root.dark rather than .dark. A bare class ties with :root on specificity and wins only by sitting later in the file, which is fragile: a brand :root block further down had been silently reverting --surface and the brand tokens to their light values, leaving the page background white while the cards went dark. BUTTONS AND ELEVATION The button primitive was still the shadcn scaffold: a grayscale default variant and a size scale starting at 36px, below the touch target this app needs. So every real call site hand-patched the same brand fill and min-height, ten of them, and drifted apart on padding, weight and shadow. That drift is what read as unpolished. The default variant is now the brand fill, sizes start at 44px, and there is a pressed state, a hover lift, and a loading prop. The overrides are gone. A shared elevation scale sits behind the Tailwind shadow utilities, so cards and dialogs agree with buttons about how raised things are; the dark values carry more opacity and a faint inset highlight, since shadows read as nothing on a dark ground. The focus ring was measured at 2.59:1 against the page, under the 3:1 floor for a non-text indicator, and no alpha value clears it at any lightness. It is now opaque at oklch(0.55), measuring 4.54:1. HIERARCHY Submit outranks Skip by size and fill instead of colour alone. Next Round outweighs Menu. The donate button gives up the only brand fill on the landing page so choosing a city can have it. City rows become cards with real elevation and an explicit Play affordance, having previously been near-invisible against the page. The guess map is framed in a padded card rather than restyled, so a bright map over dark chrome reads as deliberate. The score counts up on reveal.
VNGeoGuessr
A GeoGuessr clone focused on Vietnamese locations with accurate boundary detection and anti-cheat security. Play geolocation guessing games across 5 Vietnamese locations using real street-level imagery.
🎮 Features
- 5 Vietnamese Locations: Ha Noi, Da Nang, Ho Chi Minh, Da Lat, 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 18+
- npm 11+
- Redis server (for leaderboards)
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 15 + React 19 + Tailwind CSS 4
- Street View: Mapillary API + PhotoSphere Viewer
- Maps: Leaflet + OpenStreetMap
- Geographic Data: Nominatim API + Turf.js
- Storage: Redis (leaderboards) + In-memory sessions
- UI Components: shadcn/ui
🎯 How to Play
- Enter your username
- Select a Vietnamese location
- 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%