Skip to content

App Catalog

The goal is that we want to have a simple method of using a Git repository to represent an App Catalog. This allows us to easily extend our software with more apps in the future, and it allows our users to create their own private App catalogs (for example to beta-test unreleased software).

Repository

We have converged on a repository structure that looks like this:

/el/em/element/metadata.yml
/el/em/element/docker-compose.yml
/categories.yml

Every application is in a sub-folder in the repository. The path of the application is derived from its name: the first two characters of the application name are the name of the folder, and the second two characters of the application are the name of the subfolder within.

Every application is represented by a metadata file and a docker-compose file. The metadata file has the following syntax:

name: "Application Name"
version: "0.1.0"
authors:
  - "John Doe"
repository: "https://github.com/dani-garcia/vaultwarden"
documentation: "https://github.com/dani-garcia/vaultwarden/wiki"
description: "Example description"
license: "AGPL"
icon: https://website.com/icon.png
screenshots: []
category: productivity

The categories.yml file in the root of the repository contains a list of all categories along with their logos.

productivity:
    name: Productivity
    logo: https://website.com/icon.png

We have a Rust script that will ensure the validity and correctness of all of the applications in the App catalog repository to prevent broken configurations from being pushed.

Implementation Changes

Backend

The backend has a database table called App Catalogs which stores a list of repository URLs. It checks out each of these repositories, and periodically fetches new commits. Whenever there is new data, it will perform a one-way sync with the database, updating the known applications and their data. It will create new applications in the database if it needs to, but it will never delete applications. This is to keep the code simple.

The backend also has an AppCatalog row that is called foreign. In order for us to create AppInstances of foreign apps, we will create an empty App row per foreign application. This will not contain a description, logo, or any of the other metadata.

Using the Django Admin, it is possible to add multiple App Catalogs that are not foreign, for users that are self-hosting the backend and would like to combine our Catalog with theirs.

Events

The event that causes the Device to launch or stop applications is the Device Request with the SchedulerAction event. In the payload of this event, the Device gets an application object that looks like this:

{
    "application": {
        "appstore": "Fractal App Store",
        "name": "wikijs",
        "version": "latest"
    }
}

We would change this to include the repository of the application, like so:

{
    "application": {
        "repository": "https://github.com/fractalnetworksco/app-catalog",
        "name": "wikijs",
    }
}

Device

The device maintains a checkout per repository (and branch), so that if multiple apps are loaded, a single checkout of the repository suffices.

Upon getting a SchedulerAction event, the device checks if it has already checked out that repository. If so, it performs a fetch. If not, it clones the repository.

Periodically, the Device will fetch all repositories and potentially update applications. This may be triggered by a request from the Hive Backend.

Frontend

The frontend will render our built-in default App catalog the same way it already does. It additionally allows for installing apps from foreign App Catalogs using a modal with a free-form import for adding the repository URL and application name. The frontend will not render images for applications installed from foreign repositories.

Ideas

Encrypted Repository

Potentially, we might support using encrypted repository URLs so that you can add applications from private repositories. These would be encrypted with your Device secret.