Files
vngeoguessr/docs/tech-stack.md
T
tiennm99 1c62e3e1dd perf(mapillary): race dart-throw windows concurrently
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.
2026-08-29 14:27:42 +07:00

54 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/redis` SDK (REST client, no sockets)
- **Credential Flexibility**: Accepts `UPSTASH_REDIS_REST_URL`+`UPSTASH_REDIS_REST_TOKEN` (vanilla Upstash) or `KV_REST_API_URL`+`KV_REST_API_TOKEN` (Vercel Marketplace aliases)
- **Multi-tenant Key Prefix**: All physical keys carry `KEY_PREFIX` (default `vngeoguessr:`) to safely share Upstash DB with other Vercel projects. Prefix applied centrally in `src/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)