Schema definition with GraphQL SDL

by Peter Balazs on 02/08/2018

With the release of our Javascript SDK, you can now define your project's schema with the GraphQL schema definition language. Later on, you can change this schema file to evolve your project, and the SDK will take care of handling the migration.

The Mozaik Schema Definition Language (mSDL) is built on top of the GraphQL SDL (GraphQL SDL), with predefined scalars, interfaces and directives. Based on this schema definition, Mozaik will generate all your content types and the final GraphQL schema.

Let's walk through a simple example:

Defining our content type schema

First, we have to identify what content types we need to define in our schema: the primary model is the Blog post type. We want to be able to add one author to each post, and we want to add one or more categories to a post. Also for every post we want to define a featured image. We want to show a placeholder colour on our website until the image is loaded. And of course we need a home page, where we display the latest blog posts, and a few highlighted posts and a main image.

With all this in our mind we can start defining our content types:

Author

An author has a name, an email address and a twitter account. Also we want to be able to create multiple authors. We can define this with the following code:

type Author implements SimpleContentType {
name: SinglelineText @config(label: "Author name", groupName: "personal", isTitle: true)
email: SinglelineText @config(groupName: "personal")
twitter: SinglelineText @config(groupName: "personal")
}

We have to create an Author type that implements the SimpleContentType interface. It will allow us to create multiple documents of this content type.

We have only three fields, and all have are a simple text input. In GraphQL terms it is a String, in Mozaik terms it is a SinglelineText. We will use the later one, however it is possible to use the built in String scalar type for fields, as it is automatically mapped to the SinglelineText type. We can use the @config directive on fields to set different configuration options:

  • we can set a custom label by using the label argument. If it is not set the name of the field will be capitalised and used as the field label in the Mozaik content editor
  • we can group fields, grouped fields will be displayed on different tabs in the content editor. If it is not set, the default group name will be Content.
  • Also we can mark a field to be the document title by setting the isTitle parameter to true

Category

Since we want to be able to categorise our blog posts, we need to create a Category type as well. A category has a name and can have multiple sub-categories.

This type also implements the SimpleContentType because we want to create multiple categories. The name definition is now familiar, since we used the the similar definition for the Author content type. But the subcategories field definition is new: we want to define a reference to the same content type. All we have to do is setting the field type to the same name as we used for defining the type. Since we want to be able to add more categories to a blog post, we have to use the GraphQL List type type modifier ([...]).

The schema definition for this type:

type Category implements SimpleContentType {
name: SinglelineText @config(isTitle: true)
subcategories: [Category]
}

Featured image and Color enum

Every post has a featured image, but it wouldn't make sense to define these featured images as separate documents. This is why Mozaik supports the embeddable content type: we can define a set of fields, that can be used in other content types.

We need define a type that implements the EmbeddableContentType interface. This type has an image field and its type is an Image. By setting a field's type to Image (or Video, Audio or Asset), Mozaik will prompt us to select an image (or the other relevant type) from the Media Library.

type FeaturedImage implements EmbeddableContentType {
image: Image
title: String
background: ColorEnum
}

Also we want to add a background colour property to this content type. But we want to limit what colours can be selected by the editors. For this we can create an enumeration content type: This content type has a predefined set of values that can be selected from a dropdown on the UI. We can define one by defining a GraphQL enum type:

enum ColorEnum {
blue @config(label: "Blue")
lightRed @config(label: "Light red")
}

The values must start with a lower or upper case letter, and can't contain spaces. However, it is possible to add a custom, more-readable label to each value by using the @config directive.

Post

Now we have all the building blocks to define our Post content type:

type Post implements SimpleContentType {
  title: String @config(isTitle: true)
  intro: MultilineText @config(label: "Short description")
  body: RichText
  postAuthor: Author
  featuredImage: FeaturedImage
  categories: [Category]
}

The only new thing here is the MultilineText and RichText types. The first one will add a text area input in the content editor, while the RichText type adds a Rich text editor.

Homepage

The last content type we need to define is our home page. Since it would make sense to have multiple home pages for our site, we want enforce that maximum 1 document can be created for this content type. We can easily achieve this by using the SingletonContentType interface. This does exactly what we want: only one document can added of a singleton content type.

type Homepage implements SingletonContentType {
title: SinglelineText @config(label: "Page title", isTitle: true)
cover: FeaturedImage @config(groupName: "cover")
highlightedPosts: [Post]
}

Final schema

type Author implements SimpleContentType {
name: SinglelineText @config(groupName: "personal", isTitle: true)
email: SinglelineText @config(groupName: "personal")
twitter: SinglelineText @config(groupName: "social")
}

type Category implements SimpleContentType {
name: String @config(isTitle: true)
subcategories: [Category]
}

type Post implements SimpleContentType {
title: String @config(isTitle: true)
  intro: MultilineText @config(label: "Short description"
body: RichText
postAuthor: Author
featuredImage: FeaturedImage
categories: [Category]
}

enum ColorEnum {
blue @config(label: "Blue")
lightRed @config(label: "Light red")
}

type FeaturedImage implements EmbeddableContentType {
image: Image
title: String
background: ColorEnum
}

type Homepage implements SingletonContentType {
title: String @config(isTitle: true)
  cover: FeaturedImage
highlightedPost: [Post]
}

We can use this schema definition with the Mozaik SDK to create all content types in Mozaik from the command line.

Having the possibility to define our content type schema like this, we can keep the schema as part of our code repository. And we can reuse the same schema across different projects, which helps us setting up new projects in just a few seconds instead of doing repetitive work on a UI. Later on this schema can be edited and reapplied to an existing project: Mozaik will take care of doing the hard work of the required migration.