Node.js API Tutorials

How To Build a Weather App in JavaScript (Node.js) Using the OpenWeatherMap API

The first official weather forecast ever appeared on the first of August 1861. The legendary vice-admiral Robert Fitzroy, a royal-navy officer and pioneer in meteorology, was collecting data for his Meteorological Office from 15 land stations across England. Nowadays, there are over 40000 stations across our planet, accessible via free, affordable, advanced, and accurate technologies. So what are we waiting for?

What is a Weather API?

Let’s start from the end.

An API (application programming interface) is a form of pre-defined interaction between the client and the service.

In other words, the client doesn’t need to bother about the inside structure of the responding side and vice versa.

The main advantage of using weather APIs includes full independence from:

Weather APIs allow us to:

  • cooperate with powerful and enormous data storage,
  • get historical weather records,
  • access forecasts for any point on Earth.

Applications are only limited by our imagination and creativity. You can embed it inside your app as a feature (all data is ready, there is no need to process it).

You can make a bot for some messenger that will return a forecast.

You can even create an aggregator of different weather APIs.

There are many popular weather APIs out there to choose from. Let’s highlight a few of them:

OpenWeatherMap

The OWM API is free on a basic plan and high-precision API. Their weather database is huge. You can use diverse metrics (e.g., temperature, humidity, air pollution, wind speed and degree, clouds percentage). You can also get a simple forecast, daily forecast, historical weather data, or use a city search.

DarkSky

This weather API is gaining popularity. It is a freemium-based API with powerful endpoints:

  • minute-by-minute forecast within an hour,
  • current weather with customized response data,
  • and a weather time machine.

You can analyze past forecasts, real weather situations, or explore the future predictions.

Related: How to use the Dark Sky API in JavaScript (Node.js)

As mentioned above, the list is huge, so you can go with something else.

But in this article, we’ll show you how to use the OpenWeatherMap API to build an application.

Node.js

For this project, we’ll be using node.js – one of the most popular run-time environments for JavaScript.

Node.js helps create fast and advanced web applications. It has many additional libraries/modules for any purpose.

In case of any problems, you can discuss them within a responsive node user community.

For installing node.js or getting any information, you can check out this page. Once you have installed the node and npm to your PC, you can easily check it by typing the following commands in the terminal:

$ node -v
v8.10.0
$ npm -v
3.5.2

The versions may vary depending on your installation.

Now, let’s create our project and install all the required modules. First, create a folder where you want to keep all the work. Then move it in the terminal (you can use the cd command) and type this line:

$ npm init

After that, you should fill in some crucial data (inside of I/O in the terminal) for creating an independent node.js project.

Finally, there will be a package.json file with all the project info (including start file – by default, it’s index.js).

All the modules that we will install in this tutorial are local for this project, so your “main” node won’t be affected by this.

Now let’s install all the packages, which will help create the weather app.

We will need 3 additional modules:

  1. ejs
  2. express
  3. unirest.

If this is still all confusing to you, don’t worry. We’ll explain in more detail below.

An example of the syntax for installing any package looks like this:: npm install. So, for our modules, it should look like this:

$ npm install ejs

EJS – embedded javascript – template language for implementing js objects inside of HTML documents. It’s useful when you need to receive some data from your scripts and dynamically show it on your web page.

$ npm install express

Express is a lightweight framework for node.js to work with fully provided web instruments. It helps run a server, handle requests from the client, and connect the correct HTML/ejs template with a response. You can read more details about ejs + express solutions here.

$ npm install unirest

Unirest is a simple and powerful solution that requests a library. We will use it for making requests to OpenWeatherMap API and handle the response. For more information, visit this doc.

Now the project is ready and all the modules have been installed, so we can make the next step.

How to use the OpenWeatherMap API

1. Get a RapidAPI account

The first thing you need for this project (and for any project using API), is registering for a free user account on RapidAPI.

RapidAPI maintains thousands of different APIs. It allows anybody to use them via a straightforward interface. RapidAPI also supports creating new APIs. So even if you aren’t an experienced API developer, this site should be in your bookmarks.

2. Get an API key/access to OpenWeatherMap

Now add the OpenWeatherMap API to your list.

It’s free, so you can immediately start testing it once you have a RapidAPI account.

Let’s analyze the main API window:

The OpenWeatherMap Console some key stats about the API including rating, the popularity score, latency, etc.

There are also 3 tabs:

  • Endpoints – all request URLs that we can interact with.
  • API Details – short docs for the API with links on authors.
  • Discussions – topics on RapidAPI from the users about some issues and tasks.

Navigate to Endpoints, or click here. The structure looks pretty understandable:

The left section of the screen consists of links with all the unique endpoints in the API. We will come back to this soon to explain all the features of the OpenWeatherMap.

The middle column gives detailed info about the selected endpoint (i.e., all required headers, params, optional params, etc.).

The right column represents a code snippet on the chosen language (node.js in our case, but there are many more options) and a sample response.

Here you can test all the requests by setting your query and clicking the “Test endpoint” button.

We are almost ready to develop the results.

To get access to OpenWeatherMap via RapidAPI, you’ll need to get the following:

  • 2 headers: x-rapidapi-key and x-rapidapi-host
  • 1 parameter: appid that you should get on site of the OpenWeatherMap. You’ll receive an API key when subscribing to one of their plans.

3. Test the OpenWeatherMap endpoints

This weather API provides almost everything regarding meteorological data, but its most significant advantage is retrieving the weather data using parameters.

For this purpose, let’s use the GET Search Weather Data request.

This endpoint returns a search result based on a location.

It has one required parameter “q”, which is a query for a city. All other params are optional for modifying the search results. Let’s try to test this query (you can use the built-in RapidAPI tester for it).
Add both headers, appid parameter and “q=Rome”. Let’s try finding the capital of Italy. The response should be as follows:

{
  "message": "accurate",
  "cod": "200",
  "count": 5,
  "list": [
    . . . . . . .  
  ]
}

The provided result is returned in JSON (javascript object notation).

You may be wondering why we have 5 different results for Rome. The answer is simple: there is more than one city named “Rome” on our planet.

If you look at the top of the response, you will see a “count” key with the value “5”, which limits the number of responses to 5.

But what if we would prefer to get 40 cities? Well, for this purpose, the endpoint has an optional parameter cnt, which informs the server about the maximum number of cities that we are looking for.

Try to increase cnt, and you will see how many cities named “Rome” are located in the USA.

Also, if you don’t want to process the cities from any unnecessary countries, you can modify your q param with a comma and short name of the correct country (“Rome, IT” instead of “Rome” in our case).
Now let’s try to understand the key data from the response for one city.

{
         "id": 6539761,
         "name": "Rome",
         "coord": {
             "lat": 41.8933,
             "lon": 12.4829
         },
         "main": {
             "temp": 302.9,
             "pressure": 1013,
             "humidity": 33,
             "temp_min": 299.82,
             "temp_max": 305.37
         },
         "dt": 1565881765,
         "wind": {
             "speed": 6.7,
             "deg": 270
         },
         "sys": {
             "country": "IT"
         },
         "rain": null,
         "snow": null,
         "clouds": {
             "all": 0
         },
         "weather": [
             {
                 "id": 800,
                 "main": "Clear",
                 "description": "clear sky",
                 "icon": "01d"
             }
         ]
     }

This is a standard response. Let’s go over each element:

  • id and name nodes represent the name and geocode of a returned city;
  • coord contains two geographical coordinates of the city, longitude (lon) and latitude (lat);
  • main – place for the main weather info. Here we could take temperature (temp), it’s minimum (temp_min) and maximum (temp_max), pressure, and humidity. Please, pay attention to the sample temp value in the previous response (Kelvins). To convert it to Fahrenheit or Celsius, use a units parameter (imperial or metric value respectively);
  • dt – millisecond DateTime value of the weather results;
  • wind – node for wind metrics, i.e. speed and degree (deg);
  • sys – system data about the city. In this specific example, it is a country;
  • rain, snow, and clouds inform about the appropriate type of precipitation;
  • weather – textual information about the weather state with id, its name (main) and a longer representation (description).

With the help of other params, we can also search for a location by longitude and latitude (lon and lat), convert the response to other types (mode = json, html, xml), and more.

OpenWeatherMap also has 3 more endpoints, but they are quite similar to the search endpoint:

  • GET Current Weather Data –  inform about the appropriate type of precipitation; place on Earth.
  • GET Daily Forecast Weather Data – predicts daily forecasts for the next 2 weeks.
  • GET Forecast Weather Data – returns a forecast for every 3 hours in the next 5 days.

How to Build a Weather App

Getting a specific place

Rome is a big city and sometimes you may want to find a more accurate place. Let’s say we want to get the weather forecast for a famous place in Rome. For example, the Colosseum. According to Wiki, this legendary building has the following geo-coordinates:

41°53′25″N 12°29′33″E / 41.8902°N 12.4924°E / 41.8902; 12.4924

Create a colos.js file in our project folder and type next lines:

var unirest = require('unirest');
var express = require('express');
var app = express();

These lines import unirest and express modules and also create the app variable.

Now it’s time to handle the client requests (don’t confuse this with requests to API):

app.get('/', function(req, res){
unirest.get("https://community-open-weather-map.p.rapidapi.com/weather")
  .header("X-RapidAPI-Key", <YOUR_RAPIDAPI_KEY>)
  .header("x-rapidapi-host", "community-open-weather-map.p.rapidapi.com")
  .query({
     'appid': <YOUR_APP_ID>,
     'lon': '12.4924',
     'lat': '41.8902',
     'units': 'metric',
     'mode': 'html'
  })
  .end(function (result) {
     res.writeHead(200, {"Content-Type": "text/html"});
     res.write(result.body);
     console.log('Colosseum, I am coming!');
  });
})
app.listen(8081, function(){
  console.log('Server running at https://127.0.0.1:8081/');
})

The first method handles the get request (i.e., visiting the page with the named URL) for the server.

Here we use the unirest object for preparing and sending a get request to the API. It has a complete endpoint address, headers for RapidAPI and all the required params: appid, longitude and latitude, units and mode for returning response already in HTML.

The next step is to create a callback function unirest.get().end(), that creates a dynamic HTML response via writeHead() and write() methods.

Finally, it logs to the console with the phrase “Colosseum, I am coming!”.

To run our server, we used the app.listen() method (note that 8081 – port number for the localhost URL).

Now let’s try to run our code in the terminal:

$ node colos.js

The console response should be as follows:

Server running at https://127.0.0.1:8081/

Let’s try visiting the link:

There is no better time in a year to visit Colosseum than now. Be sure to check the console, as it should have changed:

Server running at https://127.0.0.1:8081/
Colosseum, I am coming!

Making the HTML response

Let’s be honest: it’s cheating when you use HTML mode directly from the API. Also, you will be unable to change anything in the representation result. So here we will try to create our own HTML template and feed it by data from OpenWeatherMap.

First, create a new file forecast.js.

Let’s pay tribute to Mr. Fitzroy and get a forecast for his native birthplace – Ampton.

Paste the next lines in the file:

var unirest = require('unirest');
var express = require('express');
var app = express();

app.set("view engine", "ejs");
app.use(express.static('public'));
app.get('/', function(req, res){
unirest.get("https://community-open-weather-map.p.rapidapi.com/forecast")
  .header("X-RapidAPI-Key", <YOUR_RAPIDAPI_KEY>)
  .header("x-rapidapi-host", "community-open-weather-map.p.rapidapi.com")
  .query({
      'appid': <YOUR_APP_ID>,
      'q': 'Ampton',
      'units': 'metric'
  })
  .end(function (result) {
      res.render('index', {data:result.body});
  });
})
app.listen(8081, function(){
  console.log('Server running at https://127.0.0.1:8081/');
})

The code is similar to the previous example, except for a few things.

We will call the forecast endpoint, indicate ‘Ampton’ as query, and send results into the res.render() method (instead of direct HTML writing).

Ejs can help make the representation more attractive. As you may see, we get a response in the JSON and send it via render(). That tries to take pointed ejs-template and connect with the data.

By default, render() looks for the templates in the path: “./views/”. So now you need to create within the project new folder views and a file index.ejs inside of it.

Here we will create the HTML code for the nice response representation. As the response will have 40 nodes (forecasts for 5 days, every 3 hours) with the same structure, we will use the <table> tag and feed it through a loop.

Type the next lines in index.ejs:

<!DOCTYPE html>
<html>
  <head>
     <meta charset="utf-8">
     <title>OpenWeatherMap</title>
  </head>
  <body>
     <% if(data !== null){ %>
         <h4>A forecast for <%=data.city.name%>, <%=data.city.country%>:</h4>
         <div>
             <table>
                 <thead>
                     <tr>
                         <th>Datetime</th>
                         <th>Temperature</th>
                         <th>Humidity</th>
                         <th>Pressure</th>
                         <th>Clouds</th>
                         <th>Wind speed</th>
                         <th>Wind degree</th>
                         <th>Weather</th>
                         <th>Description</th>
                     </tr>
                 </thead>
                 <tbody>
                     <% for (var i = 0; i < data.cnt; i++) {%>
                         <tr>
                             <td><%=data.list[i].dt_txt%></td>
                             <td><%=data.list[i].main.temp%>&#176</td>
                             <td><%=data.list[i].main.humidity%>%</td>
                             <td><%=data.list[i].main.pressure%> atm</td>
                             <td><%=data.list[i].clouds.all%> %</td>
                             <td><%=data.list[i].wind.speed%> m/s</td>
                             <td><%=data.list[i].wind.deg%>&#176</td>
                             <td><%=data.list[i].weather[0].main%></td>
                             <td><%=data.list[i].weather[0].description%></td>
                         </tr>
                     <% } %>
                 </tbody>
             </table>
         </div>
     <% } %>
  </body>
</html>

This is typical HTML-markup, but with ejs <%expression%> tags.

In these tags, the file interacts with javascript commands (like conditions, loops, etc.).

Pay attention that for getting the value of some object ejs uses <%=object.value%>.

Here we’ll create the table with<thead> rows (names of the columns) and then in a loop we take the correct data from the response.

Also, there is <h4> highlighted text with the name and country of the city.

If you want to get a forecast for any other place, you should change the q parameter.

Now let’s run our server and visit it.

You wouldn’t want to be a sailor in this time of year.

Now let’s upgrade the frontend part of the site with a little CSS.

All the supporting files (static, images, databases, scripts, etc.) should be stored in the public folder.

It is important to distinguish the different types of static files so that we will keep our stylesheets tools in the CSS subfolder.

After managing this path, create a style.css file.

Let’s add the following styling:

html,
body {
  height: 100%;
}
body {
    margin: 0;
  background: linear-gradient(to right bottom, #49a09d, #5f2c82);
  background-repeat: no-repeat;
  background-attachment: fixed;
    font-family: sans-serif;
    font-weight: 100;
}
.container {
  position: absolute;
  width: 100%;
    top: 10%;
    left: 0%;
}
table {
    width: 100%;
    border-collapse: collapse;
    overflow: hidden;
    box-shadow: 0 0 20px rgba(0,0,0,0.1);
}
th,
td {
    padding: 15px;
    background-color: rgba(255,255,255,0.2);
    color: #fff;
}
th {
    text-align: left;
}
thead th {
    background-color: #55608f;
}
tbody tr:hover {
     background-color: rgba(255,255,255,0.3);
}
tbody td {
  position: relative;
}
tbody td:hover::before {
  content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: -9999px;
    bottom: -9999px;
    background-color: rgba(255,255,255,0.2);
    z-index: -1;
}

After that, you should modify index.ejs file. Paste this line in the <head> section:

<link rel="stylesheet" type="text/css" href="/css/style.css">

Here we are connecting the style file with the template. Modify the <div> tag with the attribute:

<div class="container">

Save it and rerun to the server. Now it should look a little bit prettier:

Now Ampton doesn’t look so bad.

Related Resources

4/5 - (4 votes)

View Comments

Share
Published by

Recent Posts

Power Up Your Enterprise Hub: New March Release Boosts Admin Capabilities and Streamlines Integrations

We're thrilled to announce the latest update to the Rapid Enterprise API Hub (version 2024.3)!…

3 weeks ago

Unveiling User Intent: How Search Term Insights Can Empower Your Enterprise API Hub

Are you curious about what your API consumers are searching for? Is your Hub effectively…

3 weeks ago

Rapid Enterprise API Hub Levels Up Custom Branding, Monetization, and Management in February Release

The RapidAPI team is excited to announce the February 2024 update (version 2024.2) for the…

1 month ago

Supercharge Your Enterprise Hub with January’s Release: Search Insights, Login Flexibility, and More!

This January's release brings exciting features and improvements designed to empower you and your developers.…

3 months ago

Enhanced Functionality and Improved User Experience with the Rapid API Enterprise Hub November 2023 Release

Rapid API is committed to providing its users with the best possible experience, and the…

5 months ago

The Power of Supporting Multiple API Gateways in an API Marketplace Platform

In today's fast-paced digital world, APIs (Application Programming Interfaces) have become the backbone of modern…

6 months ago