Create a Node.js Weather App - Get the weather from the command line

In this article, we’ll make a weather app CLI (command-line interface). We’ll use the OpenWeather API, axios, and pure Node.js. So before we get started, head on over to OpenWeather and create an account, you’ll need an API key to continue with the article.

Setting up

Create a new directory, called weather, with a file index.js:

user@user:~$ mkdir weather
user@user:~$ touch index.js

We’re also going to need to initiate npm:

user@user:~$ npm init

Just hit enter for each prompt.

Now that we got that out of the way, let’s install axios:

user@user:~$ npm i axios

Axios is a promise based HTTP client for the browser and node.js. Basically, it’s what we’re going to use to fetch data from the OpenWeather API.

Your folder structure should now look like this:

user@user:~$ ls
index.js node_modules package.json package-lock.json

Now that our project is set up, let’s start writing our code.

Setting up index.js

We’re going to need to include some things before we begin prompting users for their location, such as a way to make our file executable, import the axios library, and setting some API information.

#!/usr/bin/env node
const axios = require("axios");

const BASE_PATH = "http://api.openweathermap.org/data/2.5/weather";
const API_KEY = "<your key here>";

Note: To get your API key, click your username on the navigation bar on the OpenWeather website. Select “My API keys”. Copy and paste it to the API_KEY variable.

To make our file executable, we’ll need to run a command: chmod +x index.js. After entering this command, we’ll be able to run our file by typing ./index.js. Note: Our file can still be executed by typing node index.js.

We can now start writing some code.

First, we need to be able to prompt users for their location. We can accomplish this with a function, prompt:

const prompt = (message, callback) => {
  const stdin = process.stdin;
  const stdout = process.stdout;

  stdin.resume();
  stdout.write(message);

  stdin.once("data", (data) => {
    callback(data.toString().trim());
  });
};

(Using the DRY principle, this is the same function we used in this article).

The above function will ask a user for their location and then do something (i.e. fetch data from the API) with that information via the callback.

Let’s call the function:

prompt("Enter a location or a postal code: ", function (location) {
  if (!location) {
    console.log("Please try again");
    process.exit();
  }
});

And test it out:

user@user:~$ ./index.js
Enter a location or a postal code:

Nothing will actually happen yet, as we haven’t implemented our API call. Lets do that now.

prompt("Enter a location or a postal code: ", function (location) {
  if (!location) {
    console.log("Please try again");
    process.exit();
  }

  axios
    .get(`${BASE_PATH}?q=${location}&units=imperial&appid=${API_KEY}`)
    .then((response) => {
      const weather = response;
      const message = `\nCurrent date and time: ${weather.headers.date}\nIt's ${weather.data.main.temp} degrees in ${location}.`;

      console.log(message);
      process.exit();
    })
    .catch((err) => {
      console.log(`Error: ${err.response.data.message}`);
      process.exit();
    });
});

We’ve now added our API call. First, axios will .get the data based on the location entered. It’s in the parameter as ${location}, along with the API key that we defined at the beginning of this article. Then, we’ll store the response in a variable called weather, which we’ll use in the message variable to access the date, temperature, and location.

After our data is fetched, and we have then stored it in a variable (message), we’ll log it to the console, exiting the process, as it’s complete.

If it fails (e.g. an invalid location was entered), an error message will be logged to the console instead.

Full Code

#!/usr/bin/env node
const axios = require("axios");

const BASE_PATH = "http://api.openweathermap.org/data/2.5/weather";
const API_KEY = "<your key here>";

const prompt = (message, callback) => {
  const stdin = process.stdin;
  const stdout = process.stdout;

  stdin.resume();
  stdout.write(message);

  stdin.once("data", (data) => {
    callback(data.toString().trim());
  });
};

prompt("Enter a location or a postal code: ", function (location) {
  if (!location) {
    console.log("Please try again");
    process.exit();
  }

  axios
    .get(`${BASE_PATH}?q=${location}&units=imperial&appid=${API_KEY}`)
    .then((response) => {
      const weather = response;
      const message = `\nCurrent date and time: ${weather.headers.date}\nIt's ${weather.data.main.temp} degrees in ${location}.`;

      console.log(message);
      process.exit();
    })
    .catch((err) => {
      console.log(`Error: ${err.response.data.message}`);
      process.exit();
    });
});

Conclusion

You might want to expand on this small program to make it better. For example, you might want to store your API keys more securely. You can create some environment variables to hide your key. Whatever you decide to do, please share it with us in the comments below.

Happy coding!

comments powered by Disqus

Related Posts

Unveiling the Fascination of the Collatz Conjecture: Exploring Sequence Creation with JavaScript

The Collatz Conjecture, also known as the 3x+1 problem, is a fascinating mathematical puzzle that has intrigued mathematicians for decades. It has sparked publications with titles such as The Simplest Math Problem Could Be Unsolvable, or The Simple Math Problem We Still Can’t Solve because it is, indeed, rather simple-looking.

Read more

The Art of Data Visualization: Exploring D3.js

Data is everywhere, flowing into our applications from various sources at an unprecedented rate. However, raw data alone holds little value unless it can be transformed into meaningful insights.

Read more

JavaScript’s Secret Weapon: Supercharge Your Web Apps with Web Workers

During an interview, I was asked how we could make JavaScript multi-threaded. I was stumped, and admitted I didn’t know… JavaScript is a single-threaded language.

Read more