Seed Project

Overview

Available since io.Connect Desktop 10.0

The io.Connect seed project is the main approach for delivering, customizing, and packaging io.Connect Desktop. The seed project enables you to control the entire process of creating your own custom distribution package, reducing the time for adopting new platform versions.

The seed project provides the following benefits:

  • installing the latest or a specific version of the platform components;
  • integrating the platform license key;
  • customizing the platform system configuration;
  • customizing the platform assets like logos, icons, splash screen, loader, and more;
  • customizing various branding features via the CLI configuration (the product name and description, the names and icons of the produced artifacts);
  • development and production modes that support different configuration settings;
  • templates for the customizable system apps (e.g., Workspaces App, Web Group App, Launchpad);
  • adding your own custom apps to be packaged with your platform build;
  • test templates for writing and executing your own tests;
  • producing artifacts (installers, bundles) for Windows and macOS;
  • code signing settings;
  • publishing and auto update settings;
  • CI/CD integration settings;

The @interopio/iocd-cli library provides an io.Connect CLI which is a necessary tool for creating and managing a seed project.

ℹ️ For more details on the available io.Connect CLI commands, see the CLI section.

Requirements

To be able to create and use an io.Connect seed project, the following requirements must be met:

  • Node.js v22 or later;
  • npm v9 or later;
  • OS: Windows 10 or later, macOS 11 or later;
  • License: the seed project requires a valid license key for io.Connect Desktop;

Quick Start

Execute the following steps to quickly setup your seed project.

  1. Install the io.Connect CLI to create a seed project:
  • Install the io.Connect CLI:
npm install -g @interopio/iocd-cli@latest
  • Navigate to your project directory and create the seed project by executing the following command:
iocd create

Alternatively, you can use npx to execute the create package command directly:

npx @interopio/iocd-cli@latest create
  1. Follow the prompts and provide a product name, select the desired platform components, select which templates to add for customization, and provide a valid license key.

⚠️ Note that the Application Adapters aren't currently available as installable components via the io.Connect CLI. Until they become available, they will be delivered to you as separate bundles which you have to add manually to your project.

  1. Install the necessary dependencies for the seed project:
npm install
  1. Prepare the project for usage by executing the following command. This will install the selected components and the dependencies for all customizable apps:
npm run setup
  1. To run your seed project in development mode in order to test your platform and your interop-enabled apps, execute the following command:
npm run dev
  1. After customizing and testing your platform project, you can produce build artifacts both for Windows and for macOS by executing the following command:
npm run build

Project Structure

The following demonstrates the basic structure of the seed project:

.
├── apps/                       # Contains the customizable system apps. You can place your own apps here to be bundled with the package.
├── components/                 # Downloaded platform components.
│   ├── iocd/                   # The main platform component (required).
│   └── <other-components>      # Additional licensed components (devTools, demos, and more).
├── config/                     # Seed project configuration files.
│   ├── forge.config.js         # Electron Forge configuration.
│   ├── iocd.cli.config.json    # io.Connect CLI configuration.
│   └── iocd.license.key        # License key file.
├── modifications/              # Contains all platform customizations (icons, images, and more) and configuration overrides.
│   ├── base/                   # Modification that will be applied in all modes (development/build).
│   ├── dev/                    # Modifications that will be applied only in development mode.
│   └── build/                  # Modifications that will be applied only during production builds.
├── tests/                      # Automated tests.
│   └── basic.test.js           # Example test suite.
├── .github/workflows/          # Pre-configured GitHub Actions workflow example for CI/CD automation.
├── package.json
└── README.md

Components

The following table lists the currently available components that can be installed via the seed project:

Component Description
"demos" Contains a set of web demo apps that can be used for testing and PoC purposes.
"devTools" Contains the io.Connect Dev Tools.
"iocd" Required. This is the main platform component.

Configuration

Basic Settings

The metadata for your product can be configured in the package.json file:

{
    "name": "my-product-slug",
    "version": "1.0.0",
    "description": "My product description.",
    "productName": "My Product Name",
    "author": "My Company"
}

The values specified in these fields are automatically populated by the io.Connect CLI when you execute the create command.

The following table describes the purpose of each property:

Property Type Description
"author" string Used as a company name (also used to auto-generate copyright).
"description" string Used as a product description in installers and metadata.
"name" string Used as a project identifier (e.g., folder name, executable name, package name, and more).
"productName" string Used as a human-readable product name displayed to users in UIs.
"version" string Used as a version for your platform app.

The settings for configuring the io.Connect CLI are in the iocd.cli.config.json file located in the /config folder.

The following is a basic configuration for the io.Connect CLI specifying the store from which to download the platform components and the list of components and component versions to retrieve:

{
    "components": {
        "store": {
            "github": {
                "repo": "interopio/iocd-components/releases"
            }
        },
        "list": {
            "iocd": "latest"
        }
    }
}

ℹ️ For details on all available configuration settings for the io.Connect CLI, see the complete JSON schema for the iocd.cli.config.json file. The schema is located in the /node_modules/@interopio/iocd-cli/dist/schemas folder. Add a $schema property to your configuration file to enable IDE autocompletion and validation.

License Key

io.Connect Desktop requires a valid license key to operate.

ℹ️ For details on how to obtain a license key for io.Connect Desktop 10.0, contact us.

During the process of creating the seed project, you will be prompted to provide a valid license key for io.Connect Desktop. Copy and paste your license key when prompted to continue the project creation. If you don't provide a valid license key, you won't be able to create a seed project.

The io.Connect CLI will create automatically an iocd.license.key file located in the /config folder of the seed project. You can use this file to manage your license key later.

⚠️ Note that you must never commit the iocd.license.key file in your project repository to prevent leaking your license key. By default, this file is ignored in the .gitignore settings.

For the purpose of setting up CI/CD automation, you can also use the IOCD_LICENSE_KEY environment variable to store and obtain the license key from your GitHub secrets during build.

Customization

Modifications

Modifications are the recommended way to customize io.Connect Desktop components without directly editing component files. They allow you to change configurations, add apps, modify assets, and override default behavior while preserving your changes across component updates.

Key Concepts:

  • Modifications are stored separately from components in the modifications/ folder
  • Changes persist when components are updated or reinstalled
  • Mode-specific modifications allow different behavior in dev vs. build mode
  • Files are copied or merged into components when running iocd dev or iocd build

Directory Structure:

modifications/
├── base/                     # Applied in all modes
│   └── iocd/
│       ├── config/
│       ├── assets/
│       └── apps/
├── dev/                      # Applied only in dev mode
│   └── iocd/
│       └── config/
└── build/                    # Applied only in build mode
    └── iocd/
        └── config/

Processing Order:

  1. Base modifications (modifications/base/) are applied first
  2. Mode-specific modifications (modifications/dev/ or modifications/build/) are applied second, overriding base when needed

Common Use Cases:

  • Replace logos and icons in modifications/base/iocd/assets/
  • Configure system settings in modifications/base/iocd/config/
  • Add app definitions in modifications/base/iocd/apps/
  • Use different URLs for dev (localhost) vs. build (file://) in mode-specific folders

Special File Types:

  • .json.merge - Deep merges with existing JSON instead of replacing
  • .delete - Removes the corresponding file
  • .replace marker - Replaces entire directory (place in directory to replace)

System Configuration

The io.Connect Desktop system configuration (the system.json file) controls platform-wide settings like auto-updates, logging, and feature flags. To customize these settings, create modification files that merge with the default configuration.

Location:

modifications/base/iocd/config/system.json.merge

The following example demonstrates how to enable auto updates:

{
    "autoUpdater": {
        "enabled": true,
        "updateSource": {
            "type": "Service",
            "baseUrl": "https://updates.yourcompany.com"
        },
        "interval": 60
    }
}

The following example demonstrates how to configure the system logging:

{
    "logging": {
        "level": "info",
        "appender": "default"
    }
}

Mode-Specific Configurations

Using different settings for development and production build mode:

Dev mode (modifications/dev/iocd/config/system.json.merge):

{
    "logging": {
        "level": "debug"
    },
    "features": {
        "devTools": true
    }
}

Build mode (modifications/build/iocd/config/system.json.merge):

{
    "logging": {
        "level": "error"
    },
    "features": {
        "telemetry": true
    }
}

When modifying the system configuration, consider the following:

  • Use .merge extension to deep merge with existing configuration.
  • Without .merge, the file completely replaces the original.
  • Changes are applied when running iocd dev or iocd build.
  • Environment variables like ${PRODUCT_VERSION} are automatically expanded.

Icons & Images

Default logo:

Replace the default logo files in modifications/base/iocd/assets/images/:

modifications/base/iocd/assets/
└── images/
    ├── logo.ico   # Windows executable icon (multiple resolutions)
    ├── logo.icns  # macOS app bundle icon (multiple resolutions)
    └── logo.png   # App icon (used in UI)

Requirements:

  • logo.ico: Windows icon file with multiple sizes (16x16, 32x32, 48x48, 256x256)
  • logo.icns: macOS icon file with multiple sizes (use Icon Composer or iconutil)
  • logo.png: PNG file, recommended size 512x512

Apps

io.Connect Desktop includes several built-in apps that you can replace with your own custom versions:

  • Workspaces - Workspace management UI
  • Groups - Window grouping UI
  • Splash Screen - Platform splash screen
  • Launchpad - App launcher
  • Notifications - Notification center

Apps in the apps/ folder allow you to customize these built-in apps or add entirely new functionality. This approach keeps your core platform apps in the same repository, eliminating the need to manage them across multiple repositories and simplifying version control, deployment, and coordination.

Using Template Apps

Template aspp can be selected during project creation or added later:

# Add a template app
iocd apps add workspaces

# List available templates
iocd apps list --available

Available templates:

  • workspaces - Workspace management
  • groups - Window grouping
  • splash-screen - Loading screen
  • launchpad - App launcher

Once added, build your implementation on top of the template in the apps/ folder.

Creating Custom Apps

For custom apps, create a folder in apps/ with an iocd.app.json file:

apps/
└── my-custom-app/
    ├── iocd.app.json       # Defines modifications and build behavior
    ├── package.json
    └── src/

Example iocd.app.json:

In this example:

  • Dev mode (triggered by iocd dev or npm run dev): Executes a start script (typically starts a dev server with hot-reload) and copies the development app configuration so the app definition points to the dev server
  • Build mode (triggered by iocd build or npm run build): Executes a build script (typically builds optimized production assets) and copies the final built assets to the modifications folder
{
   "dev": {
        "script": "start",
        "modifications": [
            {
                "source": "/config/my-app-dev.json",
                "destination": "/modifications/dev/iocd/config/apps/my-app.json"
            }
        ]
    },
    "build": {
        "script": "build",
        "modifications": [
            {
                "source": "/dist/",
                "destination": "/modifications/build/iocd/assets/my-app"
            }
        ]
    }
}

The iocd.app.json file defines:

  • base: Array of modifications applied in all modes
  • dev: Object with optional script (npm script name) and modifications array
  • build: Object with optional script (npm script name) and modifications array

Managing Apps

# Install app dependencies
iocd apps install

# Start apps in dev mode
iocd apps dev

# Build apps for production
iocd apps build

Development

Development mode allows you to quickly start io.Connect Desktop with all your configured changes and apps, enabling rapid iteration and testing during development.

When you run dev mode, the CLI will:

  1. Apply all relevant modifications - Base modifications and dev-specific modifications are copied to components
  2. Start all apps - Runs the dev script for each app (typically starting dev servers with hot-reload)
  3. Launch the platform - Starts the platform with all changes applied
# Start io.Connect Desktop in dev mode
iocd dev

# Or using npm script
npm run dev

Installing & Updating Components

To install a component or update existing component while in development mode, use the following command:

# Update components
iocd components install <component-name>

# Or using npm script (note the -- before the component name)
npm run components-install -- <component-name>

This command will download and install the latest version of the specified component.

If you want to install a specific version, use:

iocd components install <component-name>@<version>

# Or using npm script (note the -- before the component name)
npm run components-install -- <component-name>@<version>

Testing

Testing is based on WebdriverIO and depends on the @interopio/wdio-iocd-service package, which enables starting and controlling io.Connect Desktop from WebdriverIO. This allows you to create and run comprehensive end-to-end (E2E) tests for your io.Connect Desktop platform.

Running Tests

Tests are written in the tests/ folder and can be executed using:

# Run all tests
npm test

# Or using the WebdriverIO CLI directly
npx wdio run ./wdio.config.ts

Writing Tests

Tests are written using WebdriverIO syntax with the io.Connect Desktop service handling app lifecycle. Example test structure:

describe("io.Connect Desktop Platform", () => {
    it("should launch successfully", async () => {
        // Your test logic here.
        // The @interopio/wdio-iocd-service handles starting/stopping io.Connect Desktop.
    });
});

Add your test files to the tests/ directory. They'll run automatically in CI/CD pipelines.

Building for Production

The build process creates production-ready installers for distribution. It orchestrates multiple steps to produce signed, optimized packages ready for deployment.

What happens during build:

  1. Build all apps - Executes build scripts for each app in production mode
  2. Reinstall components - Downloads and installs fresh component versions
  3. Apply all modifications - Copies base and build-specific modifications to components
  4. Code sign binaries - Signs executables and libraries (if configured)
  5. Create build artifacts - Generates installers (.exe setup on Windows, .dmg on macOS, .zip archives)
  6. Publish to release server - Uploads artifacts for auto-updates (if configured)

Build System:

The build process is based on Electron Forge, a complete toolchain for building and packaging Electron apps. The main configuration is located in config/forge.config.js, where you can customize makers, publishers, and build behavior.

Build Commands

# Build installer
iocd build

# Or using npm script
npm run build

# Build options
iocd build --output custom/path         # Custom output directory
iocd build --publish-only               # Skip build, only publish
iocd build --skip-install               # Skip component installation

Build Output

Depending on the OS, you can configure Electron Forge makers to produce different types of artifacts. The following configurations have been tested:

Windows

  1. Squirrel.Windows installer (.exe setup)
  • You can change the install GIF by replacing the install.gif in assets folder.
  • The app will be installed into %LocalAppData%\YourAppName. Squirrel is opinionated and does not allow changing this path.
  • By default the UserData folder generated by the platform will stay in %LocalAppData%\interop.io\io.Connect Desktop folder. You can change this by add the following system.json.merge-win32 file in modifications/base/iocd/config/system.json.merge-win32 (the merge file has win32 suffix which indicates it is only applied on Windows OS):
{
  "paths": {
    "userData": "%LocalAppData%/${PRODUCT_SLUG}/UserData/%IO_CD_ENV%-%IO_CD_REGION%",
    "cache": {
      "location": "%LocalAppData%/${PRODUCT_SLUG}/Cache/%IO_CD_ENV%-%IO_CD_REGION%",
      "copy": true
    }
  }
}
  1. Portable ZIP archive

macOS

  1. DMG disk image
  2. ZIP archive

The full list of makers is available in the Electron Forge documentation.

Code Signing

Code signing ensures that your app is trusted by operating systems and users can verify it hasn't been tampered with. Both Windows and macOS require code signing for distribution.

Windows

PFX Certificate File

Using a PFX certificate file:

{
    "win": {
        "codeSign": {
            "type": "signtool",
            "pfxPath": "path/to/certificate.pfx",
            "pfxPassword": "${WIN_PFX_PASS}"
        }
    }
}

Certificate Store

You can also use a certificate store (e.g., DigiCert KeyLocker):

{
    "win": {
        "codeSign": {
            "type": "signtool",
            "certificateSha1": "${WIN_CERT_SHA1}"
        }
    }
}

When configuring your code signing settings, consider the following:

  • If using DigiCert KeyLocker, run smctl windows certsync before building to sync certificates to Windows store.
  • Either "pfxPath" or "certificateSha1" must be provided (not both).
  • You can set "type" to "off" to disable code signing.

Custom Script

For advanced signing scenarios, you can provide a custom signing script:

{
    "win": {
        "codeSign": {
            "type": "custom",
            "customCodeSignScriptPath": "path/to/custom-sign.js"
        }
    }
}

Your custom script should export a function that receives the binary path and config:

// custom-sign.js
module.exports = async function(binaryPath, config) {
    // Your custom signing logic here.
    console.log(`Signing ${binaryPath}`);
    // Use any signing tool or API you need.
};

macOS

Code Signing Configuration
{
    "mac": {
        "codeSign": {
            "type": "keychain",
            "identity": "Developer ID Application: Your Company (TEAM_ID)"
        }
    }
}

Options:

  • "type": "keychain" (use keychain certificate), "certificate" (use .p12 file), "custom" (custom script), or "off" (no signing)
  • "identity": Developer ID Application identity or SHA-1 hash (optional, auto-selected if not specified)
  • "keychain": Keychain name or path (optional - uses default keychain if not specified)

Custom Script

For advanced signing scenarios, you can provide a custom signing script:

{
    "mac": {
        "codeSign": {
            "type": "custom",
            "customCodeSignScriptPath": "path/to/custom-sign.js"
        }
    }
}

Your custom script should export a function that receives the app bundle path and config:

// custom-sign.js
module.exports = async function(appBundlePath, config) {
  // Your custom signing logic here
  console.log(`Signing ${appBundlePath}`);
  // Use any signing tool or API you need
};
Notarization Configuration
{
    "mac": {
        "notarization": {
            "type": "notarytool",
            "appleId": "${MAC_NOTARIZATION_APPLE_ID}",
            "appleIdPassword": "${MAC_NOTARIZATION_APPLE_ID_PASSWORD}",
            "appleTeamId": "${MAC_NOTARIZATION_APPLE_TEAM_ID}"
        }
    }
}

When configuring your notarization settings, consider the following:

  • Notarization is required for distribution outside the Mac App Store.
  • Use an app-specific password (not your regular Apple ID password).
  • Generate an app-specific password at appleid.apple.com.
  • You can set "type" to "off" to skip notarization (for development builds).

Custom Script

For advanced notarization scenarios, you can provide a custom notarization script:

{
    "mac": {
        "notarization": {
            "type": "custom",
            "customNotarizationScriptPath": "path/to/custom-notarize.js"
        }
    }
}

Your custom script should export a function that receives the app bundle path and config:

// custom-notarize.js
module.exports = async function(appBundlePath, config) {
    // Your custom notarization logic here.
    console.log(`Notarizing ${appBundlePath}`);
    // Use any notarization tool or API you need.
};

CI/CD Automation

Continuous Integration and Continuous Deployment (CI/CD) automates building, testing, and publishing your io.Connect Desktop platform. The seed project includes a GitHub Actions workflow located in .github/workflows/build.yml. It produces signed installers and can publish them to a release server.

Auto Updates

Setting up auto updates allows your users to automatically receive new versions of your platform.

Requirements:

Auto-updates are supported for specific build artifact types:

  • Windows: Squirrel.Windows installers (.exe setup files)
  • macOS: DMG on macOS

Other build outputs (portable ZIP on Windows, ZIP on macOS) do not support automatic updates.

Execute the following steps to setup the platform auto updates:

  1. Set up a release server.

You can use existing solutions or build your own:

  • Existing services: Nucleus, Hazel, or other update servers (see Electron update services)
  • Custom solution: Build your own update server following Squirrel protocols
  1. Configure io.Connect Desktop to check the update server.

Create or modify modifications/base/iocd/config/system.json.merge:

{
    "autoUpdater": {
        "enabled": true,
        "updateSource": {
        "type": "Service",
            "baseUrl": "https://updates.yourcompany.com"
        },
        "interval": 60
    }
}
  1. Publish updates.

Choose one of the following approaches:

Automatic publishing during build - configure publishers in config/forge.config.js:

module.exports = {
    publishers: [
        {
            name: "@electron-forge/publisher-electron-release-server",
            config: {
                baseUrl: "https://updates.yourcompany.com",
                username: process.env.RELEASE_SERVER_USERNAME,
                password: process.env.RELEASE_SERVER_PASSWORD
            }
        }
    ]
};

Manual upload - after building, manually upload the installer artifacts to your release server.

  1. Test the auto updates.
  • Install your platform using the signed installer
  • Publish a new version to your update server
  • Launch the platform and verify it detects and installs the update

CLI

To be able to create and use a seed project, you must install the io.Connect CLI via the @interopio/iocd-cli library:

npm install -g @interopio/iocd-cli@latest

You can also use npx to directly execute package commands:

npx @interopio/iocd-cli@latest create

The io.Connect CLI provides various commands for creating and manipulating a seed project for io.Connect Desktop.

Commands

The io.Connect CLI offers the following main commands:

Command Description
apps Command with sub-commands for managing the customizable system apps in the seed project.
build <options> Builds and packages the io.Connect Desktop platform for distribution.
components Command with sub-commands for managing the seed project components.
create <options> Creates a new seed project. Accepts options for configuring the seed project.
dev Starts io.Connect Desktop in development mode (the platform isn't packaged yet).
help <command> Displays help for the specified command.
license Displays current license key information.
modifications Command with sub-commands for managing the seed project modifications.
setup Prepares the seed project for first usage. This will install the specified components and will install the dependencies for all customizable system apps.
test Runs the test suite.

create

The create command accepts the following options:

Option Description
--source <url/path> Override component source during setup
--non-interactive Run in non-interactive mode using provided options
--product-name <name> Product name for non-interactive mode
--folder-name <name> Folder name for non-interactive mode
--components <components> Comma-separated list of components (e.g., "iocd,demos,devTools")
--applications <applications> Comma-separated list of apps (e.g., "groups,workspaces")
--license-key <key> License key for non-interactive mode
--use-current-folder Install in current folder (non-interactive mode)
-h, --help Display help for command

build

The build command accepts the following options:

Option Description
--output <path> Output directory for packages (default: "dist/packages")
--publish-only Skip the build phase and only publish packages (does nothing if no publish is configured) (default: false)
--skip-install Skip installing components during the build process (default: false)
-h, --help Display help for command

components

The components command has the following sub-commands:

Command Description
uninstall <name> Remove a component from the project
install [name] Install all components listed in iocd.cli.config.json or a specific component by name
list List all installed components
browse Browse all available components from currently selected store
pin Pin all "latest" component versions to their current specific versions for reproducible builds
download [options] [output-dir] Download all available components (including prereleases) for all platforms from the current store to a local directory in local store format (-f, --force Overwrite existing files without prompting)
help [command] Display help for command

apps

The apps command has the following sub-commands:

Command Description
install [options] Install dependencies for all template apps
build [options] Build all template apps and copy output to modifications folder. Requires prior installation of dependencies.
dev [options] Start all template apps in development mode
list List all template apps that are added to the seed project, and all available templates
add <appName> Add a new template app from the registry
help [command] Display help for command

modifications

The modifications command has the following sub-commands:

Command Description
apply [component] Apply all modifications or modifications for specific component
help [command] Display help for command

Troubleshooting

Build fails with "License not found":

  • Ensure that the IOCD_LICENSE_KEY environment variable is set or create an iocd.license.key file in the /config folder with your license key.

Code signing fails on Windows:

  • Verify that the certificate is valid and not expired.
  • Check that "pfxPassword" is set correctly.
  • For certificate store signing: ensure that smctl windows certsync has been run first.
  • Verify that exactly one of "pfxPath" or "certificateSha1" is configured (not both).

Notarization for macOS fails:

  • Use an app-specific password, not a regular Apple ID password.
  • Generate an app-specific password at appleid.apple.com.
  • Verify that your Apple Developer Program membership is active.
  • Ensure that "appleTeamId" matches your Developer Team ID.

The platform won't start in development mode:

  • Run iocd setup to verify component installation.
  • Verify that that the components/iocd directory exists.
  • Review the logs in the system /temp directory.

Components not downloading:

  • Verify network connectivity.
  • Verify the component store configuration in the iocd.cli.config.json file located in the /config folder.
  • For GitHub stores: ensure that the repository access and credentials are correct.