Chapter 4: Sanity Configuration and Schemas

In the previous chapter, we learned how to use Sanity Studio. In this chapter, we will learn how to clone the project from GitHub, install its dependencies, learn how to start up the local development environment, and examine the file structure. Then, we will learn how schemas are constructed, and how to modify them, learning about relationships. This will allow you to easily make modifications to the schema, testing the schema locally by viewing it in the hosted version in the browser.

The main topics that we will cover in this chapter are the following:

  • Modeling content with schemas
  • Schema relationships
  • Extending, modifying, and deploying the schema

Technical requirements

A Terminal or Terminal emulator.

The code files for this chapter are placed at https://github.com/PacktPublishing/Jumpstart-Jamstack-Development/tree/chapter_four.

Modeling content with schemas

The schema is the heart of Sanity. It is a file that defines the structure of an entity, which could either represent something physical that occurs in nature, for example, a person, such as an author, or something abstract, such as a category, as demonstrated in Chapter 3, Exploring Sanity Studio. These structures and the collections of them, optionally linked together, are what drives the user experience in Sanity Studio.

In the next sections, we will clone the project, and work with the project's schemas.

Cloning the project

In Chapter 3, Exploring Sanity Studio, the create tool automatically created a repository in GitHub. To clone a repository, the git command-line tool is needed. Git is a source code management tool created by the inventor of the Linux kernel, Linus Torvalds. Installation instructions for each operating system can be found at https://git-scm.com/.

Following the standard steps for cloning a repository, type the following command in the Terminal:

git clone repository-name

The repository-name should be replaced with the actual name of your repository. To clone the repository, which creates a local copy, locate the repository that was automatically created in GitHub.

The repository may be cloned using one of two methods:

  • The first method uses SSH, where the username is the GitHub username and repository is the actual repository:

    git clone [email protected]:username/repository.git

    This is shown in the following screenshot:

Figure 4.1 – The GitHub Code clone modal – SSH mode

Figure 4.1 – The GitHub Code clone modal – SSH mode

  • The second method uses HTTPS, where username is the GitHub username and repository is the actual repository. Note the slightly different format than the SSH method:

    git clone https://github.com/username/repository.git

Figure 4.2 – The GitHub Code clone modal – HTTPS mode

Figure 4.2 – The GitHub Code clone modal – HTTPS mode

Both these methods will create a folder at the same filesystem level with the name of the repository. The SSH method allows a password-protected SSH key to be used, so it is the preferred method.

Exploring the project's folders

In this section, we shall examine the contents of the project's folders and files. There are several important files as well as several folders. The first file that we will examine is the sanity.json file. This file is located in the project's studio folder.

Examining the sanity.json file

Here are the first few lines of the sanity.json file:

{

  "root": true,

  "project": {

    "name": "Hands On JAMstack"

  },

  "api": {

    "projectId": "abc123d4",

    "dataset": "production"

  },

This file contains two important values: projectId and the dataset name:

  • projectId: The projectId value uniquely defines the project, meaning that no one else will have this ID. The projectId consists of letters and numbers.
  • dataset: The dataset value, however, is not unique, and will be used to identify which dataset this instance of Sanity Studio is currently using. For example, one might select production to represent a final version of a schema and data, and development to represent the upcoming changes. Both the schema and the actual content are contained within the dataset. Each dataset is completely separate, and Sanity Studio may load any one of the datasets, but only one schema at a time.

Additionally, the root is set to true to specify that this file is the project's main sanity.json file, since plugins may have their own sanity.json files. The sanity.json files found in plugins will have root set to true.

Examining the schemas folder

Next, we shall examine the schemas folder in the studio folder. In the two subfolders – documents and objects, we will find a collection of files, one per schema. Each one is a JavaScript file with a single object. The following code example shows a schema file format with minimal fields:

export default {

  name: 'siteSettings',

  type: 'document',

  title: 'Site Settings',

}

The file begins with the export keyword. The export keyword means that this JavaScript module may be used in the calling file by using the import statement. The next keyword is default. This keyword means that this single object will be used. Finally, the object itself follows, using the opened and closed parentheses.

The three essential attributes in the object, which are key and value attribute pairs, are name, title, and type.

name

The name attribute used in schemas always represents a single entity. The name value must be a single word, and per convention should match the name of the file, but without the extension, of course.

Camel case, named as such because of the animal that it most looks like, is used. The standard format is as follows: the first word is represented as lowercase, and the second word and words that follow are capitalized. For example, a correct name attribute value would be siteSettings.

title

The next important attribute is title. This attribute is meant to be a human-readable description of the schema entity and may contain spaces and other special characters. It is displayed inside Sanity Studio. Therefore, it should be a word that clearly defines what it represents. For example, the corresponding title could be Site Settings.

type

Next, the schema type determines whether the schema is a document or object. A document is what will be listed in the main navigation of Sanity Studio. An object is a more abstract representation of an entity, such as a relationship between two documents or a building block to be used within a document, such as an address block containing several fields, such as address, city, and postal code.

The default project that is automatically created uses the two directories – documents and objects, to help organize the project by grouping the schemas by type.

Author schema

For the next step, examine the structure of the author.js file in the documents directory.

Schema definition

As shown in the following code sample, the fields attribute is an array. The use of square brackets is a syntax to denote a list or collection of items. To begin with, the list of items is empty. It will be filled to contain a list of fields:

export default {

  name: 'author',

  type: 'document',

  title: 'Author',

  fields: [

    ],

}

All entities must contain at least one field. Each object within the fields array follows the same format as the entity itself, at a minimum name, title, and type.

Schema fields

Possibly the simplest example of this would be a name field, which represents the first and last name of the author:

export default {

  name: 'author',

  type: 'document',

  title: 'Author',

  fields: [

      {

         name: 'name',

         type: 'string',

         title: 'Name'

      },

    ],

}

In the preceding code example, we have placed the name attributes inside of the fields array. This array is of a string type, which basically means a short phrase or label without any associated formatting such as bold italics.

Note

The title attribute should represent a word or phrase that a content editor could recognize and will be displayed in Sanity Studio.

There are three other attributes that can be used in each field:

  • description is a longer description of how the field should be used.
  • readOnly disables editing in Sanity Studio.
  • hidden hides the field from Sanity Studio.

The readOnly and hidden fields would be modified programmatically and not by the person using the interface.

Schema field types

There is a wide range of types available for use. At the time of writing, the following types, other than document, are available:

  • Array
  • Block
  • Boolean
  • Date
  • Datetime
  • File
  • Geopoint
  • Image
  • Number
  • Object
  • Reference
  • Slug
  • String
  • Span
  • Text
  • URL

Some of these types are primitives. A primitive is a very simple piece of information, such as a Boolean value, which would be only one of two values, either true or false. Additionally, a number type is simply a numeric value. Other types, such as image, are more complex and contain multiple fields.

Note

The complete documentation on the current types available for Sanity schemas may be found at https://www.sanity.io/docs/schema-types.

We have learned about how schemas are constructed, so now let's look at how these schemas could be connected through relationships.

Schema relationships

Relationships between documents are called references. These references allow a schema to be used in another in various ways, so let's examine the various ways.

A one-to-one relationship

A reference connects one document to another. This is called a one-to-one relationship. An example of a one-to-one relationship might be a person and their street address.

The street address might only belong to one person. The address entity might have the following structure:

export default {

  name: 'address',

  type: 'document',

  title: 'Address',

  fields: [

{

   name: 'street',

   type: 'string',

   title: 'Street'

},

{

   name: 'city',

   type: 'string',

   title: 'City'

},

{

   name: 'postalCode',

   type: 'string',

   title: 'Postal Code'

},

{

   name: 'country',

   type: 'string',

   title: 'Country'

},

    ],

}

In this example, this schema is of type address, so author will link to address through the address reference as shown:

export default {

  name: 'author',

  type: 'document',

  title: 'Author',

  fields: [

  {

    name: 'name',

    type: 'string',

    title: 'Name'

  },

  {

    name: 'address'

    type: 'reference'

    to: {type: 'address'}

  }

  ],

}

In the Sanity schema, we use the reference type and an additional attribute, to. The to attribute accepts an object specifying the type.

A one-to-many relationship

In the same way, a schema can be related to many schemas, even of various types. A simple example is an author that writes for multiple publishing houses:

{

  name: 'publishers',

  title: 'Publishers',

  type: 'array',

  of: [

    {

      type: 'reference',

      to: '[{type: 'publisher'}],

    }

  ]

},

In this example, the type field is an array so that inside Sanity Studio, one or more publishers could be chosen from a list of publishers. Note that the name "publishers" is given to this field to show that this field represents multiple publishers, however, the relationship is to a schema of type publisher, and schema names are always singular.

In the first part of this chapter, we learned about the structure of a schema. In the next section, we will learn how to modify schemas.

Extending, modifying, and deploying the schema

For the example used in this book, we will be creating a news and events website. The first step in this process is to create a file named event.js in the document directory, which will represent our event schema.

The event schema

The following code segment is the schema for an event, illustrating its various fields:

export default {

  name: 'event',

  type: 'document',

  title: 'Event',

  fields: [

    {

      name: 'name',

      type: 'string',

      title: 'Name'

    },

    {

      name: 'dateAndTime',

      type: 'datetime',

      title: 'Date and Time'

    },

    {

      name: 'venue',

      type: 'reference',

      to: {type: 'venue'}

    },

    {

      name: 'virtual',

      type: 'boolean',

      title: 'Virtual Event'

    },

    {

      name: 'eventUrl',

      type: 'url',

      title: 'URL'

    },

    {

      name: 'body',

      type: 'bodyPortableText',

      title: 'Body'

    }

  ]

}

At this point, most of the file should appear familiar. The event date and time will use a special datetime field type that will present a nice calendar to the user. The event will be linked to a venue if it is not a virtual event. Whether or not the event is virtual, it will be represented by a Boolean value.

Lastly, bodyPortableText is a special field type; it is actually its own schema, representing a more advanced structure, as well as instructions on how it will be used.

The venue schema

The next step is to create a file named venue.js in the documents directory. This file will, as expected, represent a venue:

export default {

  name: 'venue',

  type: 'document',

  title: 'Venue',

  fields: [

    {

      name: 'name',

      type: 'string',

      title: 'Name'

    },

    {

      name: 'description',

      type: 'bodyPortableText',

      title: 'Description'

    },

    {

      name: 'location',

      type: 'geopoint',

      title: 'Location'

    },

    {

      name: 'telephone',

      type: 'string',

      title: 'Telephone'

    },

    {

      name: 'email',

      type: 'string',

      title: 'Email'

    },

    {

      name: 'website',

      type: 'url',

      title: 'Website'

    },

  ]

}

The venue schema also contains some useful field types, such as geopoint, which will allow us to take advantage of the Google Maps API to automatically complete an address, and a URL that provides input validation.

The schemas folder should now have the following files:

schemas

  documents

    author.js

    category.js

    event.js

    post.js

    siteSettings.js

    venue.js

The schema file

For Sanity to be able to recognize a new schema, that schema must be added to the schema.js file, which is in the studio/schemas folder. Let's see how to do so:

  1. Add the files via import statements at the top of the file, after the line starting with import siteSettings:

    // document schemas

    import siteSettings from './documents/siteSettings'

    //insert these two rows

    import event from './documents/event'

    import venue from './documents/venue'

  2. Add the imported schema to the list of schema types:

    types: schemaTypes.concat([

      // The following are document types which will appear

      // in the studio.

      siteSettings,

    //insert two rows here

      event,

      venue,

    ])

Deploying the schema

To view the schema changes, they must be deployed. When we deploy something, we move or copy it from one environment to another, usually a production environment where it can be used by other people and things. Here, we will push our changes to the schema into an environment where they may be viewed in the browser. In the root of the project directory, use either npm or yarn to install the dependencies.

Execute one of the following commands by typing it in the Terminal and pressing Enter:

yarn install

or

npm install

Once yarn or npm is used, usually it is beneficial to continue using one or the other, but not both.

Then, start up the development version of Sanity and Gatsby. Execute one of the following commands by typing it in the Terminal and pressing Enter:

yarn run dev

or

npm run dev

Using Lerna

Lerna, a tool used to manage projects with multiple packages, is used to run both Sanity and Gatsby at the same time. Here is how it works:

There is a package.json file in the root folder of the project. Running the npm run dev command will, in turn, execute the following code:

"scripts": {

  ...

  "dev": "lerna run dev --parallel",

  …

This command, npm run dev, is an alias for lerna run dev –parallel.

Lerna uses the lerna.json file in the root folder of the project. The packages that it will reference are web and studio, which correspond to the project's two folders:

{

  "packages": [

    "web",

    "studio"

  ],

  "version": "1.0.0"

}

Likewise, in the web folder, the relevant line in the package.json file is the following:

"dev": "npm run clean-cache && gatsby develop",

The dev alias will be called, which in turn deletes the cache, and then gatsby develop, which starts up the Gatsby development environment.

In the studio folder, which is the focus of this chapter, the relevant line in the package.json file is the following:

"dev": "sanity start",

Similarly, the dev alias will be called, which in turn, calls sanity start, which starts up the Sanity development environment. The schema files will be now applied locally, so a local version of Sanity Studio may be accessed at https://localhost:3333.

This will be accessed through a web browser. The two new schemas – Event and Venue – that we've added should now be visible in the left menu as shown in the following figure:

Figure 4.3 – Content navigation

Figure 4.3 – Content navigation

The Add new event screen can now be seen by following the method in the previous chapter.

The following screenshot is an example of the Add new event screen. Take note of the radio button for Virtual Event, which automatically gets created from the Boolean value specified in the schema:

Figure 4.4 – Add new event form

Figure 4.4 – Add new event form

Similarly, an example of the Venue screen is shown. Notice the Location input, which is a geopoint:

Figure 4.5 – Add Venue form

Figure 4.5 – Add Venue form

Summary

In this chapter, we learned about schemas: how they are constructed and how to create new schemas. Then, we learned how to start up the Sanity and Gatsby development environments to visualize the schema changes in a local development version of Sanity Studio. These are the basic steps that can be repeated many times, adding to and modifying the schema as needed, and subsequently viewing the website as it begins to take form.

In the next chapter, we will introduce GROQ, Sanity's open source query language, and learn how it compares with the Standard Query Language (SQL). We will learn the basic syntax, practice some basic queries, and then learn how to do advanced joins.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset