Using Nextcloud with Gatsby WebDAV

Saturday, 10th October, 2020
Using Nextcloud's WebDAV capabilities makes it a suitable backend storage for Gatsby

Party like it's 1999

I have for some time been using Nextcloud as my own personal file storage, calendar, to-do list and go-to cloud platform for everything involving my personal and family life. It's been a breath of fresh air; a cloud system that I can control, own and maintain, safe in the knowledge that some tech giant isn't scanning my family photos to train their AI.

While it's doing a good job of acting like my own personal dropbox, it occured to me that what would be great is if I could easily build static websites, say for my son's Christening, using photos from my Nextcloud. I saw that without asking everyone I wanted to visit the site to have an account on my Nextcloud instance, there wasn't an easy way to acheive this.

Having already figured out how to make plugins for Gatsby, I wondered whether anyone had made one for Nextcloud. With a bit of digging, I found that Nextcloud supports WebDAV, an extenstion of HTTP that provides for remote web content authoring, and is deeply integrated in most tools and OSs since its inception in 1999.

I found an npm package that implemented the necessary client side script to make WebDAV calls, and so I decided to try my hand at creating a source plugin for Gatsby.

Sourcy...

A source plugin is one that reads data from somewhere and creates nodes in GraphQL, the internal data tool used by Gatsby. A source could be anything: typically the filesystem (for images, markdown etc), or APIs (e.g. pulling down content from a headless CMS). Once the nodes are available, Gatsby developers can then derive pages from these in a static site.

While this was a diversion from making a static website in this case, it was a clear case of where I might make a small open source contribution, whilst keeping my Gatsby project cleaner; for the website doesn't need to know any of the details about WebDAV, the mounted shares, the filesystem directory structure or anything. It will instead be able to query GraphQL for available WebDAV nodes which I can render in anyway I see fit.

query {
      allWebdav(sort: { fields: [lastmod], order: DESC }) {
        edges {
          node {
            basename
            filename
            id
            lastmod
            mime
            size
            type
            webDavContent {
              publicURL
              childImageSharp {
                fluid {
                  src
                  srcSet
                  aspectRatio
                  sizes
                  base64
                }
              }
            }
          }
        }
      }
    }

I added a little bit of logic to allow for retries, as I found the WebDAV code or my Nextcloud instance would sometimes fail to fetch. I ought to add some code to throttle the requests too (PRs welcome!), but for the most part the plugin is really just gluing together the WebDAV API with Gatsby's internal API.

Et Voila

Once the plugin's installed in your Gatsby project, you can then check the query above in your gatsby-node.js file and do what you want with the results. To create an individual page for each entry I'd write:

webdavItems.data.allWebdav.nodes.forEach(node => {
  createPage({
    path: node.id,
    component: path.resolve("./src/templates/some-component.js"),
    context: node,
  })
})

I found that using the plugin meant that I could focus much more on the presentational aspect of this (which is really what I want to do for small, private sites like this) and worry less about where the data comes from.

For more information, see the source code with an example site in Gatsby on my Github.