Building a Weather App with Node, Express, Webpack & React Part 2: Weather APIs

Welcome back! If you missed the intro or part 1 of this series, feel free to head back for an overview of what we're building and how to get started.

In Part 1 we managed to get everything set up, but haven't actually built any features related to the weather yet. We'll change this in part 2 with some integrations with third party services.

Dark Sky Integration for Weather

For the weather demo, we could get away with dummy data. However, since the nice folks over at Dark Sky (formerly Forecast.io) provide a free developer account, we can go a step further and provide real weather updates!

To get started, head over to Dark Sky's developer section and sign up for a new account. Once you get signed in, take a note of your API key - you'll need this later.

Dark Sky API Portal

Once you've got the key, we can go ahead and create a new endpoint on our server to provide our React app with weather information.

It might have been easier to have React call Dark Sky directly, but calling third party services in Javascript from the browser is generally tricky for security reasons (CORS, etc) - this 'proxy' method gets around that, and means we can map or add to the Dark Sky data as it transitions through our server as our app requires.

To hook up our new API, create a new route file called '/routes/weather.js' with the following (note - you'll need your Dark Sky API Key here!):

var express = require("express");
var fetch = require("node-fetch");
var router = express.Router();

router.get("/", function(req, res, next) {
  var darkskyApiKey = "your-api-key";

  fetch(
    `https://api.darksky.net/forecast/${darkskyApiKey}/${req.query.latitude},${
      req.query.longitude
    }/?exclude=minutely,hourly&units=uk2`
  )
    .then(function(fetchRes) {
      return fetchRes.json();
    })
    .then(function(json) {
      res.setHeader("Content-Type", "application/json");
      res.send(JSON.stringify(json));
    })
    .catch(function(error) {
      res.send(JSON.stringify(error));
    });
});

module.exports = router;

Then to wire our route up, add the following in 'app.js' (around the same locations in the file as the definitions for the index route):

...
var weatherRouter = require("./routes/weather");
...
app.use("/api/weather", weatherRouter);
...

That should be all we need, to try it out either go to http://localhost:3000/api/weather/?latitude=55.806814&longitude=-4.336192 in your browser or use Postman to check what we get back.

Postman Weather Query

Address Lookup

We have one 'bonus' API to integrate with - Address Lookup. From the web service call above, you'll see Dark Sky expects a Latitude and Longitude to be supplied in order to get weather for a specific location.

While we could get this from the user's browser for their current location, with a little bit more work we can expand this to get weather for anywhere in the world for free with Open Streetmap's geocoding service.

To make the job of geocoding a little easier, we're going to use a handy NPM package called node-geocoder:

$ npm install --save node-geocoder

Once you've downloaded node-geocoder, we can integrate it with a new route. Create a new file in '/routes/geocoding.js' like we did for the weather.js route:

var express = require("express");
var router = express.Router();
var NodeGeocoder = require("node-geocoder");

var options = {
  provider: "openstreetmap",

  // Optional depending on the providers
  httpAdapter: "https", // Default
  //apiKey: process.env.GOOGLE_MAPS_API_KEY, // for Mapquest, OpenCage, Google Premier
  formatter: null // 'gpx', 'string', ...
};

router.get("/", function(req, res, next) {
  var geocoder = NodeGeocoder(options);

  res.setHeader("Content-Type", "application/json");

  // Or using Promise
  var query = req.query.query;
  console.log(query);

  geocoder
    .geocode(query)
    .then(function(geores) {
      res.send(JSON.stringify(geores[0]));
    })
    .catch(function(geoerr) {
      res.send(JSON.stringify(geoerr));
    });
});

module.exports = router;

Then to wire our route up, add the following in 'app.js' (around the same locations in the file as the definitions for the index route):

...
var geocoding = require("./routes/geocoding");
...
app.use("/api/geocode", geocoding);
...

Ok, let's give our new service a try. Open up a browser or boot up postman and request http://localhost:3000/api/geocode/?query=Glasgow and check what you get back:

Postman Address Query

If all has gone well, we now have a service our (eventual) React app can use to convert a place like 'Glasgow' into Lat/Lng coordinates Dark Sky understands. Great!

Wrapping Up

We now have access to all of the data our app will need, we just need to build out the React part so our user doesn't need to try and make sense of raw JSON.

Check back in Part 3 where we'll start our React app build and start to bring everything together. Until then, check the updated repo with a working version of the story so far in the Part 2 folder on github.

Show Comments