Integration file structure
Each integration is stored inside a directory named after the integration domain. The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: mobile_app. So all files for this integration are in the folder mobile_app/.
The bare minimum content of this folder looks like this:
manifest.json: The manifest file describes the integration and its dependencies. More info__init__.py: The component file. If the integration only offers a platform, you can keep this file limited to a docstring introducing the integration"""The Mobile App integration.""".
Integrating devices - light.py, switch.py etc
If your integration is going to integrate one or more devices, you will need to do this by creating a platform that interacts with an entity integration. For example, if you want to represent a light device inside Home Assistant, you will create light.py, which will contain a light platform for the light integration.
- More info on available entity integrations.
- More info on creating platforms.
Integrating service actions - services.yaml
If your integration is going to register service actions, it will need to provide a description of the available actions. The description is stored in services.yaml. More information about services.yaml.
Data update coordinator - coordinator.py
There are multiple ways for your integration to receive data, including push or poll. Commonly integrations will fetch data with a single coordinated poll across all entities, which requires the use of a DataUpdateCoordinator.
If you want to use one, and you choose to create a subclass of it, it is recommended to define the coordinator class in coordinator.py. More information about DataUpdateCoordinator.
Where Home Assistant looks for integrations
Home Assistant will look for an integration when it sees the domain referenced in the config file (i.e. mobile_app:) or if it is a dependency of another integration. Home Assistant will look at the following locations:
<config directory>/custom_components/<domain>homeassistant/components/<domain>(built-in integrations)
Brand images - brand/
Brand images (icons and logos) are stored in the brands repository. Home Assistant Core proxies these images through a local API so that they are served from the same origin as the frontend.
The available API endpoints are:
/api/brands/integration/{domain}/{image}- Integration icons and logos/api/brands/hardware/{category}/{image}- Hardware images
All endpoints return a generic placeholder image by default if the requested image does not exist. To opt out and receive a 404 instead, add the ?placeholder=no query parameter.
These endpoints require authentication. Requests can authenticate using either a standard authenticated session (Bearer token) or by passing an access token in a token query parameter. The frontend obtains this access token via the brands/access_token WebSocket command and appends it to all brand image URLs automatically.
The following image filenames are supported:
icon.png/dark_icon.pnglogo.png/dark_logo.png[email protected]/[email protected][email protected]/[email protected]
Local brand images for custom integrations
Custom integrations can ship their own brand images by including a brand/ directory inside the integration directory. For example:
custom_components/my_integration/
├── __init__.py
├── manifest.json
└── brand/
├── icon.png
└── logo.png
When a brand/ directory is present, images are served directly from the local filesystem via the /api/brands/integration/{domain}/{image} endpoint. Local images take priority over images fetched from the brands CDN.
You can override a built-in integration by having an integration with the same domain in your <config directory>/custom_components folder. The manifest.json file requires a version tag when you override a core integration. An overridden core integration can be identified by a specific icon in the upper right corner of the integration box in the overview
Note that overriding built-in integrations is not recommended as you will no longer get updates. It is recommended to pick a unique name.