GeoFire is an open-source JavaScript library that allows you to store and query a set of items based on their geographic location. GeoFire uses Firebase for data storage, allowing query results to be updated in realtime as they change. GeoFire does more than just measure the distance between locations; it selectively loads only the data near certain locations, keeping your applications light and responsive, even with extremely large datasets.

Live Demo

To showcase the power and simplicity of GeoFire, we built a demo which uses it alongside our Firebase Transit Open Data Set. The demo allows you to drag a circle around San Francisco and see all MUNI (the public transit system for the city) vehicles which are currently within it. Since GeoFire is built on top of Firebase, the demo updates in realtime as you drag around the circle and as new data comes in.

The GeoFire data for this demo is stored in a public Firebase which is freely available for use by any developer. We also provide GeoFire data for our latest open data set, launching today, Parking.

In addition to the MUNI demo, we created several other examples which show you how to perform common tasks in GeoFire. The code for all examples, including the MUNI demo, is available in the GeoFire GitHub repository.

GeoFire 2.0

A growing number of apps and websites - from car-sharing services to food recommendation apps to local event aggregators - alert users to places or things near them. While server-based solutions for geolocation queries are nothing new, there was nothing which allowed you to do them efficiently in Firebase. So we introduced GeoFire last September to provide you with an easy way to do client-side, on-the-fly filtering of geolocation data.

GeoFire 2.0 is a complete rewrite of that GeoFire library. We simplified the API and aligned it closer to the Firebase JavaScript client API you are already familiar with. You can now do even more with smaller, cleaner code. This version of GeoFire is now "production ready" - we have improved performance, added several common feature requests, and are ensuring its quality with a comprehensive test suite.

Quick Walkthrough

The best way to see what GeoFire can do is to jump right into the code. GeoFire has dependencies on Firebase (for realtime data storage) and RSVP (for an implementation of JavaScript promises), so we need to include them in our HTML file along with the GeoFire library:

<head>
  <!-- RSVP -->
  <script src="path/to/rsvp.min.js"></script>

  <!-- Firebase -->
  <script src="https://cdn.firebase.com/js/client/1.0.17/firebase.js"></script>

  <!-- GeoFire -->
  <script src="https://cdn.firebase.com/libs/geofire/2.0.0/geofire.min.js"></script>
</head>  

The necessary files are also available via Bower and npm. See the GeoFire documentation for full download instructions.

GeoFire stores its data at whatever Firebase location you choose to pass it:

var firebaseRef = new Firebase("https://your-app.firebaseio.com/geofire/");
var geoFire = new GeoFire(firebaseRef);  

Once you have created a GeoFire instance, you can add locations to it using set(). It takes as input a unique, arbitrary key to represent the location as well as the location's latitude-longitude pair:

geoFire.set("some_key", [37.785326, -122.405696]).then(function() {
  console.log("Provided key has been added to GeoFire");
}, function(error) {
  console.log("Error: " + error);
});  

To retrieve the location of a key at any time, pass the key to get():

geoFire.get("some_key").then(function(location) {
  if (location === null) {
    console.log("Provided key is not in GeoFire");
  }
  else {
    console.log("Provided key has a location of " + location);
  }
}, function(error) {
  console.log("Error: " + error);
});  

GeoFire's real utility is shown by creating a GeoQuery. Say you are making an app for cyclists which shows the bicycle shops within a mile (1.609 kilometers) of a user's current location. The first thing you need to do is add the bike shops you care about to GeoFire. Then, create a query centered at the user's current location (let's say they are at [37.4, -122.6]):

var geoQuery = geoFire.query({
  center: [37.4, -122.6],
  radius: 1.609 //kilometers
});  

A query on its own is not very useful. However, GeoFire allows you to add callback functions which are fired when important query events happen. Since you want to display every bike shop which matches the query criteria, listen for the key_entered event. Every time a key (that is, a bike shop) enters the query, the callback you defined will get called with data about that location:

geoQuery.on("key_entered", function(key, location, distance) {
  console.log("Bicycle shop " + key + " found at " + location + " (" + distance + " km away)");
});  

It is important to realize that the key_entered event works like typical Firebase events. That is, it will be fired for every key in GeoFire which matches the query criteria, both keys which are already in GeoFire and those which are added at any point in the future. Thanks to Firebase, you receive these events in realtime.

GeoFire is smart about how it looks for keys within the query. It does not need to load all of the GeoFire data into memory. If your user is looking for bicycle shops in San Francisco, GeoFire will not load data for locations in New York only to realize that they are on the opposite side of the country. It only checks on locations which are actually nearby. This keeps your app light and responsive, regardless of how big your data set is.

If your user is biking around while looking for a shop to visit, it is possible that shops which were within a mile of them are now further away. To deal with this, GeoFire will fire the key_exited event for each key which leaves the query:

geoQuery.on("key_exited", function(key, location, distance) {
  console.log("Bicycle shop " + key + " left query to " + location + " (" + distance + " km away)");
});  

That is really all you need to make your app work. GeoFire offers other features not covered here, including:

  • Removing locations
  • Updating query criteria
  • Canceling queries
  • Dealing with keys which move around within a query
  • Alerting you when initial data is processed

To learn more about these features, read the full documentation and view the code samples.

Go Forth And Build!

GeoFire 2.0 is available today and is ready to be integrated into your website or app. If you have any questions or feedback, post them in our Firebase Google Group or reach out to us on Twitter. We cannot wait to see what you build with GeoFire!