mirror of
https://github.com/tiennm99/vngeoguessr.git
synced 2026-10-11 03:13:56 +00:00
Each Mapillary window query costs ~1-5s and most windows hold no panoramas, so throwing them one at a time made /api/new-game wait for the sum of every miss. Measured in production: median 17.8s, max 90.5s over 18 samples. Throw 8 windows per round instead, race them with Promise.any and abort the losers once one yields panoramas. Wall time becomes one round-trip in the common case. Same 20-window budget, same per-city delta, same 401 short-circuit. After the change, over 10 samples: median 5.6s, max 20.3s.
3.2 KiB
3.2 KiB
Tech Stack
Frontend Framework
- Next.js 15.4.6: React-based full-stack framework with App Router
- React 19.1.0: Latest React version for component architecture
- Tailwind CSS 4: Utility-first CSS framework for styling
Street View & Mapping
- Mapillary API: Panoramic street-level imagery provider (thumb_original_url, is_pano=true filter)
- Dart-throw strategy: pick random points in city bbox, query small fixed-size sub-bboxes (2×delta), re-roll on empty. Keeps query cost under Mapillary cap.
- Concurrent rounds: 8 windows raced per round (20 max total). A Mapillary round-trip costs ~1-5s, so racing keeps wall time at one round-trip instead of the sum of every miss.
- Per-city delta: configurable in CITIES enum (
src/lib/game.js). HN: 0.003° (~333m), others: 0.005° (~556m)
- Leaflet: Interactive mapping library for guess placement
- OpenStreetMap: Map tile provider for base maps
- @photo-sphere-viewer/core: 360° panorama viewer (planned integration)
Geographic Processing
- @turf/turf: Spatial operations library for distance calculations and point processing
- Bbox-based Location: Pre-defined city bounding boxes for location generation
- Server-side Calculations: All geographic processing on backend
Data Storage & Session Management
- Upstash Redis (REST): Session and leaderboard storage via
@upstash/redisSDK (REST client, no sockets) - Credential Flexibility: Accepts
UPSTASH_REDIS_REST_URL+UPSTASH_REDIS_REST_TOKEN(vanilla Upstash) orKV_REST_API_URL+KV_REST_API_TOKEN(Vercel Marketplace aliases) - Multi-tenant Key Prefix: All physical keys carry
KEY_PREFIX(defaultvngeoguessr:) to safely share Upstash DB with other Vercel projects. Prefix applied centrally insrc/lib/upstash.js; callers use logical keys only. - Key Namespaces:
session:{id}(30-min TTL),leaderboard:{scope},distance:{scope}(no expiry) - Sorted Sets: Leaderboard ranking with automatic trimming (top 200)
- UUID v4: Session identifier generation
- 30-minute Session Expiry: Automatic TTL-based cleanup
UI Components & Styling
- shadcn/ui: Complete component library with "new-york" style
- Radix UI: Headless component primitives
- Lucide React: Icon library
- class-variance-authority: Component variant management
- tailwind-merge + clsx: Dynamic class name handling
Form Handling & Validation
- react-hook-form: Form state management
- @hookform/resolvers: Form validation resolvers
- zod: Schema validation
Development & Analytics
- ESLint: Code linting with Next.js configuration
- Turbopack: Development server bundler
- @vercel/analytics: User analytics tracking
- @vercel/speed-insights: Performance monitoring
Key Dependencies
- uuid: unique session identifier generation
- @upstash/redis: REST-based Upstash client; no socket pooling, works in edge compute and serverless
- JavaScript Only: No TypeScript - pure JavaScript implementation
- Individual Parameters: Functions use separate parameters instead of object destructuring
- Note:
redis(node-redis) package not used (replaced by Upstash REST SDK)