Site showcasing, how to model the menu in Kontent.ai and the use this model in the Gatsby application to render a menu and its linked content.
This showcase extends originates from Explicitly modeled navigation approach and adds some Gatsby specific steps.
# In the root folder of this repo
npm install # install all required packages
npm run build # build the latest version of the local packages
# open the /example/navigation folder
cd examples/navigation
npm run develop # runs `gatsby develop` command
Now you could browse the site on http://localhost:8000 and see GraphiQL explorer on http://localhost:8000/___graphql.
This section explains how the content is modeled. You could follow next section of Import the content to your on Kontent.ai project and explore the models by your own.
First of of all it is required to create two content types:
Navigation item
- which will represent an item in the menu of your websiteContent page
- this content type represent ty content you want to display on the website
This content type - Navigation item
- has following structure:
- Title - Text element
- Slug - URL slug element - auto-generated from title
- Subitems - Linked items element - content type limited to
Navigation item
- Content - Linked items - content type limited to contain at most one item to of type
Content page
This content type represent and item in the menu in your website. You could have multiple menus on your site, in that case you could use multiple "root" navigation items to model this situation.
In case you want to link external URL to different domain, it is possible to extend the content type by Text element called i.e. External URL.
This content type - Content page
- has following structure:
- Title - Text element
- Content - Rich text element
This content type is used as a content container, it could be reused across multiple channels.
In this example, there is only one content model holding the content, but you could of course use multiple types for content modeling. All of them then could be allowed in Content element of the Navigation item
content type.
There are two main parts that need to be generated:
- Menu - render the menu component with proper routes
- Pages - register page components under the menu routes
It is required to extend the GraphQL schema of the Navigation item
content type and build up the routes from the Slug elements in Navigation item
- the new field is named url
in the showcase.
The idea is to traverse bottom-up the navigation tree for every Navigation item
to it's parent modeled by Subitems
element and gather it Slug element i.e.:
- from
gatsby-kontent
>for-developers
>why-kontent
- to
/why-kontent/for-developers/gatsby-kontent
This extension is showcased in gatsby-node.js's createSchemaCustomization. This is a similar approach that Wordpress is using
Create a menu component that is using the url
field to build up the simple menu. In the showcase menu component there is a query loading three levels of the menu.
Use the precomputed url
field to programmatically create pages using Gatsby API.
In gatsby-node's createPages live-cycle API to query all Navigation items
and register their then new pages under the route from url
field and pass preffered_language
and item's codename
as a context property to create page base on the template.
The last step is to use contextual data to query content you want to render under specific route. Showcase contain only one type of the generic content item Content page
. For this type it is required to create a template (/templates/content-page.js
).
If you want to check the content in your own project, you could use following guide:
-
Go to app.kontent.ai and create empty project
-
Go to "Project Settings", select API keys and copy
Project ID
-
Install Kontent.ai Backup Manager and import data to newly created project from
kontent-backup.zip
file (place appropriate values forapiKey
andprojectId
arguments):npm install -g @kontent-ai/backup-manager-js kbm --action=restore --apiKey=<Management API key> --projectId=<Project ID> --zipFilename=kontent-backup
-
Go to your Kontent.ai project and publish all the imported items.
This showcase shows the basics for the menu modeling. If you want to take a look to more complex setup you should continue to ondrej.chrastina.dev [source
]. This website is applying more complex approaches.
As mentioned before, the navigation item could be extended by External URL
field. This field is then used instead of url
field.
There are multiple content pages used as the content container. Namely Home page
, Sections page
, Listing page
. These content containers are using different templates when registering the page components under the routes (templates).
One of the content container types is Listing items
, this type allows to select content type(s) that is/are then used to determine what is about to be queried in the page. To model it in Kontent.ai Type selector custom element is used and then in the application. Then when the application is registering the page components ir loads detail items and register them under their own route with detail component template.
If you are using complex and nested menu navigation in combination with Preview URLs you might need to have a way to map the "preview" URL to the one you have built using schema customization because in the context of Preview URLs there is only url slug
, codename
, language
and item ID
, but not the information of other elements, or their relationship.
⚠ Render "preview pages" only in development environment (
NODE_ENV
is set todevelopment
) and for the pages that requires preview to prevent build time performance degradation.
In a nutshell, you want register routes endpoint like i.e. /preview/<LANGUAGE>/<CODENAME>
by hooking to createPages
Gatsby Node API method and use one of the following approaches to map your preview URLs to the publish URLs.
-
- Just use the same construct, that is already used for creating production pages
if(process.env.NODE_ENV === 'development') { createPage({ path: `/preview/page/${contentPage.preferred_language}/${contentPage.system.codename}`, component: require.resolve(`./src/templates/content-page.js`), context: { language: contentPage.preferred_language, codename: contentPage.system.codename, }, }) }
-
Use some React based approach to handle redirection
- Choose one compatible with Gatsby Routing mechanism, like
client-only
routes using@react/router
- Choose one compatible with Gatsby Routing mechanism, like
-
- Mind the description of the action "Server redirects don’t work out of the box".
- Also defining redirects on client side (option
redirectInBrowse
) lead to small delay/blink on development server from 404 to redirected page.