# App

On this page we will look at what the various files in the Homey app folder are for and what essential concepts you should be aware of to start developing your Homey app.

Apps are able to use all of Homey's capabilities and thus can use the following technologies:

* [Wi-Fi](https://apps.developer.homey.app/wireless/wi-fi)
* [Bluetooth LE](https://apps.developer.homey.app/wireless/bluetooth)
* [Z-Wave](https://apps.developer.homey.app/wireless/z-wave)
* [Zigbee](https://apps.developer.homey.app/wireless/zigbee)
* [433 Mhz](https://apps.developer.homey.app/wireless/rf-433mhz-868mhz)
* [Infrared](https://apps.developer.homey.app/wireless/infrared)

Most Apps use only one wireless technology but it is possible to use them all at the same time in a single Homey App. Regardless of the wireless technologies used in your Homey app most of the concepts are the same. Every Homey app has the same basic file structure:

{% tabs %}
{% tab title="JavaScript" %}

```
com.athom.example/
├─ .homeycompose/
│ ├─ app.json
│ └─ ...
├─ assets/
│ ├─ icon.svg
│ └─ images
│   ├─ small.png
│   ├─ large.png
│   └─ xlarge.png
├─ drivers/
│ ├─ my_driver/
│ │ ├─ assets/
│ │ │ ├─ icon.svg
│ │ │ └─ images/
│ │ │   ├─ small.png
│ │ │   ├─ large.png
│ │ │   └─ xlarge.png
│ │ ├─ device.js
│ │ └─ driver.js
│ └─ ... 
├─ locales/
│ ├─ en.json
│ └─ nl.json
├─ settings/
│ └─ index.html
├─ api.js
├─ app.js
├─ app.json
├─ env.json
└─ README.txt
```

{% endtab %}

{% tab title="TypeScript" %}

```
com.athom.example/
├─ .homeycompose/
│ ├─ app.json
│ └─ ...
├─ assets/
│ ├─ icon.svg
│ └─ images
│   ├─ small.png
│   ├─ large.png
│   └─ xlarge.png
├─ drivers/
│ ├─ my_driver/
│ │ ├─ assets/
│ │ │ ├─ icon.svg
│ │ │ └─ images/
│ │ │   ├─ small.png
│ │ │   ├─ large.png
│ │ │   └─ xlarge.png
│ │ ├─ device.mts
│ │ └─ driver.mts
│ └─ ... 
├─ locales/
│ ├─ en.json
│ └─ nl.json
├─ settings/
│ └─ index.html
├─ api.mts
├─ app.mts
├─ app.json
├─ env.json
└─ README.txt
```

{% endtab %}

{% tab title="Python" %}

```
com.athom.example/
├─ .homeycompose/
│ ├─ app.json
│ └─ ...
├─ .python_cache/
│ └─ ... 
├─ assets/
│ ├─ icon.svg
│ └─ images
│   ├─ small.png
│   ├─ large.png
│   └─ xlarge.png
├─ drivers/
│ ├─ my_driver/
│ │ ├─ assets/
│ │ │ ├─ icon.svg
│ │ │ └─ images/
│ │ │   ├─ small.png
│ │ │   ├─ large.png
│ │ │   └─ xlarge.png
│ │ ├─ device.py
│ │ └─ driver.py
│ └─ ... 
├─ locales/
│ ├─ en.json
│ └─ nl.json
├─ settings/
│ └─ index.html
├─ api.py
├─ app.py
├─ app.json
├─ env.json
└─ README.txt
```

{% endtab %}
{% endtabs %}

## App Manifest

The `/app.json` file is the complete app manifest, it tells Homey what your app does. When you run or publish your app this file is generated from the various `*.compose.json` files and the JSON files in the `/.homeycompose/` folder. The generation of your app manifest is referred to as Homey Compose and it supports some additional advanced features such as templating. All the various compose files will be explained in the rest of the documentation.

All basic information about your app is configured in the `/.homeycompose/app.json` file. You can read the [App Manifest documentation](https://apps.developer.homey.app/the-basics/app/manifest) to learn more about this file.

{% hint style="warning" %}
Because the `/app.json` file gets generated from the various Homey Compose files you should never manually edit it. You should edit the `*.compose.json` and JSON files in the `/.homeycompose/` folder instead.
{% endhint %}

## App Class

{% tabs %}
{% tab title="JavaScript" %}
In the `/app.js` file you can create an `App` class. This class gets instantiated once, when your app started. This is a great place to put logic that is shared throughout your app, and it is sometimes necessary for Flow cards and other resources that you only want to setup once.

The app instance can be accessed from your `Driver` and `Device` classes through `this.homey.app`.

{% code title="/app.js" %}

```javascript
const Homey = require('homey');
const ApiClient = require('your-external-api-client');

class App extends Homey.App {
  async onInit() {
    // create an ApiClient once when the app is started
    this.client = new ApiClient();
  }
}

module.exports = App;
```

{% endcode %}

{% code title="/drivers/\<driver\_id>/device.js" %}

```javascript
const Homey = require('homey');

class Device extends Homey.Device {
  async onInit() {
    // access the ApiClient through the App instance
    const data = await this.homey.app.client.getData();
  }
}

module.exports = Device;
```

{% endcode %}
{% endtab %}

{% tab title="TypeScript" %}
In the `/app.mts` file you can create an `App` class. This class gets instantiated once, when your app started. This is a great place to put logic that is shared throughout your app, and it is sometimes necessary for Flow cards and other resources that you only want to setup once.

The app instance can be accessed from your `Driver` and `Device` classes through `this.homey.app`.

{% code title="/app.mts" %}

```mts
import Homey from 'homey';
import ApiClient from 'your-external-api-client';

export default class App extends Homey.App {
  client?: ApiClient;

  async onInit(): Promise<void> {
    // create an ApiClient once when the app is started
    this.client = new ApiClient();
  }
}

```

{% endcode %}

{% code title="/drivers/\<driver\_id>/device.mts" %}

```mts
import Homey from 'homey';
import type App from '../../app.mjs';

export default class Device extends Homey.Device {
  async onInit(): Promise<void> {
    // access the ApiClient through the App instance
    const data = await (this.homey.app as App).client?.getData();
  }
}

```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
In the `/app.py` file you can create an `App` class. This class gets instantiated once, when your app started. This is a great place to put logic that is shared throughout your app, and it is sometimes necessary for Flow cards and other resources that you only want to setup once.

The app instance can be accessed from your `Driver` and `Device` classes through `self.homey.app`.

{% code title="/app.py" %}

```python
from homey import app

from your_external_api_client import ApiClient


class App(app.App):
    client: ApiClient

    async def on_init(self) -> None:
        # create an ApiClient once when the app is started
        self.client = ApiClient()


homey_export = App

```

{% endcode %}

{% code title="/drivers/\<driver\_id>/device.py" %}

```python
from typing import cast

from homey import device

from ...app import App


class Device(device.Device):
    async def on_init(self) -> None:
        # access the ApiClient through the App instance
        data = await cast(App, self.homey.app).client.get_data()


homey_export = Device

```

{% endcode %}
{% endtab %}
{% endtabs %}

## App API

Homey apps can expose an API that other devices can talk to. It is even possible for Homey apps to talk to each other by exposing an API. The API implementation in the root folder of your app contains the handlers for all the API endpoints. You can read about exposing an API from your App in the [Web API guide](https://apps.developer.homey.app/advanced/web-api).

## Assets

In the `/assets/` folder at the root of your app you can put the assets of the app. These are the app icon `icon.svg` and the app images that will be shown in the Homey App Store. Read the [App Store guidelines](https://apps.developer.homey.app/app-store/guidelines#1-4-images) for more information about the icon and images.

## Drivers and Devices

The `/drivers/` folder contains all the drivers of your app. The drivers are the parts of a Homey app that allow users to add and then control devices. This folder should only contain other folders, it is common for those folders to be named after the product code of the device they are implementing. You can learn more by reading the [Devices documentation](https://apps.developer.homey.app/the-basics/devices).

## Locales

Translation files are kept in the `/locales/` directory. You can learn more about these files by reading the [internationalization documentation](https://apps.developer.homey.app/the-basics/app/internationalization).

## Readme

The `/README.txt` file in the root of your app contains the long-form description of your app. This will be shown in the Homey App Store when a user is browsing your app. Read the [App Store guidelines](https://apps.developer.homey.app/app-store/guidelines#1-3-readme) for more information about the readme.

{% hint style="info" %}
You can supply translated versions of the readme by naming the file `README.<languagecode>.txt`, for example `README.nl.txt` would contain the Dutch translation of the readme. You can find the supported languages in the [internationalization documentation](https://apps.developer.homey.app/the-basics/internationalization#supported-language-codes).
{% endhint %}

## Settings

{% tabs %}
{% tab title="JavaScript" %}
In your Homey app you can save settings that are persistent across reboots. These settings can be accessed from anywhere in your app through [`ManagerSettings`](https://apps-sdk-v3.developer.homey.app/ManagerSettings.html).

{% code title="/app.js" %}

```javascript
const Homey = require('homey');

class App extends Homey.App {
  async onInit() {
    const username = this.homey.settings.get('username');
    // ...
  }
}

module.exports = App;
```

{% endcode %}
{% endtab %}

{% tab title="TypeScript" %}
In your Homey app you can save settings that are persistent across reboots. These settings can be accessed from anywhere in your app through [`ManagerSettings`](https://apps-sdk-v3.developer.homey.app/ManagerSettings.html).

{% code title="/app.mts" %}

```mts
import Homey from 'homey';

export default class App extends Homey.App {
  async onInit(): Promise<void> {
    const username = this.homey.settings.get('username');
  }
}

```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
In your Homey app you can save settings that are persistent across reboots. These settings can be accessed from anywhere in your app through [`ManagerSettings`](https://python-apps-sdk-v3.developer.homey.app/manager/settings.html).

{% code title="/app.py" %}

```python
from homey import app


class App(app.App):
    async def on_init(self) -> None:
        username = self.homey.settings.get("username")


homey_export = App

```

{% endcode %}
{% endtab %}
{% endtabs %}

You can also create a page where users can update the App Settings by creating an `index.html` file in the `/settings/` folder. Since drivers have their own settings, most apps shouldn't need any App settings. Read more about how and when to use app settings in the [App Settings guide](https://apps.developer.homey.app/advanced/custom-views/app-settings).

## Environment

The `/env.json` file in the root of your app contains the environment variables of your app. Since this file is usually used to store secret keys it should be kept on your computer. If you use Git the `/env.json` file should therefore be added to the `/.gitignore` file. In this file you can store information that should not be public, for example the OAuth2 tokens your app uses to connect to a cloud service.

{% code title="/env.json" %}

```javascript
{
  "CLIENT_ID": "12345abcde",
  "CLIENT_SECRET": "182hr2389r824ilikepie1302r0832"
}
```

{% endcode %}

The variables are available anywhere in your app under `Homey.env.CLIENT_ID`, `Homey.env.CLIENT_SECRET`, etc. Make sure they are uppercase, and that their value is a string.

{% tabs %}
{% tab title="JavaScript" %}

```javascript
const Homey = require('homey');

const CLIENT_ID = Homey.env.CLIENT_ID;
const CLIENT_SECRET = Homey.env.CLIENT_SECRET;
```

{% endtab %}

{% tab title="TypeScript" %}

```mts
import Homey from 'homey';

const CLIENT_ID = Homey.env.CLIENT_ID;
const CLIENT_SECRET = Homey.env.CLIENT_SECRET;

```

{% endtab %}

{% tab title="Python" %}

```python
from homey.homey import Homey

CLIENT_ID = Homey.env.get("CLIENT_ID")
CLIENT_SECRET = Homey.env.get("CLIENT_SECRET")

```

{% endtab %}
{% endtabs %}

{% hint style="danger" %}
These variables are stored on Homey, and in theory should not be readable by anyone. However, make sure that these variables alone do not provide access to private resources.
{% endhint %}

## Node.js

As of Homey v12.9.0, all Homey platforms run apps on Node.js v22 (see [Node.js 22 upgrade guide](https://apps.developer.homey.app/upgrade-guides/node-22)). The table below lists the Node.js versions used by earlier Homey software versions across different platforms.

| Platform               | Version Range          | Node.js Version |
| ---------------------- | ---------------------- | --------------- |
| Homey Pro (2016–2019)  | < v7.4.0               | v12             |
| Homey Pro (2016–2019)  | >= v7.4.0 && < v12.9.0 | v16             |
| Homey Pro (2016–2019)  | >= v12.9.0             | v22             |
| Homey Pro (Early 2023) | < v12.9.0              | v18             |
| Homey Pro (Early 2023) | >= v12.9.0             | v22             |
| Homey Pro (mini)       | < v12.9.0              | v18             |
| Homey Pro (mini)       | >= v12.9.0             | v22             |
| Homey Cloud            | >= v12.9.0             | v22             |

> Note: Homey Cloud apps migrate to Node.js 22 only after you publish a new version after December 2nd, 2025. Earlier versions will continue running on the previous Node.js version.

## Python

The Python version running on Homey platforms is the latest available full release, currently `3.14`. Once a new version is released, apps using the previous version do not immediately stop working, but they should be updated to guarantee future compatibility.

### Dependencies

To ensure Python dependencies are compatible with all Homey platforms that support the Python runtime, the dependencies of you app should be managed through the Homey CLI. It allows for [adding](https://apps.developer.homey.app/getting-started/homey-cli#add-dependencies-to-a-homey-app), [removing](https://apps.developer.homey.app/getting-started/homey-cli#remove-dependencies-from-a-homey-app) or [installing already defined](https://apps.developer.homey.app/getting-started/homey-cli#install-the-dependencies-of-a-homey-app) dependencies. Using these commands will pre-compile the dependencies so they can be bundled with the app for installation and publishing. The pre-compiled environments are stored in `.python_cache` in your project folder.

### Typing

To add static type-checking to your Python project, or just add better suggestions to your IDE, you can install the [homey-stubs](https://pypi.org/project/homey-stubs/) package in a project [virtual environment](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#create-and-use-virtual-environments), or globally if you want it to be available for all your projects.

You can install the package with a type-checker globally using the following command.

```bash
python -m pip install homey-stubs pyright
```

If you use `pyproject.toml` and want to disable [pyright](https://github.com/microsoft/pyright) warnings about missing sources for the `homey` module you can add the following to your pyproject.toml.

```toml
[tool.pyright]
reportMissingModuleSource = 'none'
```

## Homey Ignore

The `/.homeyignore` file in the root of your app can be used to prevent certain files or folders from being included in your Homey App when publishing. It works in the same way as `.gitignore`. By default all files in the app directory will be included when publishing your Homey App. `/.homeyignore` is useful in case you want to commit documentation, designs, images, etc. to your version control system but not include it in your Homey App when publishing.

{% code title="/.homeyignore" %}

```javascript
comments.txt
docs/*
```

{% endcode %}
