TLDR: Here’s the step-by-step guide on how to use the www.tomorrow.io Weather API for a weather widget — from getting the API token, through building a simple frontend app, to deploying and embedding it on your website.

We will use React to build the widget. We will deploy it using Heroku.

The full source code is available on GitHub .

By the end, you will have this lovely widget:

weather api weather widget

______________________________________________________________________________

Weather widgets are endlessly useful, no matter your project. 

With a well-designed widget, you can easily add weather data to your site or app, improving the user experience and offering practical functionality.

At www.tomorrow.io, we want to help our developer community easily and quickly build exciting new projects with our Weather API. And so, we want to show you step-by-step how to quickly build a weather widget that can have a vast variety of applications.

Let’s get to it.

1. Create an account for the Tomorrow.io API

The first step is easy: go to https://developer.www.tomorrow.io/sign-up and create an account.

www.tomorrow.io api weather api

The Tomorrow.io API has a free version, but also a few paid tiers as well with greater functionality. For our example, we’ll stick with the free weather API

Copy the API key, as seen below.

weather api key

2. Create a simple React app

In order to quickly get to a working widget, we will use Create React App to bootstrap our application. So with no further ado, let’s start by typing the code below in a terminal:

npx create-react-app my-app-name
cd my-app-name
npm start

If all went well, you should be able to enter http://localhost:3000/ and see your app up and running.

Now that we have it, let’s start writing our own widget code. We will do it in a few steps:

Fetch data from the API

Now we’re going to fetch the data from the API. In our widget we want to show realtime information and hourly forecast. We will fetch this information using React Hooks that we will create. One hook for Realtime, and one hook for Hourly. They will use a generic hook that fetches information. We would provide the hooks with the parameters that we need to send to the API:

All the details of the endpoints are, of course, available in the API docs.

The hook looks like this:

import { useState, useEffect } from 'react';

/**
 * A hook that fetches the given <url>.
 */
function useFetch({ url }) {
    const [response, setResponse] = useState({});
    const [loading, setLoading] = useState(true);
    const [hasError, setHasError] = useState(false);

    useEffect(() => {
        setLoading(true);
        fetch(url)
            .then((res) => {
                if (res.status !== 200) {
                    throw new Error(res.statusText);
                }
                return res.json();
            })
            .then((res) => {
                setResponse(res);
                setLoading(false);
            })
            .catch(() => {
                setHasError(true);
                setLoading(false);
            })
    }, [url]);

    return [response, loading, hasError]
}

export { useFetch };
import { useFetch } from "./use-fetch.hook";
import { createUrl } from "../utilities";

/**
 * A react hook that fetches hourly forecast for a given location
 * (<lat>, <lon>) for a time frame (<start>, <end>).
 */
const useHourly = ({ apikey, lat, lon, start, end }) => {
    const url = createUrl({
        url: 'https://api.www.tomorrow.io/v3/weather/forecast/hourly',
        query: {
            apikey,
            lat,
            lon,
            unit_system: 'si',
            fields: 'precipitation,temp,feels_like,weather_code',
            start_time: start.toISOString(),
            end_time: end.toISOString()
        }
    });

    return useFetch({ url });
};

/**
 * A react hook that fetches realtime data for a given location
 * (<lat>, <lon>) for a time frame (<start>, <end>).
 */
const useRealtime = ({ apikey, lat, lon }) => {
    const url = createUrl({
        url: 'https://api.www.tomorrow.io/v3/weather/realtime',
        query: {
            apikey,
            lat,
            lon,
            unit_system: 'si',
            fields: 'precipitation,temp,feels_like,weather_code',
        }
    });

    return useFetch({ url });
};

export { useHourly, useRealtime };

Create UI components to present it

Now that we have the data, we can create the UI to present it. We’ll start with the main component – App. It will use the hooks we created, handle loading and error states, and will render the app parts – time and title, realtime information and hourly forecast. It looks like this:

import React from 'react';
import './app.component.css';
import { Realtime } from "./realtime.component";
import { Hourly } from "./hourly.component";
import { useHourly, useRealtime } from "../hooks/use-weather.hook";
import Tomorrow.ioIcon from '../icons/www.tomorrow.io-icon-colored.svg';
import PinIcon from '../icons/pin.svg';
import { addHours } from "../utilities";

const now = new Date();
const sixHoursFromNow = addHours({ date: now, hours: 6 });

function Loading() {
    return <div>Loading...</div>;
}

function Error() {
    return <div>Oops! Something went wrong :(</div>;
}

function PoweredBywww.tomorrow.io() {
    return (
        <div className="powered">
            <a className="powered-link" target="_blank" href="https://www.www.tomorrow.io">
                <img className="icon powered-icon"
                     src={www.tomorrow.ioIcon}
                     alt="Powered by Tomorrow.io"
                     title="Powered by Tomorrow.io" />
                Powered by Tomorrow.io
            </a>
        </div>
    );
}

function App({ apikey, lat, lon, location }) {
    const [realtimeResponse, loadingRealtime, realtimeHasError] = useRealtime({
        apikey, lat, lon
    });
    const [hourlyResponse, loadingHourly, hourlyHasError] = useHourly({
        apikey, lat, lon, start: now, end: sixHoursFromNow
    });

    if (loadingRealtime || loadingHourly) {
        return <Loading />;
    }

    if (realtimeHasError || hourlyHasError) {
        return <Error />;
    }

    return (
        <div className="app-root">
            <PoweredBywww.tomorrow.io />
            <div className="time">{now.toDateString()}</div>
            <div className="location">
                <img className="icon location-icon"
                     src={PinIcon}
                     alt={location}
                     title={location} />
                {location}
            </div>
            <Realtime realtime={realtimeResponse} />
            <div className="divider" />
            <Hourly hourly={hourlyResponse} />
        </div>
    );
}

export { App };

Realtime component will show the temperature, feel like value and the weather text, with a nice weather icon.

import React from 'react';
import './realtime.component.css';
import { Temp } from "./temp.component";
import { WeatherIcon } from "./weather-icon.component";
import { prettyPrintWeatherCode } from "../utilities";

function Realtime({ realtime }) {
    return (
        <div className="realtime">
            <div className="realtime-temp"><Temp value={realtime.temp.value} /></div>
            <div className="realtime-temp-degrees">°C</div>
            <div>
                <div className="realtime-weather-code">{prettyPrintWeatherCode(realtime.weather_code.value)}</div>
                <div className="realtime-feels-like">Feels Like <Temp value={realtime.feels_like.value} />°</div>
            </div>
            <div className="realtime-icon">
                <WeatherIcon value={realtime.weather_code.value} />
            </div>
        </div>
    );
}

export { Realtime };

Hourly component will go through the next 6 hours of forecast, and will show the hour, the temperature, and it’s weather icon.

import React from 'react';
import './hourly.component.css';
import { formatTime } from "../utilities";
import { Temp } from "./temp.component";
import { WeatherIcon } from "./weather-icon.component";

function Hourly({ hourly }) {
    return (
        <div className="hourly">
            {hourly.map(hour => (
                <div className="hour">
                    <div className="hour-time">{formatTime(hour.observation_time.value)}</div>
                    <div className="hour-icon"><WeatherIcon value={hour.weather_code.value} /></div>
                    <div className="hour-temp"><Temp value={hour.temp.value} />°</div>
                </div>
            ))}
        </div>
    );
}

export { Hourly };

You can, of course, design your own icons and UI for your widget, but here at Tomorrow.io, our designer created a library of stylized icons for every type of weather, which you can get here: https://developer.www.tomorrow.io/v3/docs/weather-codes

www.tomorrow.io weather api codes

Create a good look and feel

Now that we have the real-time and hourly forecast data being pulled into our application, and we have the UI components to present it, it’s time to make it look beautiful.

Let’s add some CSS to make everything look nice. We will make heavy use of flexbox to layout our components. The full CSS files are available in the repository. But eventually, we get this good looking widget:

weather api Tomorrow.io weather widget

Enable getting dynamic parameters from URL

OK, so we have a beautiful and functioning widget. But – it’s still working with example hard coded parameters. Now, it’s time to enable passing these parameters from the URL query string, so we can later provide them in our embedding website.

So, before rendering our app, we will read these parameters and pass them to our App component, propagating them to the components and hooks that we built in the previous sections. It will look like this:

import React from 'react';
import ReactDOM from 'react-dom';
import { App } from './components/app.component'
import './index.css';

const params = new URLSearchParams(window.location.search);

const apikey = params.get('apikey');
const lat = params.get('lat');
const lon = params.get('lon');
const location = params.get('location');

ReactDOM
    .render(
        <App apikey={apikey} lat={lat} lon={lon} location={location} />,
        document.getElementById('root')
    );

Now, we can use the widget like this (notice the URL parameters):

weather widget weather api

Our widget is done! It’s time to deploy it 🚀

3. Deploy your widget

We will use GitHub and Heroku as source control and hosting solution for our widget. Of course, you can use any other solutions. 

The first step after uploading our code to GitHub repository is to create a new Heroku app and a pipeline that will deploy the app automatically on every push to master branch, like this:

weather api heroku weather widget

Now, under Settings we connect it to our GitHub repository, and activate automatic deploys. After doing it, the settings page should look like this:

weather api heroku

If we don’t want to wait for the automatic deploys, we can click Manual Deploy on the same settings page. 

Well, if all went well, we can open our deployed widget by clicking “Open app”.

www.tomorrow.io weather widget

Notice: the widget will now show error state as expected, since we did not provide the required parameters.

https://www.tomorrow.io-weather-widget.herokuapp.com/?apikey=YOUR_API_KEY&lat=40&lon=-2&title=BOSTON

So let’s provide him with some example parameters, and see it in the works:

weather widget Tomorrow.io

4. Embed on your website or app

Now, we’re at the last step – embedding our widget on our website!

We do this by injecting an iframe element that it’s src points to our newly deployed URL. The markup will look like this:

weather api weather widget iframe

And that’s it! You’ve successfully created a custom weather widget using the Tomorrow.io weather API. Hopefully that was helpful, and we look forward to seeing what you build with our API. 

Notice: In this post we put the API key on the client as a query parameter to the widget, for example purposes. Your API key is a secret, and should not be exposed on client side in a real production environment. We recommend creating a server that would perform as a proxy to Tomorrow.io API, and keeping the API key there.