Frontend Plugins

Build a plugin remote loaded by Core UI. This guide follows version 3.1.7 (03acdf712c).

For the host behavior, see Frontend & Plugin Loading. For shared components, see Shared UI Components.

Generated layout

pnpm create-plugin creates frontend/plugins/inventory_ui/:

src/
  config.tsx              IUIConfig: navigation, routes, widgets
  modules/<module>/       Feature components
  pages/<module>/         Route entries
  widgets/                Exposed widgets
module-federation.config.ts
rspack.config.ts
project.json              serve port (template uses 3005)

The Nx project is named inventory_ui. The template exposes ./config, a main module, a settings module, and ./widgets. Remove unused sample surfaces or implement them completely. The generated UI port 3005 conflicts with Sales UI; assign an unused port.

Federation contract

module-federation.config.ts declares name: <name>_ui and exposes mapping to real components with the expected named exports. Shared singletons include react, react-router, erxes-ui, @apollo/client, jotai, ui-modules, and react-i18next.

src/config.tsx declares IUIConfig { name, path, navigationGroup, modules[] }. Every navigation path must map to a real route, and every expose must resolve. Real example: frontend/plugins/sales_ui/src/config.tsx adds defaultPath, sub-groups, relationWidgets, propertyInputs, and searchProviders.

Data and state

  • Server state with Apollo Client; colocate GraphQL documents with the feature and prefix operation names.
  • Plugin-wide client state with Jotai; component-local state with React state.
  • Forms with React Hook Form plus Zod; provide loading, empty, success, and error states.
  • After mutations, update Apollo cache, refetch, or subscribe so the UI never needs a manual refresh.
  • Lazy-load exposed modules inside Suspense.

Enable locally with ENABLED_PLUGINS=inventory and open the Core UI host (http://localhost:3001), not the remote URL directly.

Source references

Was this helpful?