Skip to content

Building the app outside Lovable

Clone the repository, then install the dependencies once:

Terminal window
bun install # or: npm install

Bun is used in every example below; npm run <script> works the same way.

Terminal window
bun run dev # dev server with hot reload, http://localhost:8080
bun run build # production build
bun run preview # serve the production build locally

Useful extras:

Terminal window
bun run lint # eslint
bun run format # prettier
bunx tsgo --noEmit # typecheck (or: bunx tsc --noEmit)

Prerequisites, installed once on your machine:

  • Rust — https://rustup.rs
  • Windows: Visual Studio Build Tools with Desktop development with C++, WebView2, and WiX v3 or NSIS for the installers
  • macOS: Xcode command line tools
  • Linux: webkit2gtk-4.1, libayatana-appindicator3, librsvg2, build-essential
Terminal window
bun run desktop # native window with hot reload (tauri dev)
bun run desktop:build # release binary + installers

Installers are written to src-tauri/target/release/bundle/ (.msi/.exe on Windows, .dmg/.app on macOS, .deb/.AppImage on Linux). Each installer must be built on the OS it targets, or through CI.

Front-end only, without the native window:

Terminal window
bun run desktop:dev:web # dev server using desktop/index.html
bun run desktop:build:web # static bundle in dist-desktop/

See Running the app as a desktop app for permissions, scopes and icons.

The shell ships its own plugin tooling — a builder, a watch mode and a scaffold generator. Plugin authors never write a build script and never think about excluding React: it is handled once, automatically.

Terminal window
bun run plugin:new <name> # scaffold plugins/<name>/ (builds immediately)
bun run plugin:build <name> # bundle one plugin to public/plugins/<name>/
bun run plugin:build # bundle every plugin under plugins/
bun run plugin:watch <name> # rebuild on each save
bun run plugin:build <name> -- --minify # minified bundle

The builder takes plugins/<name>/src/index.tsx, bundles it (browser, ESM) to public/plugins/<name>/index.js and copies ui.json next to it. React is never bundled: every react / react/jsx-runtime import — including the ones inside dependencies like lucide-react — is redirected to the shared bridge in plugins/_runtime/, so the bundle reuses the shell’s React instance.

Typecheck a plugin separately:

Terminal window
bunx tsgo --noEmit -p plugins/<name>/tsconfig.json

Install a built plugin from the app: open the Plugins panel, paste /plugins/<name>/index.js and click Add. Rebuild after every source change, then click Reload on the plugin’s row in the panel: the bundle is refetched from its original URL and the plugin restarts (no page reload needed). Removing and re-adding the plugin also works.

4. Types package for plugins in separate repositories

Section titled “4. Types package for plugins in separate repositories”
Terminal window
bun run plugin-types:build # regenerate packages/plugin-api/dist/index.d.ts

Emits the whole plugin type surface (PluginContext, PluginDefinition, SliceHandle, Services, settings, value types, tables, lists, manifests, transactions…) as one self-contained declaration bundle, with react external. The package is types-only and regenerated from src/kernel/ — never edit dist/. See packages/plugin-api/README.md and Developing a plugin in a separate repository for consuming it (npm, npm pack, or Git dependency) and the tsconfig mapping.

5. Syncing an external plugin repository (Plugin Studio)

Section titled “5. Syncing an external plugin repository (Plugin Studio)”

A plugin repository created from templates/plugin-studio/ holds no shell source: it receives a pre-built shell and the published contracts. After the framework changes, refresh it in two steps.

In this framework repository:

Terminal window
bun run studio:export

This regenerates packages/plugin-api/dist/, builds the shell SPA (vite.studio.config.ts) into templates/plugin-studio/shell/ (gitignored, so it is never committed here) and copies the contracts, runtime bridge, tooling and docs into the template.

Then copy into the plugin repository, overwriting:

Terminal window
T=templates/plugin-studio
DEST=<path-to-plugin-repo>
for d in shell packages/plugin-api packages/documents-core plugins/_runtime tools docs; do
rm -rf "$DEST/$d" && mkdir -p "$(dirname "$DEST/$d")" && cp -r "$T/$d" "$DEST/$d"
done

Your own plugins/<name>/, business packages/ and tests/ are untouched. Finally, in the plugin repository, run bun install, bun run check and bun run dev to confirm the plugins compile against the new plugin-api version (check its version in packages/plugin-api/package.json).

Documentation under CC BY 4.0 · © SCFlow contributors ·Back to supplychainflow.org