> 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/developers/docs/_mcp/server.

# Create a custom app

> An introduction to building apps for Contentful | Install an app to a space | Choose content types for your app to interact with

#### To go straight to app building, try out our quickstart guide.

Follow the steps below to get your app up and running almost immediately. For detailed explanations on a specific step, click the questionmark icon.

**Set up project** [?](#setup)

1. Run

```bash
npx create-contentful-app my-first-app
```

2. Select **blank template**.
3. Select **JavaScript**.
4. Wait for `create-contentful-app` to finish generating your project.

**Start development server**

1. Run

```bash
cd my-first-app
```

2. Run

```bash
npm run start
```

**Open file**

* Open `src/locations/Sidebar.jsx` in your editor

**Replace contents** [?](#add-the-reading-time-method-to-our-sidebar-component)

Replace the contents of the file with the following code snippet:

```js
import React, { useState, useEffect } from 'react';
import { List, ListItem, Note } from '@contentful/f36-components';
import { useSDK } from '@contentful/react-apps-toolkit';

const CONTENT_FIELD_ID = 'body';
const WORDS_PER_MINUTE = 200;

const Sidebar = () => {
  const sdk = useSDK();

  const contentField = sdk.entry.fields[CONTENT_FIELD_ID];
  const [blogText, setBlogText] = useState(contentField.getValue());

  // Listen for onChange events and update the value
  useEffect(() => {
    const detach = contentField.onValueChanged((value) => {
      setBlogText(value);
    });
    return () => detach();
  }, [contentField]);

  const readingTime = (text) => {
    const wordCount = text.split(' ').length;
    const minutes = Math.ceil(wordCount / WORDS_PER_MINUTE);
    return {
      words: wordCount,
      text: `${minutes} min read`,
    };
  };

  // Calculate the metrics based on the new value
  const stats = readingTime(blogText || '');

  // Render the metrics with Forma36 components
  return (
    <>
      <Note style={{ marginBottom: '12px' }}>
        Metrics for your blog post:
        <List style={{ marginTop: '12px' }}>
          <ListItem>Word count: {stats.words}</ListItem>
          <ListItem>Reading time: {stats.text}</ListItem>
        </List>
      </Note>
    </>
  );
};

export default Sidebar;
```

**Create your app definition** [?](#create-your-app-definition)

1. [Go to the management view](https://app.contentful.com/deeplink?link=app-definition-list), navigate to "Apps" and click "Create App"

2) Enter "Blog Post Metrics" in the **Name** field.
3) Enter `http://localhost:3000` under "Frontend" area.
4) Check **Entry Sidebar** under the "Locations" area.
5) Click **Save**.

**Install your app to a space** [?](#install-your-app-to-a-space)

1. In the [Contentful web app](https://app.contentful.com/), navigate to the space in which you want to install the app.
2. Click the **Apps** tab and select **Custom apps**.
3. Click on the actions menu of your app and select **Install**.
   ![Install app 2](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/0b2ce8cf466ef7cb92db380c170c1b1945350a38d42cbcb591a31736f1b34834/docs/assets/apps/install-app-2.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=20260929T234720Z&X-Amz-Expires=604800&X-Amz-Signature=5287845b9b6b59e822af29311c8e6862d9b9ae12da48fdde0b215335e180147b&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)
4. In the "Manage app access" window, click **Authorize access**.

**Assign your app to a content type** [?](#assign-your-app-to-a-content-type)

1. In the [Contentful web app](https://app.contentful.com/), go to the **Content model** tab and click the "**Blog post**" content type.
2. Go to the **Sidebar** tab.
   ![Install app 5](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/ce5397fd5b9d0739cdf04337292b8463de8f058a865f0725350a761a9aecc489/docs/assets/apps/install-app-5.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=20260929T234720Z&X-Amz-Expires=604800&X-Amz-Signature=269b31b39eb2e5a0ed4376677b2faed981667ce985022cf66fcea0c58a4065c3&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)
3. Click the **+** button in the "Blog Post Metrics" card.
4. Click **Save** to apply changes to the content type.

**See your app in action** [?](#seeyourappinaction)

Your app is built. To see it in action, [go to the **Content** tab](https://app.contentful.com/deeplink?link=content) and create an entry with the content type **Blog post**. You can see your app in the entry editor sidebar.

![Sidebar Content Type](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/380acac3f9058ba3998c153d8aede54afa2894c2eb86d55385458e6b80c7fa80/docs/assets/apps/sidebar-app-in-action.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=20260929T234720Z&X-Amz-Expires=604800&X-Amz-Signature=1c748533f3b5720fe6f201dfc35cffde7bb399d1954a75691bdef8662b8a3b93&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)

## The example app you are about to build

In this tutorial, we use an example of a custom app called **Blog Post Metrics** that provides the editors with word count and reading time indicator. These metrics are set to be displayed in the entry editor sidebar for a "Blog post" content type:

> **Info**
>
> The full example app code can be downloaded from["Blog Post Metrics" app reference](https://github.com/contentful/apps/tree/master/examples/blog-post-metrics).

## Prerequisites

### Setup

* The latest LTS version of [Node.js](https://nodejs.org/en/) installed on your machine. If you don't have `Node.js` installed, you can download it [here](https://nodejs.org/en/download/).
* Be logged in to your Contentful account and have a Contentful space. If you don't have an account, [sign up](https://www.contentful.com/sign-up/) for it.
* Have a content type "Blog post" set up with fields of types "Text" and "Long text". To learn how to create a content type, refer to [Add a content type](https://www.contentful.com/help/adding-a-content-model/).

> **Info**
>
> Make sure you name your "Long text" field "Body" so it has a field ID "body".

### Knowledge

* Read and write JavaScript.
* Be familiar with basic React.
* Be familiar with [Content modeling](https://www.contentful.com/help/content-modelling-basics/).

## Create your project

To create a project for your app:

1. In your terminal, run the following command:

```bash
npx create-contentful-app my-first-app
```

> **Info**
>
> To see all the available options of `create-contentful-app` CLI tool, check [Create Contentful app reference](https://github.com/contentful/create-contentful-app/blob/master/packages/contentful--create-contentful-app/README.md).

After some time the script is ready and will ask you a couple of questions.

2. Select **blank template**.

3. Select the preferred programming language - either **TypeScript** or **JavaScript**.

The `create-contentful-app` CLI tool is initializing your new project.

4. Navigate to the newly created folder and start the app by running the following command:

```bash
cd my-first-app
npm run start
```

Your app is hosted on `http://localhost:3000`. But before we can use it we need to connect this to the Contentful web app which we will do in a later step

## Retrieve, calculate and display metrics in your app

In this subtopic, we explain how to set up the "Blog Post Metrics" app to retrieve and calculate metrics and display it to users in an entry.
Our example "Blog Post Metrics" app is intended to run in the "Entry sidebar" location, this is why we edit `src/locations/Sidebar.tsx`. This file represents the sidebar location in the Contentful web app.

> **Info**
>
> The app location is defined in [Create your app definitions](#create-your-app-definition) step of this tutorial.

> **Info**
>
> For more details about the app locations, see [App locations](/extensibility/app-framework/locations).

### Interact with the data in the Contentful web app

In this step, we set up our "Blog Post Metrics" app to listen to the changes in an entry field of the Contentful web app using the App SDK. To interact with data in Contentful, we use the `useSDK` hook.

> **Info**
>
> To interact with the Contentful web app, we use a subset of the App SDK methods. To learn about all App SDK methods, see [App SDK reference documentation](/extensibility/app-framework/sdk).

To retrieve a value from a field for further metrics calculation:

1. Open `src/locations/Sidebar.tsx`
2. Copy the following code:

#### JavaScript

```js
import React, { useState } from 'react';
import { Paragraph } from '@contentful/f36-components';
import { useSDK } from '@contentful/react-apps-toolkit';

const CONTENT_FIELD_ID = 'body';

const Sidebar = () => {
  // The sdk allows us to interact with the Contentful web app
  const sdk = useSDK();

  // With the field ID we can reference individual fields from an entry
  const contentField = sdk.entry.fields[CONTENT_FIELD_ID];

  // Get the current value from the blog post field and store it in React state
  const [blogText, setBlogText] = useState(contentField.getValue());

  return <Paragraph>Hello Sidebar Component</Paragraph>;
};

export default Sidebar;
```

#### TypeScript

```typescript
import React, { useState } from 'react';
import { Paragraph } from '@contentful/f36-components';
import { SidebarAppSDK } from '@contentful/app-sdk';
import { useSDK } from '@contentful/react-apps-toolkit';

const CONTENT_FIELD_ID = 'body';

const Sidebar = () => {
  // The sdk allows us to interact with the Contentful web app
  const sdk = useSDK<SidebarAppSDK>();

  // With the field ID we can reference individual fields from an entry
  const contentField = sdk.entry.fields[CONTENT_FIELD_ID];

  // Get the current value from the blog post field and store it in React state
  const [blogText, setBlogText] = useState(contentField.getValue());

  return <Paragraph>Hello Sidebar Component</Paragraph>;
};

export default Sidebar;
```

In the component above, the following fields are used:

* `sdk.entry.fields` — An object that holds all the fields that are in an entry.
* `fieldId` — An individual ID of a field that is defined for the app to listen to. In our example, the field ID is `body` as we specified it when creating our content type.

  \


  Use the `getValue` method to retrieve the current value from the field.

Additionally, the following methods and/or data can be used:

* `onChange` — Listen to the events from the field to calculate the wireframe metrics as soon as a user starts entering text in a "Blog post" entry.
* [`field API`](/extensibility/app-framework/sdk#field) — Leverage it to listen for value changes the app needs. It is provided by `useSDK`-hook.
* `onValueChanged` — Use this method to listen for any content updates on the landing page.
* `readingTime` — Call this method to take the value and calculate our desired metrics. The method is created in [Add the reading-time method to our Sidebar component](#add-the-reading-time-method-to-our-sidebar-component) step of this tutorial.

### Add metrics calculation to your app

In this step, we set up the blog post to be provided with the word count and the reading time metrics. To calculate those, run the following function:

#### JavaScript

```js
const readingTime = (text) => {
  const wordCount = text.split(' ').length;
  const minutes = Math.ceil(wordCount / WORDS_PER_MINUTE);
  return {
    words: wordCount,
    text: `${minutes} min read`,
  };
};
```

#### TypeScript

```typescript
const readingTime = (text: string): { words: number; text: string } => {
  const wordCount = text.split(' ').length;
  const minutes = Math.ceil(wordCount / WORDS_PER_MINUTE);
  return {
    words: wordCount,
    text: `${minutes} min read`,
  };
};
```

Our method`readingTime` uses the value set in `WORDS_PER_MINUTE` to calculate the amount of minutes one spends to read the text. You can change this value in the [Add the reading-time method to our Sidebar component](#add-the-reading-time-method-to-our-sidebar-component) step of the tutorial.

### Add the reading-time method to our Sidebar component

In this step, we set the calculated metrics to be displayed in the entry sidebar. For this, we import the following [Forma 36](/extensibility/app-framework/forma-36) components: `List`, `ListItem` and `Note`.

> **Info**
>
> Use Contentful design system [Forma 36](/extensibility/app-framework/forma-36) to give your app the look and feel of the Contentful web app.

For the calculated metrics to be displayed in the entry sidebar:

1. Open `src/locations/Sidebar.tsx`.
2. Copy the following code:

#### JavaScript

```js
import React, { useState, useEffect } from 'react';
import { List, ListItem, Note } from '@contentful/f36-components';
import { useSDK } from '@contentful/react-apps-toolkit';

const CONTENT_FIELD_ID = 'body';
const WORDS_PER_MINUTE = 200;

const Sidebar = () => {
  const sdk = useSDK();

  const contentField = sdk.entry.fields[CONTENT_FIELD_ID];
  const [blogText, setBlogText] = useState(contentField.getValue());

  // Listen for onChange events and update the value
  useEffect(() => {
    const detach = contentField.onValueChanged((value) => {
      setBlogText(value);
    });
    return () => detach();
  }, [contentField]);

  const readingTime = (text) => {
    const wordCount = text.split(' ').length;
    const minutes = Math.ceil(wordCount / WORDS_PER_MINUTE);
    return {
      words: wordCount,
      text: `${minutes} min read`,
    };
  };

  // Calculate the metrics based on the new value
  const stats = readingTime(blogText || '');

  // Render the metrics with Forma36 components
  return (
    <>
      <Info style=&#123;&#123; marginBottom: '12px' &#125;&#125;>
        Metrics for your blog post:
        <List style=&#123;&#123; marginTop: '12px' &#125;&#125;>
          <ListItem>Word count: {stats.words}</ListItem>
          <ListItem>Reading time: {stats.text}</ListItem>
        </List>
      </Info>
    </>
  );
};

export default Sidebar;
```

#### TypeScript

```typescript
import React, { useState, useEffect } from 'react';
import { SidebarAppSDK } from '@contentful/app-sdk';

import { List, ListItem, Note } from '@contentful/f36-components';
import { useSDK } from '@contentful/react-apps-toolkit';

const CONTENT_FIELD_ID = 'body';
const WORDS_PER_MINUTE = 200;

const Sidebar = () => {
  const sdk = useSDK<SidebarAppSDK>();

  const contentField = sdk.entry.fields[CONTENT_FIELD_ID];
  const [blogText, setBlogText] = useState(contentField.getValue());

  // Listen for onChange events and update the value
  useEffect(() => {
    const detach = contentField.onValueChanged((value) => {
      setBlogText(value);
    });
    return () => detach();
  }, [contentField]);

  // example implementation of a reading time calculator
  const readingTime = (text: string): { words: number; text: string } => {
    const wordCount = text.split(' ').length;
    const minutes = Math.ceil(wordCount / WORDS_PER_MINUTE);
    return {
      words: wordCount,
      text: `${minutes} min read`,
    };
  };

  // Calculate the metrics based on the new value
  const stats = readingTime(blogText || '');

  // Render the metrics with Forma36 components
  return (
    <>
      <Info style=&#123;&#123; marginBottom: '12px' &#125;&#125;>
        Metrics for your blog post:
        <List style=&#123;&#123; marginTop: '12px' &#125;&#125;>
          <ListItem>Word count: {stats.words}</ListItem>
          <ListItem>Reading time: {stats.text}</ListItem>
        </List>
      </Info>
    </>
  );
};

export default Sidebar;
```

## Embed your app in the Contentful web app

To see your app running in the Contentful web app, you must create an app definition to expose the app to Contentful. An app definition is an entity that represents an app in Contentful and stores general information about it.

### Create your app definition

To create an app definition:

> **Info**
>
> Make sure your app is running on [http://localhost:3000](http://localhost:3000) and you are logged in to [the Contentful web app](https://app.contentful.com/).

1. [Go to the **Apps** tab](https://app.contentful.com/deeplink?link=app-definition-list) under your organization settings:

2) Click **Create app**. The "App details" page is displayed.

![Create app definition 1](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/6cd8aa34effdf8d9e04c34d3b05332a38d514c8a3d869c5d31c3b19ca8fb0015/docs/assets/apps/create-app-def-1.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=20260929T234720Z&X-Amz-Expires=604800&X-Amz-Signature=8dede654ee3c4faa088a165550b19d35be058fd4c98e025edfc960e3895ede3b&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)

3. In the **Name** field, enter a custom name for your app. For our example app, we use **Blog Post Metrics** as a name.

4. In the **Frontend** field, enter URL where your app is hosted. Our example app is hosted locally for now, so the URL for it is `http://localhost:3000`.

![Create app definition 2](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/1d25fdbc18dfe976af0d915419e54bb33edd607231bc91fbb25f6520555e73ce/docs/assets/apps/create-app-def-2.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=20260929T234720Z&X-Amz-Expires=604800&X-Amz-Signature=cbb8e5b807301e3550d6c33ce3608da896a4cba082d3cb31fe722d7f80f5a681&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)

5. Under the **Locations** area, select a checkbox against a location (one or multiple) for your app. For our example app, we would like the metrics for the blog posts to be displayed in the sidebar of the entry editor, so we select the location **Entry sidebar**.

> **Info**
>
> App locations define where an app is displayed in the Contentful web app. For more details, see our [app location documentation](/extensibility/app-framework/locations), which explains the benefits of rendering your app in different locations.

6. Click **Save**. Your app definition is saved.

![Create app definition 3](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/a78b3265706ba18d2f636e22f2418aca4dd0b16144eb7a10ea7d2f74c99eb61f/docs/assets/apps/create-app-def-3.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=20260929T234720Z&X-Amz-Expires=604800&X-Amz-Signature=8c08e44d8642b4f030352542399c359e858799880390fb35d088f0c85504654b&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)

### Install your app to a space

After the app definition is created, install your app to a space:

1. In the [Contentful web app](https://app.contentful.com/), navigate to the required space.

2. In the top pane, click **Apps** and select **Custom apps**. The "Custom apps" page is displayed.

![Install app 1](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/1c0ce594f4f24c8c5ab9d2ced8bcdf48171f0241347f94911f05c97d9dc7ef39/docs/assets/apps/install-app-1.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=20260929T234720Z&X-Amz-Expires=604800&X-Amz-Signature=ff97ea963cee3b97f4474e756839e1e7f11c9e848b18b7233cc4ec5899538601&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)

3. Go to your newly created app, click on the actions menu icon and select **Install**.

![Install app 2](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/0b2ce8cf466ef7cb92db380c170c1b1945350a38d42cbcb591a31736f1b34834/docs/assets/apps/install-app-2.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=20260929T234720Z&X-Amz-Expires=604800&X-Amz-Signature=5287845b9b6b59e822af29311c8e6862d9b9ae12da48fdde0b215335e180147b&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)

The "Manage app access" window is displayed.

4. Click the **Environments** field and select the checkbox against an environment (one or multiple) in which you would like the app to be installed and click "Authorize Access". Your app is installed to the selected environment (one or multiple).

![Install app 3](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/93b1fc75207fb232449d0cfbcf6c302bca18cd42dff725860f5c9732f48c95e9/docs/assets/apps/install-app-3.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=20260929T234720Z&X-Amz-Expires=604800&X-Amz-Signature=4fd624ec2fd84fc7248e93c12e8a57ab14f1dc34bfb69655f42ddaa081448fbe&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)

> **Info**
>
> An app is able to access the data across the environments it is installed in.

> **Info**
>
> To install the app in the environment(s) belonging to a different space, switch to the required space and repeat the installation process.

### Assign your app to a content type

After your app is installed, assign it to "Blog post" content type.

To assign an app to a content type:

1. [Go to the **Content model** tab](https://app.contentful.com/deeplink?link=content-model) and click the **"Blog post"** content type.
2. Go to the **Sidebar** tab.
3. Under the "Available items" area, scroll down to the **Blog Post Metrics** card and click the **+** button. The app is added to the sidebar.
4. Click **Save** to apply changes to the content type.

## See your app in action

You have successfully created your custom app. Now, let's see it in action.

[Go to the **Content** tab](https://app.contentful.com/deeplink?link=content) and create an entry with the content type **Blog post**. You should see a sidebar app now in your entry editor.

![Sidebar Content Type](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/contentful.docs.buildwithfern.com/380acac3f9058ba3998c153d8aede54afa2894c2eb86d55385458e6b80c7fa80/docs/assets/apps/sidebar-app-in-action.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=20260929T234720Z&X-Amz-Expires=604800&X-Amz-Signature=1c748533f3b5720fe6f201dfc35cffde7bb399d1954a75691bdef8662b8a3b93&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)

## Next steps

* [Create a configuration screen](/extensibility/app-framework/app-configuration)
* [Deploy a custom app](/extensibility/app-framework/deploy-app)

## More custom app examples

Explore more custom app examples and templates on GitHub: [Examples apps and Templates using App Framework on GitHub](https://github.com/contentful/apps/tree/master/examples).

Read blog posts about building custom apps with the App Framework:

* [Building a custom Contentful app for the Last.fm API.](https://www.contentful.com/blog/build-custom-contentful-app-last-fm-api/)
* [How to manage your March Madness fantasy league with Contentful](https://www.contentful.com/blog/apps-of-march-basketball-draft-picks/)

## Additional resources

* [App Framework](/extensibility/app-framework)
* [App SDK Documentation](/extensibility/app-framework/sdk)
* [Forma 36](/extensibility/app-framework/forma-36)
* [Create Contentful App](/extensibility/app-framework/create-contentful-app)
* [App Definition](/extensibility/app-framework/app-definition)
* [App Locations](/extensibility/app-framework/locations)