Building and shipping Oda

This page is for maintainers of the Oda codebase: run the app from a source checkout, build the Windows installer, and see how builds are identified and published.

Before you start

Oda builds on Windows. The supported systems, and the native pieces behind its confinement and file locking, are on Platform support.

Run Oda from source

  1. In your checkout, install the dependencies: corepack pnpm@11.7.0 install.
  2. Build the whole project once: pnpm run build.
  3. Launch the built desktop app without rebuilding: pnpm run start:desktop. Or build first and then launch: pnpm run dev:desktop.
  4. Serve the built web interface: pnpm run start:web. The command prints a local address to open in a browser.

The command-line launcher prints the release version (--version prints it exactly) and is the only supported launcher for the app. Its flags and profiles are on Command line and flags.

The web development loop

pnpm run dev:web builds once, serves the web interface, and rebuilds the browser-side bundles as you edit sources, all in one terminal.

Short commands with make

CommandRuns
make buildpnpm run build
make webpnpm run start:web
make desktoppnpm run start:desktop
make dev-webpnpm run dev:web
make dev-desktoppnpm run dev:desktop

The scripts they call stay the source of truth. Pass options to the launched application through ARGS, for example ARGS='--no-open --port 3081': the web commands accept web flags, the desktop launcher accepts none.

Build the Windows installer

  1. Prepare the packaging environment file apps/desktop/.env.windows, which sits beside the desktop app and stays out of version control. An unsigned build needs only the application id; leave every signing value out. A setting the packer does not recognise stops packaging with unsupported setting.
  2. Run the full build first: pnpm run build. It compiles the whole project, including the native helpers. Package with the build skipped and the run fails on a missing native helper module.
  3. Package: pnpm run package:desktop:win:x64:unsigned.
  4. Take the artefacts from apps/desktop/.desktop-build/targets/win-x64/unsigned-artifacts/:
    • the installer datamind-oda-<version>-win-x64.exe;
    • its .blockmap for differential updates;
    • latest.yml, with the version, file name, size and SHA-512.

Run packaging from the wrong folder and the packer stops with No package.json found. If preparing the bundled runtime stops in a child process, run that preparation step again and package once more.

How builds are identified and published

Install a plugin bundle from a local folder

Use the command-line launcher's plugin command: give the profile the bundle should join and the bundle's absolute path as a file: address, in the form add file:/absolute/path/to/my-plugin-bundle. Managing external packages with the command needs pnpm on your PATH.

Questions, answered

Which Node.js version do I need?

24.x. The project pins its package manager through Corepack, so corepack pnpm@11.7.0 install uses the pinned version.

Do I have to build before I run the desktop app?

No. pnpm run start:desktop launches the app that was built last; pnpm run dev:desktop builds first, then launches.

How do I open the web interface from a source checkout?

Run pnpm run start:web. It serves the built web interface and prints a local address; open it in a browser. Flags for the web command are on Command line and flags.

What happens when one stage of the web development loop stops?

The loop stops the other stages and exits 1. The line that reports it names the stage: dev-web: <stage> exited (code <n>); stopping the other stages.

Why does my edit not show up in the web interface?

The loop rebuilds bundles when a source file changes, and the web server tells the browser to reload when the built files change. An edit outside the packages the web interface links rebuilds nothing, so the page stays as it is.

Can I run the web development loop next to a build?

No. Both write the same build outputs. Run one at a time.

What does --poll change?

It sets the watch interval in milliseconds, 500 ms by default, and switches the TypeScript watcher to fixed polling, which suits network drives. A value that is not a positive whole number is refused.

Packaging stopped with unsupported setting. What do I do?

The environment file holds a setting the packer does not recognise, retired settings included. Remove that setting and package again.

Can I build the installer without signing values?

Yes. Leave the signing values out of apps/desktop/.env.windows and the build produces an unsigned installer; Windows warns when such an installer first runs.

Where do the packaged builds and updates come from?

From your company's server. The installer, its blockmap and the update metadata are published inside it, and each server serves the build it pins. Updates never install while a run is active; see Updates and troubleshooting.

Can I install a plugin bundle from a local folder?

Yes. Use the launcher's plugin command with the profile and the bundle's absolute path as a file: address. Managing external packages with the command needs pnpm on your PATH.