Expose Prismic Content
The Prismic Front-Commerce module provides a loader and the infrastructure to expose Prismic-based Content in Front-Commerce's GraphQL API. This guide explains how to use it.
Exposing Prismic content in an existing Front-Commerce application GraphQL schema is one of the main use case Prismic projects. We tried to keep the API easy to understand and require as little code as possible (while keeping it maintainable and expressive).
To benefit from this API, you first need to install the Prismic module. You will also need a custom GraphQL module to define a GraphQL schema matching the content you want to expose and implement the corresponding resolver. It also recommended to have read the Prismic Core Concepts documentation.
Prismic loader API
The Prismic loader has the following API to request Content from Prismic:
loadSingle(typeIdentifier)
Returns a Content representing a Prismic Content of the corresponding type. If such Content does not exist, it throws an error.
Arguments:
typeIdentifier(string): The type of document.
loadByID(id)
Returns a Content representing a Prismic Content of the corresponding type. If such Content does not exist, it throws an error.
Arguments:
id(string): The ID of the document .
loadByUID(typeIdentifier, uid)
Returns a Content representing a Prismic Content of the corresponding type and having a UID field with the given value. If such Content does not exist, it throws an error.
Arguments:
typeIdentifier(string): The type of document.uid(string): The Unique ID of the document.
loadList(query)
Returns
a ContentList
matching the query. query must be an instance of
ListQuery,
it provides a way to filter, sort and paginate Prismic Content.
Arguments:
query(ListQuery): A query for a list of documents
defineContentTransformers(typeIdentifier, options)
Defines the content transform options for a given document type.
Arguments:
typeIdentifier(string): The type of document.options(ContentTransformOptions): Content transform options
Field Transformers
By default, the Content objects returned by those methods directly expose the
fields defined in the corresponding Prismic Custom Type. For instance if you are
retrieving a Content of type homepage and
this Custom Type is single
and defines a lastUpdate field, you can write something like:
const homepage = await loaders.Prismic.loadSingle("homepage");
// homepage is an instance of Content
// the lastUpdate field can be used directly,
// it's value is the field value returned by the Prismic API
console.log("Last update of my homepage", homepage.lastUpdate);
For most Field Types, the field value can directly be used. However for some of
them, the field value is not very handy to expose the data in the Graph or even
requires a deep transformation. To make that operation easier, the Prismic
loader also exposes some Field Transformers to transform field values. The field
transformers can be registered for a given content type by using the
defineContentTransformers method. In the previous example, if the lastUpdate
field is a Date Field,
homepage.lastUpdate will be a string. If instead you want to have a JavaScript
Date instance as the field value, define the transformers for homepage:
const { DateTransformer } = loaders.Prismic.transformers;
// this will apply to any method loading the `homepage` content type
loaders.defineContentTransformers("homepage", {
fieldTransformers: {
lastUpdate: new DateTransformer(),
},
});
const homepage = await loaders.Prismic.loadSingle("homepage");
// homepage.lastUpdate is now a Date object
console.log("Last update of my homepage", homepage.lastUpdate);
defineContentTransformers only needs to be defined once per content type, and
it's usually better to defined at a higher level in your module, for example in
the
contextEnhancer
The complete list of available Transformers can be found under
the transformers directory in Prismic module.
We will use some of them in the following examples.
Implementation examples
Those examples assume that you have created
a GraphQL module
and that it is already registered. Before being able to use the Prismic module
API, you have to make sure Prismic/Core is a dependency of your module. In
addition, we will use the Wysiwyg feature provided by Front-Commerce/Wysiwyg,
so this one also needs to be in the dependencies:
import typeDefs from "./schema.gql";
import resolvers from "./resolvers";
export default {
namespace: "my-module",
- dependencies: [],
+ dependencies: ["Prismic/Core", "Front-Commerce/Wysiwyg"],
typeDefs,
resolvers,
}
Expose a Homepage in the Graph
Define the schema
Let's assume you have created a Single Custom Type Homepage whose identifier
is homepage. This Custom Type has three fields:
titleof type Titleimageof type Imagetextof type Rich Text
While not mandatory, the best way to expose the Homepage in the Graph is to
model the GraphQL type after the Custom Type. So in schema.gql, you can add:
type Homepage {
title: String
image: String
text: DefaultWysiwyg
}
extend type Query {
homepage: Homepage
}
Implement the resolver
Once you have defined the type in the Graph, you need to implement the
corresponding resolver in resolvers.js to retrieve the homepage Content from
Prismic:
export default {
Query: {
homepage: (root, args, { loaders }) => {
return loaders.Prismic.loadSingle("homepage");
},
},
};
Define the content transform options
Now we want to ensure that the fields are correctly transformed for the
homepage content type. To do that, we need to define the content transform
options for homepage:
import typeDefs from "./schema.gql";
import resolvers from "./resolvers";
export default {
namespace: "my-module",
dependencies: ["Prismic/Core", "Front-Commerce/Wysiwyg"],
typeDefs,
resolvers,
contextEnhancer: ({ loaders }) => {
const { TitleTransformer, RichtextToWysiwygTransformer, ImageTransformer } =
loaders.Prismic.transformers;
loaders.defineContentTransformers("homepage", {
fieldTransformers: {
title: new TitleTransformer(),
image: new ImageTransformer(),
text: new RichtextToWysiwygTransformer(loaders.Wysiwyg),
},
});
return {};
},
};
Image field handling
In this example, without a dedicated resolver, the image field of the
Homepage type is the path to the image of
the main view.
In Prismic, while configuring an Image field in the Custom Type editor, it is
possible to define several views to get the same image under a different format.
Those views can also be exposed in the Graph. For instance, if you have defined
a thumbnail view, it can be exposed in the graph by applying the following
changes. In schema.gql:
type Homepage {
title: String
image: String
+ thumbnail: String
text: DefaultWysiwyg
}
extend type Query {
homepage: Homepage
}
And in the resolver:
export default {
Query: {
homepage: (root, args, { loaders }) => {
return loaders.Prismic.loadSingle("homepage")
},
},
+ Homepage: {
+ thumbnail: (homepageContent) => {
+ return homepageContent.image.thumbnail;
+ }
+ }
};
The
ImageTransformeralso rewrites the image path provided by the Prismic API to use a custom image proxy defined by the module. This path rewrite makes those image path directly usable by Front-Commerce's<Image />component.
In addition, each view carries some metadata like the alternative text or the
image dimensions. The following changes allow to expose the alternative text of
both the thumbnail and the main views:
type Homepage {
title: String
image: String
+ imageAlt: String
thumbnail: String
+ thumbnailAlt: String
text: DefaultWysiwyg
}
extend type Query {
homepage: Homepage
}
In the resolver:
export default {
Query: {
homepage: (root, args, { loaders }) => {
return loaders.Prismic.loadSingle("homepage")
},
},
Homepage: {
+ imageAlt: (homepageContent) => {
+ return homepageContent.image.main.alt;
+ },
thumbnail: (homepageContent) => {
return homepageContent.image.thumbnail;
},
+ thumbnailAlt: (homepageContent) => {
+ return homepageContent.image.thumbnail.alt;
+ },
}
};
Title field handling
In this example, the title is exposed as a plain string in the graph. However,
the TitleTransformer also generates an HTML representation of the field. So if
you need to retrieve the HTML code instead, you can define a custom resolver on
the title field of the Homepage type:
export default {
Query: {
homepage: (root, args, { loaders }) => {
return loaders.Prismic.loadSingle("homepage")
},
},
+ Homepage: {
+ title: (homepageContent) => homepageContent.title.html;
+ }
};
In addition, Title and Rich Text fields are very similar; a Title field can be
seen as a restricted Rich Text field. As a result, the Transformers dedicated to
Rich Text fields can also be used on Title fields. So if you want to expose the
title as a DefaultWysiwyg, you can do the following changes instead. In the
schema.gql:
type Homepage {
- title: String
+ title: DefaultWysiwyg
image: String
text: DefaultWysiwyg
}
extend type Query {
homepage: Homepage
}
And in the module:
import typeDefs from "./schema.gql";
import resolvers from "./resolvers";
export default {
namespace: "my-module",
dependencies: ["Prismic/Core", "Front-Commerce/Wysiwyg"],
typeDefs,
resolvers,
contextEnhancer: ({ loaders }) => {
- const { TitleTransformer, RichtextToWysiwygTransformer, ImageTransformer } = loaders.Prismic.transformers;
+ const { RichtextToWysiwygTransformer, ImageTransformer } = loaders.Prismic.transformers;
loaders.Prismic.defineContentTransformers("homepage", {
fieldTransformers: {
- title: new TitleTransformer(),
+ title: new RichtextToWysiwygTransformer(loaders.Wysiwyg),
image: new ImageTransformer(),
text: new RichtextToWysiwygTransformer(loaders.Wysiwyg),
},
})
return {}
}
}
Expose an article and retrieve it by its uid
Let's assume you have created a Custom Repeatable Type Article which
identifier is article. This Custom Repeatable Type has three fields:
uidof type UID (this field is mandatory to retrieve the article by its identifier)titleof type Rich Textcontentof type Rich Text
Implement the schema
We can model the corresponding GraphQL schema as follows:
type Article {
uid: String
title: DefaultWysiwyg
content: DefaultWysiwyg
}
extend type Query {
article(slug: String!): Article
}
The slug argument represents the value of the uid field.
Implement the resolver
export default {
Query: {
article: (_, { slug }, { loaders }) => {
return loaders.Prismic.loadByUID("article", slug);
},
},
};