farhan reza

When building location-based web applications, developers usually default to the Haversine formula to calculate the distance and bearing between two GPS coordinates. For most apps, assuming the Earth is a perfect sphere is "good enough."

But what if you are building an application where absolute precision is non-negotiable?

While building Quranbookk's Qibla Finder—a web application that helps Muslims worldwide find the exact direction of the Kaaba in Mecca—I quickly realized that standard spherical math was introducing unacceptable margins of error.

Here is why I ditched Haversine and how I implemented a sub-millimetre precise solution using Next.js and Karney’s Geodesic Algorithm.

The Problem with the Haversine Formula

The Haversine formula calculates the shortest distance over the earth's surface, but it assumes the Earth is a perfect sphere. In reality, the Earth is an oblate spheroid (wider at the equator and flatter at the poles).

When calculating the bearing to Mecca from across the globe (say, from North America or Northern Europe), that "spherical assumption" can result in an error of several degrees. When building a religious tool where users rely on absolute accuracy, being off by a few degrees is a massive failure in user experience and trust.

Enter Karney's Geodesic Algorithm

To solve this, I moved to the WGS84 ellipsoid model using Charles Karney's geodesic algorithm. Instead of drawing a line across a perfect sphere, Karney's algorithm calculates the shortest path between two points on an ellipsoid surface.

The mathematical complexity is significantly higher, involving elliptic integrals, but the result is a bearing and distance calculation accurate to within a fraction of a millimetre.

Implementing it in Next.js

Since I was building a modern web platform, performance was critical. I built the application using Next.js 15 App Router.

To handle the heavy lifting without bloating the client-side bundle, the heavy geodesic calculations can be processed dynamically. For the client side, I utilized the HTML5 Geolocation API combined with the DeviceOrientation event to read the device's magnetometer.

// A simplified conceptual approach
import { Geodesic } from 'geographiclib-geodesic';

export function calculatePreciseBearing(lat, lng, destinationLat, destinationLng) {
  const geod = Geodesic.WGS84;
  const r = geod.Inverse(lat, lng, destinationLat, destinationLng);

  // r.azi1 gives the precise forward azimuth (bearing)
  return r.azi1; 
}

Enter fullscreen mode Exit fullscreen mode

The Result

By combining Karney's algorithm with Next.js edge performance, the resulting compass is incredibly lightweight, runs entirely in the browser (no mobile app download required), and provides mathematical precision that outpaces most native applications.

If you are building location-critical applications, stop defaulting to Haversine. The math is slightly harder, but the precision is worth it. You can see the live implementation on my platform here: Qibla Finder - Quranbookk.