John Stewart

Hi! I'm John. I'm a developer, coder, geek, tech head, maker of websites at MLB. JavaScript always. Creater of Pomy.io 🍅

Next.js + Google Sheets

Pretty good 👌🏽

I love building out a CMS. I think Wordpress and Drupal are really powerful solutions for companies. Then you get into the headless CMS market and there are even more options to choose from.

Sometimes though you are working on a small site and would like to make static content dynamic without having to implement an entire CMS. I ran into this situation recently and had remembered colleagues telling me they had used a Google Spreadsheet to power content for a site.

So a few google searches and I found Tabletop.js. This is an awesome library that allows you to pull information from a Google Spreadsheet into your application which is exactly what I did.

Tabletop.js + Google Sheets

There are some specific instructions you have to follow in order to get this to work properly so definitely take your time with those and make sure you get it right.

After you have properly published your Google Sheet the next step is to run the following.

Tabletop.init({
  key: 'YOUR_KEY_HERE',
  callback: function(data) {
    console.log(data);
  },
  simpleSheet: true
});

That's all it takes to be able to grab some data from a Google Sheet!

One thing to note is that this library is isomorphic meaning that it can fetch data on the server as well as the client. This presented a small issue with Next.js as Next.js was trying to bundle the server code for the client which lead to issues.

Next.js Integration

To integrate this into Next.js was fairly easy once I realized I could just use a custom express server with Next. From that perspective it makes a bit more sense as I am fetching the data to power the site then sending that as initial data down to the components within Next.

Below is a small sample of what was done to integrate it.

function getData() {
  return new Promise(resolve => {
    Tabletop.init({
      key: 'YOUR_KEY_HERE',
      callback: data => resolve(data),
      simpleSheet: true
    });
  });
}

server.get('/', async (req, res) => {
  try {
    const data = await getData();
    return app.render(req, res, '/index', { cmsData: data });
  } catch (error) {
    console.error(error);
  }
});

I left out a bit here on using express with Next.js mainly because there is a great example repo located here that should answer your questions.

Production Concerns

While using this approach seems nice it definitely has it's drawbacks. Turns out someone else has already discussed these drawbacks here.

That said, I have two main concerns. One, being that Google can really change this endpoint that is being used at any given time. Second, being that if the data for the site is not accessible for any reason then the site will be pretty messed up if it's relying solely on that data.

There are many possible solutions for this. The first I thought of was to create a copy each time the data is fetched. Store this on the file system or in memory as it's probably not that big (at least mine isn't). This provides a nice fallback.

Summary

I think this is a great solution for small websites that you want to provide some dynamic aspect to without reaching for a CMS. It has it's drawbacks but I think these can be overcome.

Lastly, after doing some quick Googling it seems that there is a market for very small CMS solutions. All I found was Tiny CMS but even that didn't meet the use case I described here.

A simple lightweight CMS with one endpoint for page data seems like something a lot of people would be interested in or at the very least one person 🙂.

If you liked this article and want to say hi, then you can find me on Twitter.