ODE Desktop developer mode
Developer mode in ODE Desktop lets you iterate on a local custom app build (for example dist/ after npm run build) against a profile’s real observations and workspace, without replacing the bundle you downloaded from Synkronus.
What it is
When developer mode is on, ODE Desktop mirrors your selected folder into the profile workspace under bundles/dev-local/. The workbench then loads:
- Custom app from
bundles/dev-local/app/ - Form preview from
bundles/dev-local/forms/(when your folder includes aforms/directory)
Observations, attachments, and sync still use the profile database. The Synk-downloaded bundle in bundles/active/ is not overwritten.
Prerequisites
- ODE Desktop installed (see project README for build-from-source).
- A profile with a configured workspace.
- A local folder whose root contains
index.html(typical: your custom appdist/output). - Optional: download an app bundle from Synkronus on the Bundles page so
bundles/active/has forms andapp.config.jsonwhen developer mode is off.
Enable developer mode
- Open Workbench → Bundles.
- Turn Developer mode On.
- Click Browse… and select the folder that contains
index.html. - Wait for the first mirror to finish (or click Refresh app).
While developer mode is on, an orange banner appears on all Workbench pages with the folder path and a Refresh app shortcut.
Folder layout
Your selected folder is the app root (same idea as the app/ directory inside a published bundle):
my-custom-app/dist/
index.html ← required at root
app.js
assets/
forms/ ← optional; mirrored for Form preview
my_form/
schema.json
ui.json
- Custom app entry:
index.htmlat the selected path (not a parent repo root unless that root is your built app). - Forms: standard bundle layout under
forms/{formType}/schema.jsonandui.json, plus optionalforms/ext.jsonand custom question types (same as Formulus bundles).
Refresh app
After you rebuild the custom app or edit forms locally:
- Click Refresh app on the Bundles page or in the Workbench banner.
This re-runs the mirror (source → bundles/dev-local/app/ and source/forms/ → bundles/dev-local/forms/). Custom app and Form preview pick up changes on the next load (the embed remounts automatically after a successful mirror).
Refresh from server on the Bundles page is separate: it updates bundles/active/ from Synkronus only.
What changes when developer mode is on
| Area | Behavior |
|---|---|
| Custom app (Workbench) | Loads mirrored app under bundles/dev-local/app/ |
| Form preview | Lists and loads specs from bundles/dev-local/forms/ when mirrored |
| Observations / sync | Unchanged — profile SQLite |
| Downloaded bundle | Stays in bundles/active/ for server reload and non-dev use |
getCustomAppUri / getFormSpecsUri (in preview bridge) | Point at dev-local roots when mode is on |
Workbench banner
When developer mode is on, every Workbench route shows a compact status strip above sync/activity messages: active folder path and Refresh app. Configure the folder and toggle on the Bundles page only.
Limitations
- Device APIs (camera, GPS, QR, etc.) are stubbed in ODE Desktop form preview, same as before developer mode.
- The mirror is a copy — edit files in your source folder, then Refresh app; ODE Desktop does not watch the filesystem.
- Invalid or missing folder (no
index.html) shows a blocking error; the custom app does not silently fall back tobundles/active/. - Observation query indexes use
app.config.jsonfrom the mirrored app when developer mode is on; rebuild indexes if you change index declarations (see Observation queries).
Platform comparison
| Formulus (device) | ODE Desktop (developer mode) | |
|---|---|---|
| Custom app source | Downloaded bundle | Local folder → bundles/dev-local/app/ |
| Forms | Bundle on device | Mirrored forms/ or bundles/active/forms/ when off |
| Observations | On-device DB | Profile workspace SQLite |
| Typical use | Field collection | Local iteration before publish |
See also
- Understanding app bundles — Synk download to
bundles/active/ - Custom applications — custom app role in bundles
- Observation queries —
getObservationsByQueryand indexes