ODE Desktop is the Open Data Ensemble desktop application (Tauri + React + Rust). It provides two modes:
| Mode | Purpose |
|---|---|
| Data management | Pull, inspect, correct, and sync observations; import/export; conflicts and local workspace state. |
| Forms / app workbench | Develop and test app bundles, embedded formplayer, and custom apps — aligned with Formulus and the shared WebView contract. |
The internal Rust crate may still be named custodian; user-facing strings use ODE Desktop.
- Field and data staff managing observations and sync (Data management).
- Form and app authors testing bundles and custom apps against Synkronus before mobile deploy (Workbench).
Relationship to other ODE components: Synkronus (API), Formulus + formplayer (runtime parity), Portal and CLI (same public API — no privileged desktop channel). Long-form prose here is intended to be copy-friendly for opendataensemble.org documentation; keep user-facing sections free of repo-only trivia (put contributor notes under Development).
Official builds are produced with pnpm tauri build (artifacts vary by OS: .msi, .dmg, .app, AppImage, .deb, etc.). When releases are published, attach those bundles to GitHub Releases and link them from project docs.
Prerequisites
- Windows: WebView2 (usually present on current Windows 10/11).
- Linux: WebKitGTK and related packages as required by Tauri prerequisites.
- macOS: Xcode command-line tools for development builds.
A placeholder curl-style installer script is at scripts/install-ode-desktop.sh (to be wired to real release asset URLs). For early testing, run from source (below).
From the monorepo root:
cd desktop
pnpm install
pnpm devIn another terminal:
cd desktop
pnpm tauri dev| Script | Purpose |
|---|---|
pnpm dev |
Vite dev server (frontend). |
pnpm build |
Typecheck + Vite production build. |
pnpm build:formplayer |
Build ../formulus-formplayer and copy output into public/formplayer_dist/. |
pnpm build:tauri |
Prepare Formplayer assets (build:formplayer) and then run the desktop frontend build. |
pnpm tauri build |
Full desktop bundle; automatically runs pnpm build:tauri first, so the packaged app includes formplayer_dist. |
pnpm lint / pnpm lint:fix |
ESLint. |
pnpm format / pnpm format:check |
Prettier. |
pnpm test |
Vitest (unit / component tests). |
pnpm typecheck |
tsc --noEmit. |
pnpm codegen:synk-client |
Regenerate TypeScript client from Synkronus OpenAPI. |
pnpm copy:formplayer |
Copy ../formulus-formplayer/build/ → public/formplayer_dist/. Prefer from formulus-formplayer/: npm run build:copy (build + Formulus + desktop copy). |
cd src-tauri
cargo test
cargo fmt
cargo clippyConfiguration is in openapi.client.config.json (paths relative to desktop/):
- Default spec:
../synkronus/openapi/synkronus.yaml - Output:
src/generated/synkronus-client
Override at generation time:
OPENAPI_SPEC_RELATIVE_PATHOPENAPI_OUTPUT_RELATIVE_PATH
CI regenerates the client and fails if the repo does not match (ode-desktop workflow).
- Bridge contract:
formulus/src/webview/FormulusInterfaceDefinition.ts— source of truth forformulusAPI/ postMessage. After changes, runsync-interfaceinformulus-formplayerand mirror behavior in the desktop WebView host. - Form preview host (Workbench → Form preview):
public/formulus-injection.js+ iframe shim; parent handlespostMessageinsrc/lib/formPreviewBridge.ts(explicit matrix perFormulusInjectionScriptrequesttype; device APIs including camera, audio, and video are stubbed in preview; observations + URIs use Tauri where applicable). Nested sub-observation flows (openFormplayer+options.subObservationMode) open a stacked Form preview iframe and resolve the parent promise withFormCompletionResultwithout persisting the child as a top-level observation. - Bundle extensions: merge rules for
forms/ext.jsonandforms/{form}/ext.jsonfollow FormulusExtensionService; seesrc/lib/bundleResolution.ts. - Embedded formplayer: production build copied into
public/formplayer_dist/; load in a WebView with the sameFormInitDataexpectations as mobile (seesrc/lib/formplayerHost.tsfor placeholder types).
Bundled icons live under src-tauri/icons/ and are referenced from src-tauri/tauri.conf.json bundle.icon. Misplaced iOS-style asset folders are not used for Tauri Linux bundles and have been removed to avoid confusion. For deb/AppImage installs, verify the packaged .desktop file Icon= entry resolves on Ubuntu/GNOME (dash, dock, Alt+Tab).
Conventional Commits; run pnpm lint, pnpm format:check, and pnpm test before pushing. PRs touching desktop/** trigger the ODE Desktop GitHub Actions workflow (see .github/CICD.md).