• Caching our content
  • Using manifest and offline plugins from gatsby
  • We need API Calls

    • How to do our API Calls
  • Caching our video

In the last episode, we built the starting point of our PWA at DailyDrip. We are showing hardcoded data. We have the Drip content hardcoded and the Video URL. We are using Grommet with Gatsby.

Today we will cache the content, and make the API calls to our API.

Here is our API call. It returns a JSON with the content description, title, and the video URL. Everything we want. This requests should pass a token in the header.

Caching with Gatsby

Gatsby has some plugins to help our life as we saw before. We will use the Gatsby offline plugin to cache our data, it uses sw-precache. And we will use gatsby manifest plugin, to help us manage our manifest.json.

Let's add them as libraries.

yarn add gatsby-plugin-manifest


yarn add gatsby-plugin-offline

Now, we can set up and customize these plugins in our gatsby configuration file.

vim gatsby-config.js

We will add them in the plugins section.

For the manifest, we will add name, shor name, colors and the display mode. We saw in previous episodes what this means. Also, we will set our icons. This is nothing new for us.

      resolve: `gatsby-plugin-manifest`,
      options: {
        name: "DailyDrip PWA",
        short_name: "DailyDrip",
        start_url: "/",
        background_color: "#f7f0eb",
        theme_color: "#a2466c",
        display: "minimal-ui",
        icons: [
            // Everything in /static will be copied to an equivalent
            // directory in /public during development and build, so
            // assuming your favicons are in /static/favicons,
            // you can reference them here
            src: `/favicons/android-chrome-192x192.png`,
            sizes: `192x192`,
            type: `image/png`
            src: `/favicons/android-chrome-512x512.png`,
            sizes: `512x512`,
            type: `image/png`
      resolve: "gatsby-plugin-offline",
      options: {
        runtimeCaching: [
          // these assets, let's cache them aggressively
          // We probably want these to check the network first but this works
          // and at least shows some differences
            urlPattern: /\.(?:png|jpg|jpeg|webp|svg|gif|mp4)$/,
            handler: `cacheFirst`
          // Our js and css, we'd like to change them
            urlPattern: /\.(?:js|css)$/,
            handler: `networkFirst`
          // our API should always be checked for the latest episode
            urlPattern: /dailydrip/,
            handler: `networkFirst`

The super interesting and new thing for us is about caching. This is similar to what sw-precache does. Here we are adding runtime cache. We need to cache all our assets, our API calls and especially the video.

We will start by caching all our assets. They can be png, jpg, svg or others. We will also cache mp4, that will be our video. We will use as cache handler mechanism, cacheFirst. It means, we will first get this from the cache before doing the HTTP request. These handler options and others you can see on the sw-toolbox documentation.

Our JS and CSS will be used network first, because we would like to change them, in case there is something new from the API. Our APi request will also be network first, because everyday we have a new video.

This is everything we need to do to cache our content and make our website work offline.

Making API Calls

To make our API calls, we are going to use apisauce. It is a library to make HTTP request, it is very similar to axios.

Let's add apisauce to our project.

yarn add apisauce

We will create a folder to have our api content

cd src/
mkdir api
cd api
vim DailyDripApi.js

In our API, we will import apisauce and have a BASE_URL to be used with our API. Also, we will have a functin that returns the url to get our daily video. The token will be stored in an environment variable.

We have two instances for our API, a raw instance and an authenticated instance, we are going to use the authenticated instance and pass the token in the headers.

import apisauce from "apisauce";

const BASE_URL = "https://www.dailydrip.com/api";
const dailyVideoUrl = () => `${BASE_URL}/drips/?daily=1`;

const authToken = process.env.GATSBY_API_TOKEN;

const rawInstance = apisauce.create({
  baseURL: `${BASE_URL}`

const authedInstance = () => {
  return apisauce.create({
    baseURL: `${BASE_URL}`,
    headers: { Authorization: `Token token=${authToken}` }

export default {
  getDailyContent: function getDailyContent() {
    return authedInstance()
      .then(response => response.data);

As API method, we will have a method called getDailyContent, returning the JSON we saw in Postman. This will be what our API functions should look like.

We will make the HTTP requests in our Drip component. It will have state. Yes, state. We avoid using state in our React components, but this is only one component, I don't want to use Redux here, just for a single thing, if this project grows up more and we have more requests, probably redux would be a good choice.

Our state will have title, content and videoURL. We will make our request in our componentDidMount method.

  componentDidMount() {
    DailyDripApi.getDailyContent().then(response => {
        title: response.title,
        content: response.description,
        videoURL: response.video

We will get the content from our response JSON. Also, we need to change in our component what we have hardcoded before, not it will get this from the state.

Let's test that! Here we are getting data from our local environment, it does not have video, but this text comes from there.

We will deploy in netlify. We also should add our environment variable on the production server, let's do that.

Once we push, it deploys automatically. And here it is building. Nice! Deployed!

Let's check localhost if I went offline, and I refresh the page, I can see everything, including the video. We are getting all the assests from the Service Worker.

Let's check now our deployed website, it also works. If we go offline, we can see everything.


Today we incorporated API calls into our PWA, and we cached them. See you soon!