Weather API - Insights

Building a Serverless Weather Station App Using the Tomorrow.io Weather API

Serverless apps are quickly growing beyond a small niche to a broadly used tech stack for hosting a variety of websites. While these sites are static by nature, that does not mean that the displayed content cannot change. Not only can you load content from an API dynamically, you can also keep the associated endpoints and credentials neatly tucked away in an anonymous function that is not visible from the client side. Let’s see how this can be done:

Before we start: Finding your coordinates

Refer to our Python post to learn about finding the coordinates of your place of interest.

How will this all work?

This is the process in a nutshell:

  • You store your code in a git repository and tell Netlify where that repo is.
  • Netlify will watch the repo for new commits and will build your site as soon as new code is committed.

That’s it! Once Netlify is set up, it doesn’t need a single click to publish new code; just commit from the command line, and Bitbucket and Netlify will do the rest automatically.

Create a new Git repository

While we use Bitbucket for this example, the steps on this level are very similar across all Git platforms, Github and Gitlab being the other two that work with Netlify. Import our sample code from here and store it as a new private repository in your own account.

Sign up for a Netlify account

You’ll see right away that Netlify is closely tied to Git platforms. Instead of the usual “Google or Apple” for single-sign-on, Netlify works with Bitbucket, GitHub and GitLab credentials, or with a good old email address, if you prefer that. Ideally, you choose the platform where your code is located, but the choice is not important: You can later pull from any of the three sites once you provide the relevant credentials.

Sign up, provide some demographic information like your name and company, and click through the three-step Quickstart Guide. As you can see there, Bitlify features…

  • … continuous deployment, allowing you to “push to build”
  • … secure sites with SSL (https://) by default
  • … everything is available on the command line if that is your choice.

You will now see your account cockpit, with some usage stats and a button “New site from Git”. With the free account, at the time of this writing, you get 100GB bandwidth, 300 minutes of build time, one concurrent build and one user. To explore the site this will be plenty; the example for this post takes about 30 second to build and just a few kB of bandwidth.

Deploying a repo on Netlify

What in other scenarios can be half the project – setting up your build pipeline and getting your code to actually build and run on the target – is three easy steps here. Click “New site from Git”, select your Git provider and repository, and a few settings; you can work with the default for now. If you copied our example and followed along, you should now see your site live (using a xyz-012345.netlify.app URL) on the internet.

General repo walkthrough

Let’s look through our project. .gitignore tells Git which local files to ignore and README.md contains the project documentation, package.json contains information for a package manager. You’re probably familiar with those. Server.js is used if you want to test a deployment locally on localhost:, otherwise it is optional. This leaves us with one more file in the root, netlify.toml. This is a configuration file that tells Netlify how to build your site, similar to a make-file. Note that all configuration can be configured on netlify.com as well as in the toml-file; if there is a discrepancy, the file in the repo takes precedence.

The src directory finally contains all the code for our site: First, note that our example is derived from a similar example by netlify; feel free to compare the two projects for further understanding.

The src directory contains two subdirectories, lambda and site, and that is important: site is code that is public on the web; your HTML, CSS and JS files, along with any images etc. In our case, it is simple: Just an index.html and an index.js. The directory lambda contains everything that stays “behind the scenes” – in our case, it is a single file, getapi.js that handles the API calls we want to shield. Open getapi.js and look at the code: it contains neither the API key nor the URL of the API, because both values are stored in an environment variable that we’ll have to configure on Netlify.

That’s it! 8 files, none of them larger than 3 kB, and we have a full-fledged web app. (Ok, a tiny, full-fledged web app.)

Three layers of secrecy: site, lambda, credentials

One of the keys to properly design your site is understanding who has access to what:

Site: These files are public on the web, and this code runs in the client browser – everything is fully transparent and public.

Lambda: If you keep your repository private, this code is not visible to anyone other than those you explicitly give access. As we’ll see in a minute, this code is not executed in the client browser, but on the Netlify server.

Credentials: Even if a few hundred developers have access to your repository, your API credentials will only be accessible to those with access to the Netlify account. And since a commit to the repository will automatically trigger a build, everybody with the ability to commit will automatically publish the new code on the web, without needing access to Netlify.

Code walkthrough

As we’ve seen above, the files in the root of the repo are all configuration files, and all “web content” resides in the 4 files within the src directory. Let’s have a look:

site/index.html

A pretty basic HTML file, nothing unusual in the header. After the title div, we find a hidden div with ID coordinates: these are the coordinates of the location we’re interested in. After that follows the table that displays the values we pull from the API. Note that each cell has its own ID (t1, t2, …, s1, …, h1). This is how we reference the specific cell in the JS code. (There would be more efficient ways to loop through this array, but for this example we’ll keep it simple.)

After that we have another div for the footnote, and one for the refresh button. It couldn’t get more basic than that. Last, but certainly not least, we call our script, index.js

site/index.js

Most of this file is a class called api, which we’ll look at in a second. At the bottom we have the barely 20 lines of code that will be executed when the page gets loaded:

  • An event listener that calls api.send() when the Refresh button is pressed
  • A one-time call of api.send(), to load the weather data when the page is first loaded
  • A periodic timer using setInterval() that, you guessed it, will also call send.api()

api.send() calls api.get(), which does three things:

  • Read the coordinates from the HTML file and construct the API parameters
  • Call the lambda function:

fetch(“/.netlify/functions/getapi” + apiParams)

  • Wait for the lambda function to return, catch any errors and pass the returned JSON object to api.show()

api.show() finally does the heavy lifting of parsing the JSON object and extracting the data. But as you can see, this is straightforward with a basic =-statement for each field. The console.log() lines will help if you want to replace temperature, windspeed and humidity for other data.

Open the page in a browser, and use the developer tools to review the log file.

Are we done?

On the client side, we are: index.html and index.js are the only two files downloaded to the client. The getapi.js remains on the Netlify server and is only accessible by reference. You can call it and pass parameters, but the code within getapi.js remains private.

The lambda function: lambda/getapi.js

This file was derived from Netlify’s example code, and only has one tiny change: the tomorrow.IO API expects the word apikey, while Netlify’s example used key. Other than that, there is no difference.

getapi.js contains a single function called handler, but its name does not matter – it is called anonymously by index.js. The function itself is straightforward:

  • evaluate the parameters using qs
  • combine the parameters with the predefined API credentials

const { API_TOKEN, API_URL } = process.env

const URL = `${API_URL}?${API_PARAMS}&apikey=${API_TOKEN}`

  • call the actual remote API

process.env refers to the environment variables defined in the Netlify environment. This way, while the code of getapi.js is part of your repo, the actual credentials are not.

The environment variables

On Netlify, under your deploy, navigate to Site Settings, Build & Deploy, Environment: This is where you enter your token and the URL as a key value pair. Note that you are of course not limited to just two; you can store as many private values as you need.

Summary

As we saw above, there are three levels of code/content.

Repository/site: Contains all files that will need to be published on the web, and as such are necessarily visible to everybody.

Repository/lambda: Contains the code that is hidden from the public, and only those with access to your repo can view.

Netlify/environment: Contains the API credentials, and only those with access to your Netlify account will be able to see.

Additional Weather API ideas to try out

The example above is only basic, and can of course be expanded as you please:

  • Let the user enter an address, and display the forecast for that location
  • Replace the data, for example ocean wave height, wind direction and sunrise time for surfers, or snowfall accumulation and visibility for mountaineers

Utilize tomorrow.IO’s weather icons available at https://github.com/tomorrow-io-api/tomorrow-weather-codes

More from Tomorrow.io