Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ build and run them.
- [C# .NET MAUI](dotnet-maui/README.md)
- [C# .NET TUI](dotnet-tui/README.md)
- [C# .NET Win Forms](dotnet-winforms/README.md)
- [Electron](electron/README.md)
- [Flutter](flutter_quickstart/README.md)
- [Javascript TUI](javascript-tui/README.md)
- [Javascript Web](javascript-web/README.md)
Expand Down
5 changes: 5 additions & 0 deletions electron/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
out
dist
.DS_Store
*.log
88 changes: 88 additions & 0 deletions electron/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Ditto Electron Quickstart App 🚀

This directory contains Ditto's quickstart app for [Electron](https://www.electronjs.org/) desktop applications. The Ditto Node SDK runs in Electron's **main process**, providing full peer-to-peer sync. The UI is a React + TypeScript app in the **renderer process**, communicating with Ditto over Electron's IPC.

## Documentation

- [Javascript Install Guide](https://docs.ditto.com/sdk/latest/install-guides/js)
- [Javascript API Reference](https://software.ditto.live/js/Ditto/5.0.0/api-reference/)
- [Javascript Release Notes](https://docs.ditto.com/sdk/latest/release-notes/js)

## Prerequisites

- [Node.js](https://nodejs.org/) v22.12 or later (matches the floor of the bundled Electron runtime)

## Supported platforms

- macOS (Apple Silicon)
- Linux (x64, arm64)
- Windows (x64)

## Architecture

Electron applications run code in two processes that share no memory: a Node.js **main** process (full OS access) and a Chromium **renderer** process (a sandboxed browser window). Because the Ditto Node SDK is a native addon, it must run in main. This quickstart wires it up like this:

```
main process preload (context bridge) renderer (React)
───────────── ──────────────────────── ────────────────
Ditto.open(config) contextBridge.exposeInMainWorld window.ditto.*
auth.login(...) ('ditto', api) window.ditto.onTasksUpdated(cb)
sync.start() ipcRenderer.invoke / .on
registerSubscription
registerObserver ────► webContents.send('tasks:updated', tasks) ────► setTasks(tasks)
```

The renderer never imports `@dittolive/ditto`; it only calls `window.ditto.*` methods exposed by the preload script via `contextBridge`. Context isolation is enabled and Node integration is disabled in the renderer — the standard secure Electron defaults.

### Peer-to-peer transports

This quickstart enables LAN sync (TCP + mDNS + multicast) and disables Bluetooth LE and AWDL. BLE and AWDL on macOS require entitlements that only signed app bundles get; a plain `npm run dev` Electron process can't use them. LAN P2P provides peer-to-peer sync between devices on the same network, and the `DITTO_WEBSOCKET_URL` provides cloud sync to Ditto's Big Peer.

### Local storage

Ditto's local store is persisted at `app.getPath('userData')`, which resolves to:

- macOS: `~/Library/Application Support/Ditto Tasks/`
- Linux: `~/.config/Ditto Tasks/`
- Windows: `%APPDATA%/Ditto Tasks/`

Tasks survive restarts because of this. To reset, quit the app and delete that directory.

## Getting Started

To get started, you'll first need to create an app in the [Ditto Portal][0] with the "Online Playground" authentication type. You'll need your AppID, Playground Token, Auth URL, and WebSocket URL.

[0]: https://portal.ditto.live

From the repo root, copy the `.env.sample` file to `.env`, and fill in the fields:

```
cp .env.sample .env
```

The `.env` file should look like this (with your fields filled in):

```bash
DITTO_APP_ID=""
DITTO_PLAYGROUND_TOKEN=""
DITTO_AUTH_URL=""
DITTO_WEBSOCKET_URL=""
```

Then run the app:

```
cd electron
npm install
npm run dev
```

### Troubleshooting: `Error: Electron uninstall`

If `npm run dev` fails with `Error: Electron uninstall`, the Electron binary was not downloaded during `npm install` (this can happen if scripts were skipped or a network error occurred) on Windows. Fix it by running the install script manually:

```
node node_modules/electron/install.js
```

Then re-run `npm run dev`.
22 changes: 22 additions & 0 deletions electron/electron.vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { defineConfig, externalizeDepsPlugin } from 'electron-vite';
import react from '@vitejs/plugin-react-swc';

export default defineConfig({
main: {
plugins: [externalizeDepsPlugin()],
},
preload: {
plugins: [externalizeDepsPlugin()],
build: {
rollupOptions: {
output: {
format: 'cjs',
entryFileNames: '[name].cjs',
},
},
},
},
renderer: {
plugins: [react()],
},
});
45 changes: 45 additions & 0 deletions electron/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';

export default tseslint.config(
{ ignores: ['out', 'dist', 'node_modules'] },
{
extends: [
js.configs.recommended,
...tseslint.configs.recommended,
eslintPluginPrettierRecommended,
],
files: ['src/main/**/*.ts', 'src/preload/**/*.ts'],
languageOptions: {
ecmaVersion: 2022,
globals: globals.node,
},
},
{
extends: [
js.configs.recommended,
...tseslint.configs.recommended,
eslintPluginPrettierRecommended,
],
files: ['src/renderer/**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
);
Loading