Seed Project
Overview
Use modifications to change component configuration, replace assets, and add app definitions without editing downloaded files. Store these changes in /modifications so that you can apply them again after a component update.
Folders & Processing Order
The following example demonstrates where to place modifications for the iocd component:
modifications/
├── base/
│ └── iocd/
│ ├── config/
│ │ └── apps/
│ └── assets/
├── dev/
│ └── iocd/
│ └── config/
└── build/
└── iocd/
└── config/The CLI applies /modifications/base first, followed by /modifications/dev or /modifications/build for the selected mode. A file in the mode folder can therefore override a base modification. The directory structure beneath a component name matches the target structure inside that component.
Use /modifications/base/iocd/config/apps for app definitions and /modifications/base/iocd/assets for assets. Use the development and build folders when an app needs different URLs or settings in each mode.
The CLI resets tracked modifications before running dev or build, then applies the selected changes. Removing a modification source file also removes its tracked output when the modifications are reset and reapplied.
ℹ️ For additional examples, see Multi-Environment Builds in the io.Connect Seed Project and How to Avoid Overwriting Component App Definitions on the Developer Community site.
Replacing & Deleting Files
An ordinary file replaces the corresponding component file. Special filenames provide additional operations:
| File | Description |
|---|---|
system.json.merge |
Merges the contents into system.json, preserving properties that aren't specified. |
filename.delete |
Removes the corresponding filename from the component. |
.replace |
Replaces the target directory with the contents of the modification directory containing this marker. |
.delete |
Removes the target directory corresponding to the modification directory containing this marker. |
JSON Merging
A .json.merge file recursively merges object properties into the corresponding JSON file. New properties are added, supplied values override existing ones, and omitted properties remain unchanged.
The following example demonstrates a merge into an app configuration file named settings.json. These settings belong to the example app and aren't platform configuration properties:
{
"display": {
"theme": "light",
"showToolbar": true
},
"features": {
"search": true
}
}To change the theme and enable notifications, create settings.json.merge:
{
"display": {
"theme": "dark"
},
"features": {
"notifications": true
}
}The resulting settings.json will contain:
{
"display": {
"theme": "dark",
"showToolbar": true
},
"features": {
"search": true,
"notifications": true
}
}Named Merge Files
Use a suffix after .json.merge- to separate changes targeting the same file:
system.json.merge
system.json.merge-autoUpdate
system.json.merge-launchpad
system.json.merge-myFeatureAll these files target system.json. Base modifications are applied before modifications for the selected mode. Within each directory, files are processed in the order returned by the file system. Don't rely on the names to establish an ordering between conflicting merge files in the same directory.
Platform Selection
If the suffix contains darwin or win32, the merge file will apply only on that platform:
| File | Platform |
|---|---|
system.json.merge-darwin |
macOS. |
system.json.merge-win32 |
Windows. |
system.json.merge-myFeature-win32 |
Windows. |
Merge files without a platform identifier apply on both platforms.
Array Merging
Available since @interopio/iocd-cli 0.0.71
As of @interopio/iocd-cli 0.0.71, arrays are concatenated by default - e.g., merging {"apps": ["app3", "app4"]} into {"apps": ["app1", "app2"]} will produce {"apps": ["app1", "app2", "app3", "app4"]}. Earlier versions replaced the target array.
To select another operation, replace the array value in the merge file with a directive object:
| Directive | Description | Example |
|---|---|---|
"$append" |
Adds items to the end, matching the default behavior. | {"apps": {"$append": ["app3"]}} |
"$prepend" |
Adds items to the beginning. | {"apps": {"$prepend": ["dashboard"]}} |
"$remove" |
Removes matching items. | {"apps": {"$remove": ["legacy-app"]}} |
"$replace" |
Replaces the entire array. | {"apps": {"$replace": ["only-this-app"]}} |
⚠️ Note that if the target property is missing or isn't an array, the CLI sets it to the array in the directive, regardless of the directive type. A
"$remove"directive for a missing property therefore adds the listed items.
For object values, "$remove" compares the result of JSON.stringify(). The complete serialized object must match, including property order. The following merge removes an object containing only the specified "name" property. It won't match an object with additional properties:
{
"apps": {
"$remove": [{ "name": "unwanted-app" }]
}
}Object and array modifications can be combined in one file. The following example demonstrates how to change an app setting, extend one array, remove an item from another, and prepend a startup app:
{
"display": {
"theme": "dark"
},
"features": {
"enabledPlugins": ["my-plugin"],
"disabledPlugins": { "$remove": ["old-plugin"] }
},
"startupApps": { "$prepend": ["dashboard"] }
}System Configuration
To change platform settings, add a system.json.merge file in /modifications/base/iocd/config. Use the actual system configuration structure for the feature you are changing.
The following example demonstrates how to change the default logging category to "debug" while preserving its configured appenders and other categories:
{
"logging": {
"configuration": {
"categories": {
"default": {
"level": "debug"
}
}
}
}
}For development only, place this file in /modifications/dev/iocd/config. To use "error" for production builds, add the same structure with "level": "error" in /modifications/build/iocd/config/system.json.merge. These files will be applied after the base modifications for their respective modes.
Use .json.merge when preserving unspecified defaults. A file named system.json will replace the entire configuration.
The CLI replaces ${<VARIABLE>} placeholders in copied .json files and in the files produced by .json.merge files. Files of other types are copied unchanged. The following variables are available:
| Variable | Description |
|---|---|
${COMPONENTS_PATH} |
Folder containing the additional components. Resolves to %IO_CD_ROOT_DIR%/components in builds and to the seed /components folder in development mode. The platform expands %IO_CD_ROOT_DIR% at runtime. |
${PRODUCT_NAME} |
Product name from the basic settings. |
${PRODUCT_SLUG} |
Product slug from the basic settings. |
${PRODUCT_VERSION} |
Product version from the basic settings. |
Any other name is replaced with the value of the environment variable with that name. Names that don't match a variable are replaced with an empty string, so check the spelling of each placeholder. Backslashes in the values are converted to forward slashes.
ℹ️ For details on platform properties, see the Developers > Configuration > System section. For a complete auto update example, see the Publishing & Auto Updates section.
Icons & Images
The native app icon, tray icon, and platform branding images are controlled via the /modifications/base/iocd/assets/images folder. Create the /images folder if it doesn't exist, and add the image files you want to override.
Use the exact filenames in the following tables because the CLI, Electron Forge configuration, and platform runtime look for these paths during development and packaging.
Native App Icons
| File | Description | Requirements |
|---|---|---|
logo.ico |
Windows executable icon. The CLI embeds it into the main executable during npm run dev and npm run build. The Electron Forge Squirrel maker also uses it as the setup executable icon. |
Use a Windows .ico file with multiple sizes, such as 16x16, 32x32, 48x48, and 256x256. |
logo.icns |
App icon for macOS. The CLI copies it into the <installation_location>/Resources folder and sets CFBundleIconFile to logo.icns. The Electron Forge DMG maker also uses it for the generated .dmg. |
Use a macOS .icns file with multiple sizes. You can create it with Icon Composer or iconutil. |
logo.png |
Image asset used by the platform UI and branding. | Use a PNG file, recommended size 512x512. This doesn't replace the native Windows .exe or macOS .app icon by itself. |
On Windows, close any running instance of the app before running the command again, because the CLI has to patch the executable icon and metadata. If the Windows executable icon is stored somewhere else, update the "win.exe.exeIconPath" setting in config/iocd.cli.config.json or set the WIN_EXE_ICON_PATH environment variable. The default path is recommended because it also keeps the Squirrel installer icon aligned with the app icon.
On macOS, keep the file name logo.icns. The CLI expects this name when it updates the app bundle and signs the result.
Tray Icons
modifications/base/iocd/assets/
└── images/
├── tray-light.ico
├── tray-dark.ico
├── tray.ico
├── tray-alert-light.ico
├── tray-alert-dark.ico
├── tray-alert.ico
├── logo-alert.ico
├── trayTemplate.png
├── trayTemplate@2X.png
├── tray-alertTemplate.png
└── tray-alertTemplate@2x.pngOn Windows, the tray icon changes with the current platform theme:
| State | Lookup Order |
|---|---|
| Light theme | tray-light.ico, then tray.ico, then logo.ico |
| Dark theme | tray-dark.ico, then tray.ico, then logo.ico |
| Light theme with active notifications | tray-alert-light.ico, then tray-alert.ico, then logo-alert.ico, then the current tray icon |
| Dark theme with active notifications | tray-alert-dark.ico, then tray-alert.ico, then logo-alert.ico, then the current tray icon |
On macOS, the platform uses template PNG files (monochrome icons) instead of .ico files:
| State | Lookup Order | High-DPI Companion |
|---|---|---|
| Default | trayTemplate.png |
trayTemplate@2X.png |
| Active notifications | tray-alertTemplate.png, then the current tray icon |
tray-alertTemplate@2x.png |
The alert tray icon is used only when the platform has active notifications, the notification badge is enabled, and the tray notifications item is enabled. The "tray" object in system.json controls whether the tray menu and its items are shown. It doesn't provide custom icon file names.
After replacing any of these files, run npm run dev to apply them in development mode, or npm run build to create a new package.