UNPKG

gatsby-source-sanity

Version:

Gatsby source plugin for building websites using Sanity.io as a backend.

247 lines (201 loc) 9.27 kB
# gatsby-source-sanity Source plugin for pulling data from [Sanity](https://sanity.io) into [Gatsby](https://gatsbyjs.org) websites. ## Basic usage ``` yarn add gatsby-source-sanity # or npm i gatsby-source-sanity --save ``` ```js // in your gatsby-config.js module.exports = { // ... plugins: [ { resolve: 'gatsby-source-sanity', options: { projectId: '123456', queries: [ { name: 'posts', type: 'Post', // optional groq: ` *[_type == 'post']{ _id, title, body, } ` }, { name: 'authors', // For this case, without a type explicitly defined, // nodes will be created with type = sanityAuthor // and arrays with AllSanityAuthor groq: `*[_type == 'author']` } ] } } ] // ... } ``` Go through http://localhost:8000/___graphql after running `gatsby develop` to understand the created data and create a new query and checking available collections and fields by typing `CTRL + SPACE`. ## Options | Options | Type | Default | Description | | ------------------- | ------- | -------------------------- | ---------------------------------------------------------------------------------------------- | | projectId | string | | **[required]** Your Sanity project's ID | | dataset | string | production | The dataset to fetch from (can be tied to an .env file as needed) | | useCdn | boolean | `true` | Whether to use Sanity's CDN or not. [Learn more](https://www.sanity.io/docs/api-cdn) | | saveImages | boolean | `false` | Whether to save images to disk. [This has limitations, though](#saving-images-to-your-filesystem). | | queries | array | | **[required]** An array of objects that should contain the options below: | | (Query object) name | string | | **[required]** The name of the query, vital for the plugin's functioning | | (Query object) groq | string | | **[required]** The actual [GROQ query](https://www.sanity.io/docs/data-store/how-queries-work). | | (Query object) type | string | `'sanity' + query.name` | Used to name the collection inside GraphQL | **PLEASE NOTE**: _All_ GROQ queries must contain the _id property as it'll be used as the internal ID for Gatsby's `createNode` function. Your build process will fail otherwise. ## Saving images to your filesystem ⚠️ **This is an experimental feature, please report any bugs in the [issues](https://github.com/hcavalieri/gatsby-source-sanity/issues)** If you want to save images to the filesystem, you can use the `saveImages: true` option, but this will only work for those image objects containing a `_type: 'image'` and an `asset` property. The plugin uses the package `@sanity/image-url` to create URLs for images that preserve hotspots, crops and so on. To avoid any errors in this process, the `asset` field should, ideally, be complete. Here's a quick way of building your queries with images that will be processed correctly: _Reminder_: You can also [serve images through Sanity](#serving-images-through-sanity). ```js const imageField = 'image{ _type, asset-> }'; // By standardizing your image field query, you've // got yourself a sure way of providing the correct // data for the plugin to save images to the filesytem const postsQuery = ` *[_type == 'post']{ _id, meta{ ${imageField}, }, author->{ name, excerpt, ${imageField}, } } `; ``` ## Using .env variables If you don't want to attach your Sanity project's ID to the repo, you can easily store it in .env files by doing the following: ```js // In your .env file SANITY_ID=123456 SANITY_DATASET=production // In your gatsby-config.js file require("dotenv").config({ path: `.env.${process.env.NODE_ENV}`, }); module.exports = { // ... plugins: [ { resolve: 'gatsby-source-sanity', options: { projectId: process.env.SANITY_ID, dataset: process.env.SANITY_DATASET, // ... } } ] // ... } ``` This example is based off [Gatsby Docs' implementation](https://next.gatsbyjs.org/docs/environment-variables). ## Storing your queries in an external file Your GROQ queries will probably be long and complex, making it rather unruly to fit them all inside you `gatsby-config.js` file. What I recommend doing is creating an external `.js` file such as `sanityQueries.js` and export your queries from there. Here's an example: ```js // In your ./sanityQueries.js const metaQuery = ` meta { "ogImage": ogImage.asset->.url, seoDescription, seoTitle, slug, title, } `; const postsQuery = ` *[_type == 'post']{ ${metaQuery.trim()}, _id, body, author, } `; const authorsQuery = ` *[_type == 'author']{ _id, name, description, "photo": headshot.asset->.url, } `; module.exports = { postsQuery, authorsQuery, } // In your gatsby-config.js const queries = require('./sanityNewQueries'); module.exports = { // ... plugins: [ { resolve: 'gatsby-source-sanity', options: { // ... queries: [ { name: 'posts', type: 'Post', groq: queries.postsQuery, }, { name: 'authors', type: 'Author', groq: queries.authorsQuery, } ] } } ] // ... } ``` ## Plugin's shortcomings Sanity is an *API builder*, and for such, it's extremely hard to predict its data model: you can have all sorts of data types, with fields nested 8 levels deep inside an object, for example. For such, **this plugin can't go far in shaping your nodes' format**. If you need extra or modified fields built right into the nodes, your option is to process them in your `gatsby-node.js` file through the [onCreateNode](https://next.gatsbyjs.org/docs/node-apis/#onCreateNode) API. *Please note:* Gatsby's `createNodeField` action attaches your new field inside a `fields` object in your node, so when you query for your data in GraphQL, you'll have to do so by calling `fields { [FIELD-NAME] }`. I recommend that you play around with GraphiQl to understand the data format before building your front-end. ### Attaching a custom field to created nodes The example below is for creating a slug field for your nodes. ```js // gatsby-node.js const slugify = require('slugify'); exports.onCreateNode = ({ node, actions }) => { const { createNodeField } = actions; // check if the internal type corresponds to the type passed // to the plugin in your gatsby-config.js if (node.internal.type === 'Post') { // the new field will be accessible as fields.slug createNodeField({ node, name: 'slug', value: slugify(node.title, { lower: true }) }) } } ``` ## Serving images through Sanity Alternatively, you can use [Sanity's image-url library](https://www.npmjs.com/package/@sanity/image-url) and fetch images on the clientside through their `urlFor` function, that is quite powerful in transforming the files. Then you can LazyLoad these images and manipulate them to the client's device and connection through the `urlFor` function's parameter. More info on this, visit [the package's npm page](https://www.npmjs.com/package/@sanity/image-url). The downside of this approach is that you'd have to create lazy-loading components yourself (or use one from the community), and not have the magical blur / traced-SVG effect of the `gatsby-image` plugin. ## TODO - Do a regEx test for the query names and types to avoid errors from Gatsby - Test for bugs in different environments and data structures (**I have not tested this with Gatsby v1 or v0, yet!**) - Better asset pipeline (I've tried setting up Typescript and file bundling to no avail, if you can help out with this, it'd be awesome!) - Gather feedback for new functionalities if needed ## Credits First and foremost, a huge thanks to the good people backing Sanity for bringing such a joy to my developer life with this amazing CMS. As for the image-saving functionality, it was inspired heavily, at points copied, by [Nectum](https://github.com/nectum) at his [gatsby-source-test](https://github.com/nectum/GatsbyPluginTestBuilding/tree/master/plugins/gatsby-source-test) implementation.