Gatsby source plugin for Kentico Kontent
Description
Source plugin for Kentico Kontent REST Delivery API.
This repo contains a Gatsby (v2) source plugin that retrieves data from the Kentico Kontent REST Delivery API.
How to install
Gatsby documentation uses npm
for installation. This is the recommended approach for plugins as well.
This plugin does not need to use yarn
, if want to use it in you project, see the documentation for switching package managers.
-
Install the @kentico/gatsby-source-kontent NPM package.
npm install --save @kentico/gatsby-source-kontent
-
Configure the plugin in gatsby-config.js
file.
module.exports = {
plugins: [
{
resolve: '@kentico/gatsby-source-kontent',
options: {
projectId: '<ProjectID>',
languageCodenames: [
'default',
],
},
},
],
};
Available options
-
projectId
* - <string
> Project ID from Project settings -> API keys
-
languageCodenames
* - <string[]
> array of language codenames that defines what languages a configured for the project - the first one is considered as the default one. Initial "Getting started" project has configured just one language default
.
-
includeTaxonomies
- <boolean
> include taxonomies to GraphQL model. Turned off by default.
-
includeTypes
- <boolean
> include types to GraphQL model. Turned off by default.
-
authorizationKey
- <string
> For preview/secured API key - depends on usePreviewUrl
config. Consider using dotenv package for storing keys securely in environment variables.
-
usePreviewUrl
- <boolean
> when true
, "preview-deliver.kontent.ai
" used as primary domain for data source. Turned off by default.
-
proxy
:
deliveryDomain
- <string
> Base url used for all requests. Defaults to deliver.kontent.ai
.previewDeliveryDomain
- <string
> Base url used for preview requests. Defaults to preview-deliver.kontent.ai
.
-
includeRawContent
- <boolean
> allows to include internal.content
property as a part fo the GraphQL model. Turned off by default.
* required property
Since the plugin is using Gatsby Reporter for error logging. You could turn on --verbose
option to see the whole error object. Be careful with these options, the output log could contain some sensitive data such as authorizationKey
.
Examples of usage
An example showing how to include this plugin in a site's gatsby-config.js
file.
module.exports = {
plugins: [
{
resolve: '@kentico/gatsby-source-kontent',
options: {
projectId: '09fc0115-dd4d-00c7-5bd9-5f73836aee81',
languageCodenames: [
'default',
'Another_language',
],
includeTaxonomies: true,
includeTypes: true,
usePreviewUrl: true,
authorizationKey: '<API KEY>',
includeRawContent: true,
proxy: {
deliveryDomain: 'custom.delivery.kontent.my-proxy.com',
previewDeliveryDomain: "custom.preview.delivery.kontent.my-proxy.com"
}
},
},
],
};
The plugin creates GraphQL nodes for all Kentico Kontent taxonomies, content types, content items language variants.
The queries start with kontentTaxonomy
, kontentType
, or kontentItem
prefix (respectively allKontentTaxonomy
, allKontentType
, or allKontentItem
) and their type is kontent_taxonomy_X
, kontent_type_X
, or kontent_item_X
where X
is a codename of the taxonomy
, type
, or item
.
Look at the How to query for data section for example queries.
GraphQL nodes produced by the source plugin provide the same structure as Kontent Delivery REST API, but there are alternations for better usability, you could find more detailed description in Delivery API alternations section
Learning Resources
To see upgrade instructions see Upgrade section.
For more developer resources, visit the Kentico Kontent Docs.
Delivery API alternations
Some of the data from Kontent Delivery API requires to be altered or extended to be usable in Gatsby. There is a list of them with its description.
Preferred language
Besides of system.language
every Kontent item node contains the property preferred_language
to distinguish which language version it represents. Using this property, it is easy to distinguish whether the language fallback is used. When preferred_language
is not the same as system.language
, Kontent item was not translated to preferred_language
and the delivery API returned fallback language (system.language
).
Linked items as links
Each linked items element in linked items element as well as in rich text element is using Gatsby GraphQL node references that can be used to traverse to the nodes linked through the use of the Linked items element.
The resolution is using the createFieldExtension
called languageLink
that is resolving the codenames. Embedded @link
extension is not used because the links have to be resolved by preferred_language
as well as system.codename
equality and embedded link resolution allow using only one field to make the links out of the box.
Linked Items element
query PersonQuery {
allKontentItemPerson {
nodes {
elements {
friends {
value {
... on kontent_item_person {
id
elements {
name_and_surname {
value
}
}
}
}
}
}
}
}
}
Rich text element
query PersonQuery {
allKontentItemPerson {
nodes {
elements {
bio {
modular_content { // inline linked items as well as content components
... on kontent_item_website {
id
elements {
name {
value
}
url {
value
}
}
}
}
value
}
}
}
}
}
Rich text images and links
Kontent REST API returns images and links for Rich Text element in the form of the object, not as an array:
{
"bio": {
"type": "rich_text",
"name": "Bio",
"images": {
"fcf07d43-46d4-46ef-a58d-c7bf7a4aecb1": {
"image_id": "fcf07d43-46d4-46ef-a58d-c7bf7a4aecb1",
"description": null,
"url": "https://assets-us-01.kc-usercontent.com:443/09fc0115-dd4d-00c7-5bd9-5f73836aee81/0faa87b4-9e1e-41b8-8b38-c107cbb35147/2.jpg",
"width": 1600,
"height": 1065
}
},
"links": {
"59002186-1886-48f3-b8ba-6f053b5cf777": {
"codename": "developer_community_site",
"type": "website",
"url_slug": ""
}
},
"modular_content": [],
"value": "..."
}
}
This wrapper transforms these objects into the arrays. In case of an image the ID of the image is already stored there, in case of link, the id of a link is moved to linked_id
property. The query then looks like:
query PersonQuery {
allKontentItemPerson {
nodes {
elements {
bio {
images {
image_id
url
description
height
width
}
links {
codename
type
url_slug
link_id
}
}
}
}
}
}
Types' elements
property
Elements property is transformed from object to array.
This is the "Website" type sample. As you can see there is element
property, which is an object in Kontent delivery REST API.
{
"system": {
"id": "aeabe925-9221-4fb2-bc3a-2a91abc904fd",
"name": "Website",
"codename": "website",
"last_modified": "2019-04-01T18:33:45.0353591Z"
},
"elements": {
"url": {
"type": "text",
"name": "URL"
},
"name": {
"type": "text",
"name": "Name"
},
"description": {
"type": "rich_text",
"name": "Description"
}
}
}
And here is the example how the source plugin transforms the data.
Query
{
kontentType(system: { name: { eq: "Website" } }) {
system {
codename
id
last_modified
name
}
elements {
name
codename
type
}
}
}
Result
{
"data": {
"kontentType": {
"system": {
"codename": "website",
"id": "aeabe925-9221-4fb2-bc3a-2a91abc904fd",
"last_modified": "2019-04-01T18:33:45.0353591Z",
"name": "Website"
},
"elements": [
{
"name": "URL",
"codename": "url",
"type": "text"
},
{
"name": "Name",
"codename": "name",
"type": "text"
},
{
"name": "Description",
"codename": "description",
"type": "rich_text"
}
]
}
}
}
How to query for data
This section should help you with the first queries. For further exploring it is recommended to use GraphiQL explorer available in gatsby development environment]. If you are using developer environment for the source plugin development, you could experiment according to the How to develop locally section
Querying Kontent Items
Example is showcasing how to query type article
.
For rich text resolution resolution see Rich text element component.
For url slug resolution see Rich text element component.
query ArticleQueries {
allKontentItemArticle(filter: { preferred_language: { eq: "en-US" } }) {
nodes {
elements {
title {
value
}
content {
value
images {
image_id
url
description
}
links {
link_id
url_slug
codename
type
}
modular_content {
... on kontent_item_author {
id
elements {
name {
value
}
avatar_image {
value {
url
description
name
}
}
}
}
}
}
tags {
value {
... on kontent_item_tag {
elements {
title {
value
}
slug {
value
}
}
}
}
}
}
}
}
}
Querying Kontent Types
To query content types it is required to opt-in this in plugin configuration by using includeTypes
option in the configuration..
query Types {
allKontentType {
nodes {
Type: system {
name
codename
}
elements {
name
codename
type
options {
codename
name
}
taxonomy_group
}
}
}
}
Querying Kontent Taxonomies
To query content types it is required to opt-in this in plugin configuration by using includeTypes
option in the configuration..
query Taxonomies {
allKontentTaxonomy {
nodes {
system {
name
codename
}
terms {
codename
name
terms {
codename
name
}
}
}
}
}
How to integrate with Gatsby Cloud
If you choose to maintain you Gatsby site on Gatsby Cloud, use will need to register two webhooks from Kentico Kontent Kontent to Gatsby Cloud. Follow the tutorial for more information. All webhook notifications that are not mentioned in the tutorial will be ignored by the plugin.
Please note that change in taxonomies or content types require manual rebuild of the site, because these structural data affects GraphQL schema.
How to run tests
The package is using Jest framework for testing.
To run all tests, there is an npm script prepared.
yarn test
How to develop locally
Use a development site in development mode. And start watch mode for this repository.
yarn watch
To run complete development environment, follow the debug section the master readme
Tracking usage
The package is including tracking header to the requests to Kentico Kontent, which helps to identify the adoption of the source plugin and helps to analyze what happened in case of error.
If you think that tracking should be optional feel free to raise the feature or pull request.
Further information
To see upgrade instructions see Upgrade section.
For more developer resources, visit the Kentico Kontent Docs.
Running projects
Guides and blog posts
Previous versions
How to contribute
Check out the contributing page to see the best places for file issues, to start discussions, and begin contributing.