Inspiration

We've always been fascinated by how much of our planet is covered by water: over 70%, yet most geography games focus almost entirely on land. Games like GeoGuessr inspired us to ask: what if you stripped away the cities, the road signs, the landmarks, and just left the ocean? Could you tell the Atlantic from the Indian Ocean? Could you identify a coastline from a single Street View panorama? We built OceanGuesser to find out.


What it does

OceanGuesser is a geography guessing game focused entirely on the world's oceans and coastlines. Players are dropped into one of two game modes:

  • Easy mode — An interactive Google Street View panorama of a real coastal location. Look around 360°, study the shoreline and the water then drop your pin on the world map.
  • Hard mode — A satellite image of the open ocean. No coastlines, no landmarks — just water, waves, and your instincts.

Each game consists of 5 rounds with a 60 second timer per round. After each guess, the map reveals the correct location alongside your guess, with a line drawn between them showing exactly how far off you were. Scores are calculated using the haversine formula, the closer your guess, the higher your score, up to 5000 points per round and 25000 total. After finishing, players can submit their name to a live leaderboard separated by difficulty.


How we built it

We built OceanGuesser as a full-stack web application using the following stack:

  • Next.js 14 (App Router) with TypeScript for the frontend and API layer
  • Supabase (Postgres) for storing game locations and leaderboard scores
  • Google Maps JavaScript API for interactive Street View panoramas in easy mode
  • Mapbox GL JS for the satellite guess map and pin placement
  • Local satellite imagery for hard mode ocean images
  • Vercel for deployment

The game loop was built around a clean state machine in React: tracking rounds, guesses, scores, and replacements for invalid Street View locations. We wrote a haversine distance function from scratch to calculate great-circle distances between the player's guess and the correct location, feeding into an exponential score decay curve that rewards precision. Location data is pre-seeded into Supabase and shuffled on the client each session to ensure variety.


Challenges we ran into

Street View coverage is unpredictable. A coordinate that looks coastal on a map often has no Street View imagery within hundreds of meters. We built a browser-based validation script using the Google Street View Service API to batch-test every coordinate in our database, identifying which ones returned ZERO_RESULTS before players ever encountered them. Coordinates that remapped to nearby panoramas required careful handling — we used the panorama's status_changed event rather than arbitrary timeouts to ensure reliable loading regardless of how far the coordinate shifted.

The public schema in Supabase didn't exist by default. Early in development our entire database schema failed silently because the public schema had been dropped from the project. Queries returned null with no obvious error message, and debugging this cost us significant time before we traced it back to the missing schema.

Row Level Security locked us out. After creating our tables, all client-side queries returned permission denied errors. We had to correctly configure RLS policies to grant public read access to locations and public read/insert access to scores before anything worked.


Accomplishments that we're proud of

  • A seamless automatic location replacement system: if a Street View location fails to load mid-game, the game silently swaps in a fresh location from a pre-shuffled pool without the player ever noticing
  • A scoring system that feels fair and satisfying, the haversine curve rewards precision without punishing players too harshly for being in the right ocean but the wrong spot
  • A clean, polished UI that feels purpose-built for the game rather than generic
  • Successfully deploying a full-stack application with a live database and third party APIs end-to-end within a hackathon timeline

What we learned

  • How to work with the Google Maps JavaScript API beyond basic map rendering, Street View services, panorama status events, and coverage metadata
  • How Supabase Row Level Security works and how to configure public access policies correctly for an unauthenticated app
  • How the haversine formula translates real-world geographic distance into a fair scoring curve
  • That curating a good location library is just as important as the code — bad coordinates ruin the experience no matter how polished the game is

What's next for Ocean-Guesser

  • Daily challenge mode — everyone gets the same 5 locations each day with a shareable result card
  • Streak tracking and personal bests stored per device
  • Multiplayer — race a friend through the same 5 locations in real time
  • Expanded location library with hundreds more validated coastal coordinates across all seven continents
Share this project:

Updates