Data Modeling
Data modeling can be accomplished without writing any code using the shape editor. The shape editor provides a simple, easy-to-use interface where you'll define your shape's metadata and storage, then define its properties.
First, go to the "API" section of your project. Then:
- to create a new shape, use the "Add Shape" button.
- to edit an exiting shape, find it in the schema index and use the "Edit" action, which looks like a pencil
From there, you'll be taken to the shape editor.
Metadata
By convention shape names should be singular. For example, a shape representing articles should be title "Article". Entering the title "Article" will also fill in the name "article". What's the difference?
- Name - API identifier for your shape. It can't contain spaces, can't use special characters, and can't start with a number. Current reserved shape names include
Asset
,Upload
and shapes beginning withTS
. - Title - User-facing identifier for your shape. A title will be generated based on your shape name, but you can further customize it. Titles can include spaces and richer characters.
- Description - A user-facing explanation of a shapes's purpose. The description appears in several places in the UI.
ShapeDB Storage
Data modeling is as open-ended as possible. That said, you create your shapes to fulfill a specific use-case. Your Built-in Data Storage choice describes how you plan to use your shape.
Creating a shape without persistent storage in ShapeDB is useful to represent data returned from connected services, like SearchResults. It's also useful for data structures shared between other shapes, like SEO metadata.
When ShapeDB is enabled, you can choose the type of storage to use:
Single
Denotes a single item or singleton in programming terminology. Persist a single instance of this shape. Useful for creating shapes like Navigation or Settings.
Multiple
Denotes multiple items. This is the default setting. Useful for creating shapes like Products or Posts.
Taxonomy
Denotes a shape which is used to organize others. A taxonomy can be used to filter data entries it has relationships with, like Categories or Tags.
Annotating a shape as a "Taxonomy" allows the relationships between data entries to be surfaced to users when filtering in the asset views and entry list views.
Taxonomies appear in the sidebar in their own section under "Multiple' shapes.
A good taxonomy is something you'll use to classify other thing. Tags, Categories, Topics, Subjects, Genres, and even Authors. Right now the way a taxonomy is used in the UI is to help filter lists.
A taxonomy is effectively a multiple shape that we treat slightly differently on the backend. You can switch a multiple shape to a taxonomy and vice-versa at will.
Taxonomies treat their first text property as their “term” property. This is what will be used for auto suggest.
Properties
You easily can add, configure, and delete Shape properties using our shape editor. Pick the data type, give the property a name, and use the "plus" button it add it to your shape.
- Put your identifying properties first. Property order is important because it informs how the API generates previews of your data for list views, relationships and taxonomies. Examples of identifying properties are "Title", "Name", "Headline", etc.
- Make at least one property required.
Shape properties can hold a single value, or an array of values. In addition to primitive types like String, Number, and Boolean, we also suppport:
- an Asset type, for properties that contain images or other files
- an Object type, for properties that use the data structure of other shapes in your schema, or that use ShapeDB relationships to other saved entries in your schema
Properties are also configurable with widgets for creating and editing their values in ShapeDB.
String properties
String properties resolve to basic string values, like "hello world"
.
When configuring your String property on a shape with ShapeDB enabled, you can choose between many different form widgets for creating and editing string data in ShapeDB:
Single Line Canvas
A single line rich text widget.
Markdown
Markdown widget with preview that uses the CommonMark flavor of markdown.

Single Line
A single line plain text widget.
Paragraph
A multi-line plain text widget.
Slug
Similar to a single line text widget but with some special features specific to content slugs.
When you create a slug property, you can select a Single Line Text widget as a source property. When new content is created, the slug widget is automatically filled out based on a slugified version of the text in the source property using the slugg npm package. The slug widget content can be unlocked, allowing you to use a custom slug value instead.
A slug cannot set its source to a property in a repeater unless the slug is in the same repeater. This avoids ambiguity about what the slug content should be.
Block Canvas MDX
A rich text widget.
By default, querying for a shape with a Block Canvas MDX widget will return the property value in MDX format. Block Canvas MDX fields accept the following parameters to customize the output:
The format argument accepts the following parameters to customize the output:
format
- mdx
- html
headerIdPrefix
A prefix to be added to all id properties on header elements when outputting as HTML.
classPrefix
A prefix to be added to all CSS classes in the generated HTML.
imageConfig
An imgix configuration json object for the default
image size.
query {
home {
fooHtml(imageConfig: {w: 100, h: 100})
}
}
images
Allows you to specify imgix configurations for the default
, small
, medium
, and large
images sizes.
query {
home {
fooHtml(images: {default: {w: 100, h: 100}})
}
}
Returned image urls will have width and height parameters added to the query string: [...]example.jpg?h=100&w=100
.
Datetime
A Date and Time picker widget.
Date
A Date picker widget where the time defaults to midnight in your project's selected timezone.
Dropdown
A single selection dropdown menu widget with a predefined list of options.
Radio Buttons
Single selection radio buttons with a predefined list of options.
Number properties
Number properties hold basic number values. When ShapeDB is enabled, they can be configured to store either an integer
value or a fractional number
value.
Boolean properties
Boolean properties hold basic boolean (true/false) values. When ShapeDB is enabled, they can be configured to use either a "Checkbox" or a "Switch" widget.
When the property type is a Boolean Array, you'll be able to use the "Multiple Choice Checkboxes" widget when ShapeDB is enabled.
Checkbox
A single checkbox widget. Checkboxes work best for granular boolean values, when the resulting value will have a minor impact on the shape.
Switch
A switch widget. Switches work best for high-level boolean values, when the resulting value will have a major impact on the shape.
Multiple Choice Checkboxes
A group of checkbox items with a predefined list of options.
The resulting value will be stored as a list of booleans:
[true, false]
Asset fields
Asset fields hold images, files, or other binary data. When ShapeDB is enabled, asset fields provide an asset selection widget that works with the ShapeDB Asset Library.
query {
photo {
caption
credit
description
filename
mimeType
path
title
}
}
Object fields
Object fields contain references to other Shapes in your schema. Regardless of whether ShapeDB is enabled, there are a few choices for how to references other Shapes in an object field:
- Inline will let you create nested object structures within the shape,
- Relationship will let you create linked references between ShapeDB entries
You will see two other options in this list: "Block Canvas (deprecated)" and "Single Line Block Canvas (deprecated)". These fields provide legacy support for shapes that use the last generation Block Canvas and we discourage choosing them when creating a new shape.
If you'd like to add a new Block Canvas field, create a String field and select the "Block Canvas MDX" widget.
Inline Object
Inline object fields allow you to create nested objects inside your shape, so you can store several values under single property. A common use for an object is modeling an address:
When configuring an Inline Object field, you may select as many shapes as you'd like as valid values.
When the field is singluar, its value will be a single object with properties defined by one of N
shapes you've selected (ex, 1 dog or 1 cat).
query {
getDogOrCat {
shapeObject {
... on Cat {
name
lives
}
... on Dog {
name
isBestFriend
}
}
}
}
Array
When the field is an array of Inline Objects, its value will be a list of any N
shapes (ex, 2 cats and 3 dogs [{cat}, {dog}, {cat}, {dog}, {dog}]
)
query {
getPetStore {
shapeArray {
... on Cat {
name
lives
}
... on Dog {
name
isBestFriend
}
}
}
}
Color
When a Shape chosen for the object is the built-in "Color", the widget for it will automatically be a color picker which stores the selected color in RGB, HEX, HSV.
query {
color {
hex
hsl {
a
h
l
s
}
hsv {
a
h
s
v
}
rgb {
a
b
g
r
}
}
}
Relationship
Relationships are a fundamental part of modeling data that allow data entries to reference one another. You can think of them as foreign keys in RDBMS or Associations from Rails, but as you'll see relationships are much more useful.
The Shapes allowed by a Relationship must have built-in data storage enabled. If you want nested data instead of separate data entries, consider using an Array or Inline Object instead.
When creating a relationship the first step is to choose which shapes you want to allow in the relationship:
Multiple Relationships
When the field type is an array of Objects, relationships can be thought of as an array of single relationships. In addition, relationships can be ordered. Ordering makes multiple relationships a useful tool when building data entries that need to be manually curated.

Reverse Relationships
When a relationship is created a reverse relationship is automatically
added to the related shape. For example if you add a relationship to a
Book
type that points to the Author
type, a reverse relationship
property called bookSet
will automatically appear on Author
.
There are cases where the name of this reverse relationship property
becomes ambiguous. For example, a Post
type with two relationships
authors
and editors
which both point to the Person type. The
automatically generated field postSet
is now ambiguous because it will
contain both authors and editors. The solution is to specify the
"Reverse Name" on each relationship.
To disambiguate these relationships set the "Reverse Name" for
authors
to "authored" and the "Reverse Name" for editors
to
"edited**"**
{
getAuthor(_id: "author_id") {
postSet {
total
results {
title
}
}
}
}
{
getAuthor(_id: "author_id") {
authored {
total
results {
title
}
}
edited {
total
results {
title
}
}
}
}
Block Canvas (deprecated) and Single Line Block Canvas (deprecated)
A deprecated "rich text" field.
Block canvas fields automatically add a corresponding [blockCanvasFieldName]Html field to the API. For example a field named foo will have a corresponding fooHtml field.
- foo returns raw DraftJS JSON
- fooHtml - return rendered to HTML
The html field accepts the following parameters to customize the output:
classPrefix
A string that will prefix HTML class names in the output.
headerIdPrefix
A string that will prefix the id attributes of header elements in the output.
imageConfig
An imgix configuration object for the default image size.
query {
home {
fooHtml(imageConfig: {w: 100, h: 100})
}
}
images
Allows you to specify imgix configurations for the default
, small
, medium
, and large
image sizes.
query {
home {
fooHtml(images: {default: {w: 100, h: 100}})
}
}
Returned image urls will have width and height parameters added to the query string: [...]example.jpg?h=100&w=100.