> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://contentful.com/developers/docs/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://contentful.com/_mcp/server. # Create an app to support Native external references > A tutorial on how to create an app supporting Native external references ## Overview Contentful supports external content integration through the [App Framework](/extensibility/app-framework). While the [App Marketplace](https://www.contentful.com/marketplace/) offers ready-made solutions tailored for systems like [Shopify](https://www.contentful.com/help/external-references-with-shopify/) or [commercetools](https://www.contentful.com/help/external-references-with-commercetools/), connecting to other systems requires developing custom frontend apps with bespoke implementation. To overcome these challenges, we offer a more streamlined and cohesive approach to linking third-party systems through existing content model Reference Fields. This upgraded version of fields is referred to as **Native external references**. With Native external references you can connect any third-party system to existing reference fields. > **Info** > > **NOTE:** Native external references are only available on specific plans. For more information about feature availability, [reach out](https://www.contentful.com/contact/sales/) to your Sales representative. ## Prerequisites * We are assuming you are familiar with the following concepts: * [App Framework](/extensibility/app-framework), including [App Definition](/extensibility/app-framework/app-definition) and [App Installation](/extensibility/app-framework/app-installation) * [Functions](/extensibility/app-framework/functions) * Your organization is on a paid plan (except Lite). * The space where you will install the application has the [Orchestration](https://www.contentful.com/help/enable-spaces-for-orchestration/) feature set enabled. * Your system has the latest LTS version of [Node.js](https://nodejs.org/en/) installed. ## Example For the purpose of this example, we will be connecting to the [MockShop](https://mock.shop/) external system and resolving its data through the Contentful GraphQL API and the Content Delivery API (CDA). With Native external references we introduce the following new entity types that allow us to model the data from third-party systems in Contentful: * `Resource Provider` - a third-party system that provides resources. Each provider can have multiple resource types. In our example: a `MockShop` provider. * `Resource Type` - a specific type of resource (not the resource itself) that is provided by a resource provider. In our example: `Product`. ## Instructions to create and run the app ### Copy the example To get started with your application, you need to make a local copy of the example code by running the following command in your terminal: ```bash npx create-contentful-app@latest --example native-external-references-mockshop ``` > **Info** > > **Important:** Make sure you replace `<name-of-your-app>` with the name of your choice. Once the process finishes, navigate to the directory that was created by running this command: ```bash cd ``` ### Create a custom app definition To see your app within Contentful, you must first set it up. To do that, we will create an app definition, which is an entity that represents an app in Contentful and stores general information about it. To create the app definition, run this command: ```bash npm run create-app-definition ``` You will need to answer the following questions in the terminal when prompted. Feel free to proceed with the default options provided. 1. **Name of your application**. This is how your app will be named and it will be displayed in a few places throughout the UI. The default is the name of the folder you created. 2. **Select where your app can be rendered**. This shows potential [app locations](/extensibility/app-framework/locations) where an app can be rendered within the Contentful web app. We don't need to configure any app locations in this example. Simply press **Enter** to skip setting them up. 3. **Contentful CMA endpoint URL**. This refers to the URL used to interact with Contentful's Management APIs. In most cases the default CMA URL should be selected. For EU data residency, `api.eu.contentful.com` should be used instead of the default. 4. **App Parameters**. Parameters can be used to set default values or define custom validation rules for the app configuration. We won't define any in this example, but might be helpful for your use-case, for instance to configure an API access token parameter. For more details see the [App Parameters](/extensibility/app-framework/app-parameters) documentation. * Opt for **N** to skip the process of defining the parameters. 5. The next steps will lead you through the process of providing a Contentful access token to the application and specifying the organization to which the application should be assigned. > **Info** > > **NOTE:** Make sure the organization ID you select here is that of the organization that has access to the Native external references feature. You now have a basic application that can be enriched with additional information that will enable the example project you downloaded to function properly. ### Build and upload the app After creating the app definition, we can take care of uploading the code by running these commands: ```bash npm run build npm run upload ``` The interactive CLI will guide you through the process of providing the necessary details, such as a Contentful Management API (CMA) endpoint URL. The default value is `api.contentful.com`, but you can specify a different one if needed. Select **Yes** when prompted if you'd like to activate the bundle after upload. > **Info** > > **Important:** EU data residency users should use `api.eu.contentful.com` instead of the default. ## Create resource entities Executing the provided command in your terminal will generate resource entities within the app definition, which are described in more detail under the [Set up ResourceEntities](#set-up-resourceentities) step. ```bash npm run create-resource-entities ``` This will tell Contentful that we want to connect to [`MockShop`](https://mock.shop) via the function we uploaded under the [Build and upload the app](#build-and-upload-the-app) step and that the same function can provide `MockShop:Product` *Resource Types*. > **Info** > > **NOTE:** Configure the environment variables mentioned under the [npm run upload-ci](/extensibility/app-framework/native-external-references-example-tutorial#available-scripts) section before running these scripts. The `create-resource-entities` script generates new entities within the system, and prints out a minimal log when the operation has succeeded. If you would like to list all the previously created entities, you can utilize a similar script that prints out more verbose details: `npm run show-resource-entities`. If the entities were incorrectly created, you can run `npm run delete-resource-entities` to delete the incorrect entities and try again. ### Install the app * After you have successfully uploaded your app, install it into an existing space by running the `npm run install-app` command. * Select the space with the [Orchestration](https://www.contentful.com/help/enable-spaces-for-orchestration/) feature enabled and environment in which you would prefer to install the example app from the dialog that is displayed: ![Installation destination dialog](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/9ec02b1f291a9ade2ce91c6a1c7d607396768c2647b35cb81eb177df12f963b6/docs/assets/apps/native-external-references-example-tutorial/install-target-environment-selection.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIA6KXJSKKNFOCF7G4B%2F20260929%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260929T234736Z&X-Amz-Expires=604800&X-Amz-Signature=14aac91d3d993be27fafafad3c97755baed6b9ce8751bf9474a24c3b80986db6&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject) You will have to grant access to the space the app will be installed in. Your example app is now configured and installed. ### Configure your content model To render content from MockShop, we must first create and configure the content model. To create and configure the content model: 1. Open the Contentful web app and navigate to the space where you have installed the MockShop app. 2. Navigate to the "Content model" tab, and click **Create content type**. The "Create new content type" modal is displayed. 3. Enter your preferred name, and click **Create**. The content type is created. 4. Click **Add field** and select **Reference** as the field type. The "Add field modal" is displayed. 5. Enter a field name, in our case **Product**, and select the **Different spaces and external sources** option. 6. Select the **Type**. You can choose between having a single link, **One reference**, or a group of links, **Many references**. 7. Click **Add and configure**. The field configuration page is displayed. 8. Under the "Validation" section, specify the sources that are allowed as potential sources of data in the field being configured. 9. Set the **Source** dropdown field to **MockShop**. Once selected, the **Entity type** dropdown allows you to choose the **MockShop: Product** we previously configured when we created the [resource entities](#create-resource-entities). > **Info** > > **NOTE:** If you choose **Contentful** as the source, you can combine cross-space Contentful resources with MockShop entities when dealing with fields that have multiple references. 10. Click **Confirm**. The field is added to your content model. 11. Once you are done configuring your fields, click **Save**. ### See your app in action Now that the content model has been configured to display resources from MockShop, an entry can be created to incorporate data from particular external sources. To create an entry: 1. Open the Contentful web app and navigate to the space where you configured the content model in the previous step. 2. Navigate to the "Content" tab and click **Add entry**. 3. Select the content type you previously created with the configured field for linking to external sources. The entry editor is displayed. 4. Under **Product**, click **Add existing content**. The "Add content" modal is displayed. 5. You can search through the available content from the external provider, and select the one you want. The function built in our app fetches this content from **MockShop**. * If your field is a single reference field, select one of the entries. The "Add content" modal closes itself automatically. * For multiple references fields, you can select as many entries as needed. Click **Add** once you are satisfied with your choices. > **Info** > > **NOTE:** > If you are using a field with multiple references, you are not limited to only one source. You can combine cross-space links with resources from **MockShop**. 6. Your first entry with Native external references is ready! Click **Publish** once you are done with the editing. 7. Access the published entry data using the [GraphiQL app](https://www.contentful.com/marketplace/graphiql/) and the [CDA](/references/content-delivery-api/overview) to query it. ## Code structure ### Functions The example app is using [Functions](/extensibility/app-framework/functions) to provide a connection between Contentful and the MockShop API. In the `functions/mockShop.ts` file, we are defining the following events: * `resources.search` - retrieval of specific content based on search queries. * `resources.lookup` - retrieval of specific content based on URNs (IDs). * `graphql.resourcetype.mapping` - retrieval of resource type mappings, which determines what fields map to an external type. **Only required for GraphQL API resolution.** * `graphql.query` - handles GraphQL queries for the external third-party API. **Only required for GraphQL API resolution.** > **Info** > > The `graphql.resourcetype.mapping` and `graphql.query` handlers are only needed for GraphQL API resolution. CDA resolution requires only `resources.search` and `resources.lookup` which allows querying NER data by setting the `externalReferences=*` query parameter. See [CDA documentation](/references/content-delivery-api/overview). ### App manifest The app manifest, located in the root of the project as `contentful-app-manifest.json`, describes the app and its capabilities. It contains a `functions` property, which is an array of functions the app can run. The function properties are: * `id`: The *id* of the Function. * `name`: A readable name for the Function. * `description`: A brief description of the Function. * `path`: This is the path to the transpiled source file of the Function in your bundle, exposing a `handler` function * `entryFile`: Path pointing to the source file of the Function. Exposing a `handler` function. * `allowNetworks`: A list of endpoints the Function should be allowed to connect to, this is a security feature to prevent unauthorized access to your network. * `accepts`: An array of event types the Function can handle, which have an effect on where the functions can be used within Contentful. In this case we configure these event types: \[`resources.search`, `resources.lookup` `graphql.resourcetype.mapping`,`graphql.query`]. ### Set up ResourceEntities All ResourceEntities (such as the Resource Provider and various Resource Entities) are created and managed via the utility code in `src/tools`. These helper methods allow you to: * `create-resource-entities.ts` - Create new ResourceEntities. * `delete-resource-entities.ts` - Delete ResourceEntities. * `show-resource-entities.ts` - Show configured ResourceEntities. You can customize the ResourceEntities located in `src/tools/entities` according to your specific requirements using these helper methods. ### Property mapping `Resource Type Mappings` are used to define how a third-party schema, such as an external GraphQL type, maps to a Contentful `ResourceLink` entry. This allows Contentful to understand how to reference and display your external resource data in your Contentful entries. For example, if your external type is `Product` and contains the `id`, `name`, or `price` fields, you can configure the mapping located in `functions/mockShop.ts` so that all the fields in the `product` type are connected to the corresponding reference field in Contentful. A typical resource type mapping response looks like this: ``` { "resourceTypes": [ { "resourceTypeId": "MockShop:Product", "graphQLOutputType": "Product", "graphQLQueryField": "product", "graphQLQueryArguments": { "id": "/urn" } }, ] } ``` The `graphQLQueryArguments` field supports nested objects, allowing for more complex query structures such as: ``` { "graphQLQueryArguments": { "where": { "id": "/urn" } } } ``` ## Available scripts In the project directory, you can run: #### `npm start` Creates or updates your app definition in Contentful and runs the app in development mode. Open your app to view it in the browser. The page will reload if you make edits. You will also see any lint errors in the console. #### `npm run build` Builds the app for production to the `build` folder. It correctly bundles React in production mode and optimizes the build for the best performance. The build is minified and the filenames include the hashes. Your app is ready to be deployed! #### `npm run upload` Uploads the build folder to Contentful and creates a bundle that is automatically activated. The command guides you through the deployment process and asks for all required arguments. For more information about the deployment process, see the [Deploy with Contentful](/extensibility/app-framework/create-contentful-app#deploy-with-contentful) section. #### `npm run upload-ci` Similar to `npm run upload`, this command will upload your app to Contentful and activate it. The only difference is that with this command, all required arguments are read from the environment variables (e.g., when you add the upload command to your CI pipeline). For this command to work, the following environment variables must be set: * `CONTENTFUL_ORG_ID` - The ID of your organization. * `CONTENTFUL_APP_DEF_ID` - The ID of the app to which to add the bundle. * `CONTENTFUL_ACCESS_TOKEN` - A personal [access token](/references/content-management-api/overview). * `HOST` - Required for EU data residency and used in `npm run create-resource-entities`. #### `npm run open-settings` Opens the settings in the Contentful web app so that you can use the UI to change the settings of an [App Definition](/extensibility/app-framework/app-definition). #### `npm run install-app` Opens a dialog to select the space and environment where the app associated with the given [App Definition](/extensibility/app-framework/app-definition) should be installed. #### `npm run create-app-definition` An interactive CLI that will prompt you to provide necessary details to create an [App Definition](/extensibility/app-framework/app-definition). #### `npm run create-resource-entities` A script that reads the `entities` folder and creates new entities within the system. It will print out a minimal log when the operation has succeeded. #### `npm run show-resource-entities` A script that lists all the previously created entities. It will print out more verbose details about the entities. #### `npm run delete-resource-entities` A script that deletes previously created entities. > A tutorial on how to create an app supporting Native external references