Developing a data source extension
A data source extension makes data available to your website. A data source extension:
Can be configured and influenced from the Studio.
Is available during the server-side rendering phase and immediately after the website loads.
Can be connected simultaneously to multiple Frontend components on the same page by de-duping requests automatically.
In this document, for demonstration purposes, you will create a data source to retrieve data from the Star Wars API and display the information on your website.
Develop a data source extension
To develop a data source extension and connect it to your website, follow these steps:
Create a data source schema
A data source schema specifies the information about the data source and its configuration. The Studio uses this schema to present the available configuration options to the users.
A data source schema requires the following fields:
customDataSourceType
: is required and must comply with the format<vendor>/<identifier>
. You can use your company or project name as the<vendor>
and use a speaking identifier for the data source.name
: specifies how the data source is referenced in the Studio and should be understandable for Studio users. Thecategory
andicon
are specific schema fields for visualization in the Studio.category
: specifies the clustering of the data source in the Studio.icon
: specifies the name of the icon associated with the data source in Studio.schema
: contains a list of configuration sections, each containing some schema fields. For further information on schema fields, see Schemas.
In this example, we create an example/star-wars-movie
data source that exposes a single input field (Movie ID) where a Studio user can enter the ID of a Star Wars movie episode. The API hub passes this configuration to the data source during server-side rendering, and the data source will then fetch information about the selected movie from the Star Wars movie API.
{"customDataSourceType": "example/star-wars-movie","name": "Star Wars movie","category": "Content","icon": "stars","schema": [{"name": "Settings","fields": [{"label": "Movie ID","field": "movieId","type": "string","translatable": false}]}]}
Upload the data source schema to the Studio
To upload the data source schema to the Studio, follow these steps:
From the Studio home page or from the left menu, go to Developer > Data sources.
Click Create schema.
Copy the data source schema you created and paste it into the schema editor.
Click Validate.
If you include the
dataSourceType
in your JSON, you don't need to add it to the required field input.Click Publish.
Implement the data source extension
A data source extension is defined as a function with the config
and context
parameters and returns a value of type DataSourceResult
.
To implement the data source extension, you must register the data source extension with its customDataSourceType
value under the data-sources
key of the default export
in the packages/<project>/backend/index.ts
file. For example, we are using example/star-wars-movie
as the key in the data-sources
object to register our extension.
In this example, we receive the Movie ID configured by the Studio user as the config.configuration.movieId
.
We use this value to create a GraphQL query to filter the list of movies. Then, we perform an HTTP request to the Star Wars movie API using the Axios library and return the received response as dataSourcePayload
.
Executing API calls costs time and affects the performance of your website. Therefore, you should make as few calls as possible and execute them in parallel.
You should always validate the incoming configuration values because the Studio allows users to store configurations even if the required parameters are missing.
import {DataSourceConfiguration,DataSourceContext,DataSourceResult,} from '@frontastic/extension-types';import axios from 'axios';export default {'data-sources': {'example/star-wars-movie': async (config: DataSourceConfiguration,context: DataSourceContext): Promise<DataSourceResult> => {if (!config.configuration.movieId) {return {dataSourcePayload: {ok: false,error: 'Movie ID is missing from the configuration.',},} as DataSourceResult;}return await axios.post<DataSourceResult>('https://swapi-graphql.netlify.app/.netlify/functions/index',{query:'{film(id:"' +config.configuration.movieId +'") {title, episodeID, openingCrawl, releaseDate}}',}).then((response): DataSourceResult => {return {dataSourcePayload: response.data,} as DataSourceResult;}).catch((reason) => {return {dataSourcePayload: {ok: false,error: reason.toString(),},} as DataSourceResult;});},},};
Add preview data for the Studio
To display data source previews in the Studio, you must return a previewPayload
property in the data source response.
The context.isPreview
property of the data source is set to true
when the Studio requests for the data source preview.
You can use this property to conditionally return a previewPayload
property in the response.
The previewPayload
property must be an array of objects, each containing two properties:
title
: the title to display for the item fetched from the data source.image
: the absolute URL of the image to display for the item fetched from the data source.
In this example, we will return the title
of the movie and a URL of an image from Imgur as the image
. To learn more about data source preview in the Studio, see Using the data source filter editor and Component settings.
// code above.then((response): DataSourceResult => {const payloadResult = {dataSourcePayload: response.data,}return !context.isPreview ? payloadResult : {...payloadResult,previewPayload: [{title: response.data.film.title,image: 'https://i.imgur.com/YbxTgoD.jpeg',},],};})// rest of the code...
Add the data source on a page folder
Now you need to add the Star Wars movie data source to the page folder where you want to render the content, then you need to configure the data source filters.
To add the data sources to the page folder and configure the data source filters, follow these steps:
If necessary, create a page folder. Otherwise, from the Studio home page or from the left menu, go to Site builder.
In the page folder list, hold the pointer over the page folder where you want to render the content and click the Settings icon: the Page folder settings dialog opens.
In the Data source section, click + Add data source filter: the list of the available data sources opens. From the list, you can select the Star Wars movie data source. When you select a data source, the data source filter editor opens.
In the Movie ID field, enter the ID of the Star Wars movie. In this example, we enter
ZmlsbXM6MQ==
.Click Save.
Create a Frontend component
Now you need to create a Frontend component that renders the content fetched from the data source. In this example, we create the Frontend component that renders the Star Wars opening crawl.
To create a Frontend component, follow these steps:
Create the Frontend component schemas by uploading the following schemas to the Studio.
Star Wars opening crawl Frontend component schemajson{"tasticType": "example/star-wars-opening-crawl","name": "Star Wars opening crawl","icon": "movie_filter","category": "general","schema": [{"name": "Data source","fields": [{"label": "Star Wars movie","field": "movieData","type": "dataSource","dataSourceType": "example/star-wars-movie"}]}]}In your commercetools Frontend project, add the following
index.tsx
file undertastics/content/example/star-wars-opening-crawl
.index file of the Star Wars opening crawl Frontend componentTypeScript Reactimport React from 'react';const StarWarsOpeningCrawl = ({ data }) => {return (<marquee direction="up" style={{ whiteSpace: 'pre-wrap' }}>{data.movieData.dataSource.data.film.openingCrawl}</marquee>);};export default StarWarsOpeningCrawl;Register the
index.tsx
file for theexample/star-wars-opening-crawl
Frontend component in theindex.tsx
file underfrontastic/tastics
.Register StarWarsOpeningCrawl Frontend componentTypeScript Reactexport const tastics = {...'commercetools/ui/checkout': Checkout,'commercetools/ui/thank-you': ThankYou,'commercetools/ui/cart': Cart,'commercetools/ui/footer': Footer,'commercetools/ui/header': Header,'commercetools/ui/content/tile': Tile,'commercetools/ui/content/spacer': Spacer,'commercetools/ui/content/showcase': Showcase,'example/star-wars-opening-crawl': StarWarsOpeningCrawl,...default: NotFound,};
Add Frontend component to the page version
Finally, you must add the Frontend components you created to the page version where you want to render the content. Thus, the data retrieved from the data source is rendered on the page version through the Frontend component.
To add the Frontend components to the page version, follow these steps:
If necessary, create a page version. Otherwise, from the Studio home page or from the left menu, go to Site builder.
Use the page folder list and the status sections to navigate to the page version where you want to add the Frontend component. Then, hold the pointer over the page version and click the Edit icon: the page builder opens.
- Edit the layout of the page version as you wish. In this example, we add a 1/1 layout element to the MAIN layout section.
Use the Components pane to find the Frontend component to add. Then, drag it to the layout element. In this example, we drag the Star Wars opening crawl Frontend component to the 1/1 layout element.
Select the Frontend component. Then, in Component settings > Content select the data source to associate to the Frontend component. In this example, we select Star Wars movie.
Preview and save your changes. The Star Wars opening crawl is now rendered on your commercetools Frontend website.
Check the data source response
To check the data source response via HTTP API, you must have completed the previous steps. You must therefore have a page folder that is associated with the data source and that contains a page version. This page version must contain a Frontend component associated with the data source.
To check the response, use an HTTP client such as, Postman, HTTPie, or cURL.
From the HTTP client, send a GET
request to https://EXTENSION_RUNNER_HOSTNAME/frontastic/page
. The request must contain the following headers and query parameters.
- Headers:
Accept
:application/json
Commercetools-Frontend-Extension-Version
: your Studio developer username.
- Query parameters:
path
: the path to the page folder you created. For example,/your-page-folder
.locale
: a locale of your commercetools Frontend project. For example,en_US
.
For information on the Commercetools-Frontend-Extension-Version
header and the extension runner hostname, see Main development concepts.
curl -X 'GET' -H 'Accept: application/json' -H 'Commercetools-Frontend-Extension-Version: STUDIO_DEVELOPER_USERNAME' 'https://EXTENSION_RUNNER_HOSTNAME/frontastic/page?path=/your-page-folder&locale=en_US'
The response body will be a JSON payload with a data
key representing the page folder data, including the dataSources.dataSourcePayload
property that is passed to the Frontend component connected to the data source.
{"data": {"_type": "Frontastic\\Catwalk\\NextJsBundle\\Domain\\PageViewData","dataSources": {"ac8a8700-6a84-4c02-9160-4fc2fced3fe9": {"dataSourcePayload": {"data": {"film": {"title": "A New Hope","episodeID": 4,"openingCrawl": "It is a period of civil war.\r\nRebel spaceships, striking\r\nfrom a hidden base, have won\r\ntheir first victory against\r\nthe evil Galactic Empire.\r\n\r\nDuring the battle, Rebel\r\nspies managed to steal secret\r\nplans to the Empire's\r\nultimate weapon, the DEATH\r\nSTAR, an armored space\r\nstation with enough power\r\nto destroy an entire planet.\r\n\r\nPursued by the Empire's\r\nsinister agents, Princess\r\nLeia races home aboard her\r\nstarship, custodian of the\r\nstolen plans that can save her\r\npeople and restore\r\nfreedom to the galaxy....","releaseDate": "1977-05-25"}}}}}}...}