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.