> 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.

# App Bundle

> An App Bundle belongs to an AppDefinition and is an entity that is used when hosting an app on the Contentful App Framework.

An `AppBundle` is an entity that is used when hosting an app on Contentful.
There are two ways to create an `AppBundle`:

* You can upload a bundle directly in [your app settings](https://app.contentful.com/deeplink?link=app-definition\&tab=bundles) by dragging and dropping the files into the drop zone.
  This will automatically upload them and create a new `AppBundle` right after. After saving, the uploaded assets will be served when your app is used.
  ![app bundles list](/developers/docs/_fern-img/7d2172e1b4d9f22501a2546f9c7b4246f026e7e50c51325cb9e55a4e13f97c74.webp)
* With the [CLI command](https://github.com/contentful/create-contentful-app/tree/master/packages/contentful--app-scripts#upload-a-bundle-to-an-app-definition).

Each `AppBundle` belongs to an `AppDefinition`. Although there can be more than one `AppBundle` for each `AppDefinition`,
only one `AppBundle` can be active at a time. The active bundle is referenced directly by the `AppDefinition` and is served when the app is rendered.
You can also activate a previous `AppBundle` either via the user interface by selecting it from the list of previous bundles, or
also via a [CLI command](https://github.com/contentful/create-contentful-app/tree/master/packages/contentful--app-scripts#upload-a-bundle-to-an-app-definition)

### Limitations

There are some limitations to keep in mind when creating an `AppBundle`:

* Every `AppBundle` needs a valid `index.html` file at the root level of the folder.
* There is a limit of **10mb** and a maximum of 500 files for each bundle.
* All internal links to your assets must use relative paths. Absolute paths will not work because the public URL is randomly generated. If you're using Vite, adding [`base: ''` or `base: './'`](https://vite.dev/config/shared-options.html#base) to your `vite.config.js` will resolve this. If you're on an earlier version of a `create-contentful-app` bootstrap, adding [`"homepage": "."`](https://create-react-app.dev/docs/deployment/#serving-the-same-build-from-different-paths) to your `package.json` will resolve this.