The fastest path from nothing to a bundle running on a device. Pick the Capacitor path or the Electron path — the CLI steps are the same, only the client integration differs.
Prerequisites
- Node.js 20 or newer
- An account on the dashboard at https://app.deployyour.app
- A Capacitor 6+ project, or an Electron 28+ project
Install the CLI
npm install -g @deploy-your-app/cli
dya --version
Capacitor
1. Run the guided setup
From your project root:
dya setup
dya setup is interactive and needs a TTY. It walks through logging in, picking an organization, creating or selecting the app, writing the .deployyourapp project config, generating RSA key pairs, installing @deploy-your-app/capacitor-update-manager, writing the plugin configuration, and running npx cap sync.
If you prefer to run the steps yourself, or you are scripting this in CI, see the manual setup section below.
2. Confirm each successful launch
Add one call to your app's startup path, after your UI has rendered:
import { DeployYourApp } from '@deploy-your-app/capacitor-update-manager';
await DeployYourApp.notifyAppReady();
If this is not called within appReadyTimeout (10000 ms by default) after an update is activated, the plugin rolls back to the previous bundle. That is the safety net for a bundle that fails to boot — leave it in.
That is the whole integration. With the default autoUpdate: true, the plugin checks on launch and every checkInterval seconds (600 by default), downloads new bundles, verifies them, and activates them according to applyMode (whenIdle by default, which loads the bundle on the next launch).
3. Build and deploy
npm run build
dya deploy --channel production
Realistic output:
ℹ Assets: /Users/you/my-app/dist/spa
✔ App: My App (com.example.app)
ℹ Version: 2026.0731.142530
ℹ Channel: production
ℹ Platform: capacitor
✔ Manifest: 41 files
✔ Archive: 1.4 MB
✔ Signed with RSA-4096
✔ Uploaded: 2026.0731.142530 (1.4 MB)
✔ Deployed to production at 100% rollout
✓ Deploy complete! Version 2026.0731.142530 is live.
The version is generated from the current time when you do not pass --version.
Devices on the production channel receive the update on their next check.
Electron
1. Log in and register the app
dya login
dya apps create --name "My App" --app-id com.example.app --platform electron
Creating an app also creates a production channel and makes it the default.
2. Initialize the project and generate keys
From your project root:
dya init --app-id com.example.app
dya keys generate
dya init writes the .deployyourapp config file and auto-detects your web assets directory. dya keys generate writes four PEM files into the current directory and uploads the two public keys to the server:
| File | Keep it |
|---|---|
dya-signing-private.pem |
On your machine and in CI only. Never commit it. |
dya-signing-public.pem |
Uploaded to the server; also goes in your client config as publicKey. |
dya-encryption-public.pem |
Next to the CLI; used to encrypt bundles at deploy time. |
dya-encryption-private.pem |
Embedded in your app binary; this is the decryption key. |
Encryption is optional. If dya-encryption-public.pem is present when you deploy, the bundle is encrypted before upload.
3. Install and wire up the updater
npm install @deploy-your-app/electron-update-manager
In your main process:
import path from 'node:path';
import { app, BrowserWindow } from 'electron';
import { ElectronUpdateManager } from '@deploy-your-app/electron-update-manager/main';
const updater = new ElectronUpdateManager(
{
appId: 'com.example.app',
channel: 'production',
autoUpdate: true,
},
app.getAppPath()
);
app.whenReady().then(async () => {
await updater.initialize();
const win = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
},
});
// Required: without a window reference the updater cannot activate a bundle.
updater.setWindow(win);
win.loadFile(updater.getBundlePath());
app.on('before-quit', () => updater.destroy());
});
In your preload script:
import '@deploy-your-app/electron-update-manager/preload';
In your renderer, once the UI has rendered:
import { getUpdaterApi } from '@deploy-your-app/electron-update-manager/renderer';
await getUpdaterApi().notifyAppReady();
4. Build and deploy
npm run build
dya deploy --channel production --target electron
--target electron is required. The server only returns a bundle whose target platform matches the requesting client, so a bundle deployed with the default capacitor target is never served to a desktop app.
Manual setup without dya setup
The Capacitor equivalent of dya setup, one command at a time:
dya login
dya apps create --name "My App" --app-id com.example.app --platform both
dya init --app-id com.example.app
dya keys generate
npm install @deploy-your-app/capacitor-update-manager
npx cap sync
Then add the plugin block to capacitor.config.json:
{
"plugins": {
"DeployYourApp": {
"appId": "com.example.app",
"channel": "production"
}
}
}
Set publicKey to the contents of dya-signing-public.pem to enable signature verification on the device, and encryptionPrivateKey to the contents of dya-encryption-private.pem if you deploy encrypted bundles. Do not commit either value to a public repository.
Verifying it worked
- The dashboard shows the deployment under the app's Deployments tab.
- The device appears under Devices after its first update check.
dya deployprints the version it uploaded; the same version appears on the channel.
If a device is not picking up the update, check that its appId matches the registered app, that the channel name matches, and that the bundle's target platform matches the client.
A client whose platform the app does not target gets an HTTP 409 with a message naming the mismatch, rather than a silent "no update". The usual cause is pointing a desktop build at an app registered as ios, android, or both (or the reverse). An app targets either the Capacitor family or Electron — never both — because a channel serves one active bundle and the two bundle types are not interchangeable. Register a second app for the other platform.
Next steps
- Core concepts — channels, bundles, deployments, rollouts
- CLI command reference — every command and flag
- Capacitor plugin setup and Electron updater setup — full configuration
- Encryption and bundle signing — key handling and CI