Developer Guide / Portlet Build & Deploy

Portlet Build & Deploy

Strict rules for creating a portlet and deploying it with the portlet build.

Custom portlets are authored in the portlet bundle (for example custom-portlet/magicvarsh-sco-portlets), compiled by the portlet build into standalone ES modules, and registered into the running platform from the Portlets screen using Deploy URL. The build compiles each portlet separately and aliases react and lucide-react to thin shims that read the host's instances at runtime.

!
These rules are strict. Skipping any of them is the usual cause of portlets that need 2–3 recompiles (missing-icon errors) or fail to register (duplicate id / "Identifier already declared").

Strict rules — creating a portlet

  1. Folder & entry name must match the glob src/portlets/<Name>/<Name>Portlet.jsx. The entry file name must end in Portlet.jsx or the build will not find it.
  2. Give the descriptor a unique id. Search first with grep -rn "id: '" src/portlets. Reusing an id registers a duplicate component.
  3. Pick ONE component style and do not mix. Self-contained is recommended: do not import PortletShell.jsx at all; define your own helpers with portlet-unique names (e.g. UiCard, not PortletCard). If you go shell-based, use the imported helpers as imported and never also declare a local copy.
  4. Every lucide-react icon you import must exist in the shim (shims/lucide-react.js). Run the preflight to add missing icons automatically.
  5. Never redeclare a top-level name — one declaration per function / const / import binding at column 0.
  6. Register the portlet in src/index.js: add the import and put the descriptor in the exported portlets array (in the matching category section).
i
The descriptor must export id, name, version, category, description, component and defaultConfig.

Strict rules — building

Always run the preflight check, then build. npm run build runs the check with --fix automatically first (the prebuild step), so missing icons are resolved before the real compile — but the build still fails on duplicate ids or duplicate identifiers, because those require a code change.

cd custom-portlet/magicvarsh-sco-portlets
npm run check            # report every issue in one pass
npm run check -- --fix   # auto-add missing icons to the shim
npm run build            # preflight (--fix) + compile → dist/portlets/<Name>.js

# or build the whole module via Maven:
mvn clean package -pl custom-portlet/magicvarsh-sco-portlets -DskipTests
!
Do not hand-edit files in dist/portlets/. They are build output and are overwritten on every compile. Fix the source and rebuild.

Strict rules — deploying

Deploy the compiled bundle from the admin console — do not copy files into the running container by hand.

  1. Open Portlets from the sidebar.
  2. Select Deploy URL.
  3. Choose how to provide the built bundle: Upload .js file (the dist/portlets/<Name>.js you just built) or Paste URL (a reachable URL to that file).
  4. Deploy. The platform reads the descriptor and registers the portlet by its id, name and version.
  5. Confirm it appears in the catalogue, then place it on a page from the page editor.
Deploying a built portlet via Deploy URL (upload or paste URL).
Deploying a built portlet via Deploy URL (upload or paste URL).
!
Because portlets register by id, deploying a bundle whose id already exists will collide with the existing component. Bump the version for an update, and never reuse another portlet's id.

Generating a portlet from an image (AI)

The Image → HTML AI tool can turn a screenshot or mockup into a working portlet without writing code. After it generates the HTML you can wire runtime behaviour and produce a deployable portlet — the same kind of artifact the deployer produces from source.

  • Sample form JSON — the tool scans the generated HTML for input/select/textarea fields and shows a JSON skeleton of all fields, so you can build request mappings against real field names.
  • On page load / On submit — two config panels let you invoke an HTTP API (URL + method) or a registered integration component (by code, via /api/soap-components/{code}/invoke), with a JSON request mapping that uses ${form.<field>} tokens.
  • Deploy as Portlet — compiles an ES-module portlet (descriptor + component) with the load/submit wiring baked in, uploads it to the asset service, and registers a portlet droppable on any page.
  • Download standalone .html — a self-contained file with the same wiring for use outside the portal.
i
On load, response keys that match a field name prefill that field; on submit, the mapped request is sent to the configured API or integration component. Versioning and approval apply to the generated portlet like any other component.