We're live-coding on Twitch! Join us!
Building a Location Aware Weather Reporting Widget

Building a Location Aware Weather Reporting Widget

In the past, we looked at adding an extra security layer to our applications by using actionable data from the users IP address.

Today, we'll build a demo of a simple widget that we can place on our website(s). This widget detects the users location and gives accurate weather data.

We'll be building our demo in Node.js, but know that you can use any programming language of your choice as we won't be doing anything that can't be done in a programming language.

Before we get started, head over to Ipstack and WeatherStack and sign up to get their API keys. WeatherStack, previously known as Apixu will help us collect meteorological data that we can use to get useful information on a particular location.

Getting Started

First, we want to create a project on our machine. To do that, ensure you have Node.js installed, then navigate to your project folder and run:

npx express-generator weather --ejs

This command creates a barebones exprerss application that we can modify and use. Next, we install the dependencies using npm or yarn. As I prefer yarn, I'll be using it to install and run scripts for the remainder of this article:

yarn install

Then, we can add our remaining dependencies:

yarn add dotenv node-fetch

Next, we want to add a script that runs our server, so in package.json add:

Essential Reading: Learn React from Scratch! (2019 Edition)
"scripts": {
  "start": "nodemon ./bin/www"
},

Then install nodemon as a devDependency.

yarn add --dev nodemon

Now that we have our project setup, we can start building our app.

The User Interface

The first thing we want to do is quickly setup a view to properly display the information. So, in views/index.ejs add this piece of code.

<!DOCTYPE html>
<html>
  <head>
    <title><%= weather.request.query %> — <%= title %></title>
    <link
      href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css"
      rel="stylesheet"
    />
  </head>
  <body class="bg-gray-300 flex items-center content-center h-screen">
    <div class="max-w-lg mx-auto p-4 bg-white shadow-xl rounded-lg text-center">
      <div class="bg-blue-100 shadow rounded-lg p-10">
        <h1 class="text-xl font-bold pt-4">
          <%= weather.location.name %>
        </h1>
        <span><%= weather.location.country %></span>
        <h2 class="text-6xl py-8">
          <%= weather.current.temperature %>&deg;C
        </h2>
        <span><%= weather.current.weather_descriptions[0] %></span>
      </div>
    </div>
  </body>
</html>

From the code above, you can see that we are using Tailwind CSS, so, our app is already styled by default.

Building the Demo Widget

The next thing to do is create a .env file. This is an enviroment file that we can load custom variables from without committing them to code. To get Node.js to respect this file, at the top of app.js add this line:

// register environment variables
require("dotenv").config();

Now, on process.env we have access to variables we define in our .env file. So, remember those API keys you got from Ipstack and WeatherStack? You can now place them in the .env file like this:

WEATHER_KEY=5cd59800593b16d557089d0a17cc75bc
LOCATION_KEY=08c58c184ea64dd85605324883d888f2

Make sure to replace the API keys with the proper API keys. Then, in app.js, let's replace the default router with a route to the domain root, like this:

app.get("/", async (req, res, next) => {
  // ...
});

Then, in the router above, we get the users IP address which we'll then feed to the Ipstack API using node-fetch, that way, we can know our users current location.

app.get("/", async (req, res, next) => {
  const locKey = process.env.LOCATION_KEY;
  const locResponse = await fetch(
    `http://api.ipstack.com/${req.ip}?access_key=${locKey}`
  );
  const location = await locResponse.json();
});

With the response from Ipstack, we pass the users city to Weatherstack, which will then return a weather report for the current city.

app.get("/", async (req, res, next) => {
  // ...

  // weather request
  const weatherKey = process.env.WEATHER_KEY;
  const response = await fetch(
    `http://api.weatherstack.com/current?access_key=${weatherKey}&query=${location.city}`
  );
  const weather = await response.json();
});

We now have the weather report for the current user location, we can then feed this data to our views/index.ejs file by doing:

app.get("/", async (req, res, next) => {
  // ....
  res.render("index", { title: "Weather app", weather });
});

If you now run yarn start or npm start and headover to localhost:3000, you should see something like this.

Quick Gotcha

If you plan on deploying this app, make sure to let express know to allow proxy IP, that way if you're using a web server like Nginx, you get the users actual IP address instead of 127.0.0.1. To do that, just add this line after your express declaration:

app.set("trust proxy", true);

Like this article? Follow @KayandraJT on Twitter