npx skills add ...
npx skills add equinor/fusion-skills --skill fusion-developer-portal
Guides development of Fusion portal shells — scaffolding, module configuration, app loading, routing, header/context integration, analytics, and deployment using the Fusion Framework CLI portal commands. USE FOR: create portal, scaffold portal, configure portal modules, portal app loading, portal routing, portal header, context selector, portal analytics, portal telemetry, portal manifest, ffc portal dev, portal deployment, embed apps in portal. DO NOT USE FOR: app-level feature development (use fusion-app-react-dev), backend service changes, Fusion Help Center integration, skill authoring.
npx skills add equinor/fusion-skills --skill fusion-developer-portal
Guide development of Fusion portal shells — host applications that load, route, and render Fusion apps inside shared chrome (header, context selector, navigation).
portal.manifest.ts or ffc portal dev questions/apps/:appKey/*)Apploader component or useApploader hook for embedding appsffc portal build, ffc portal upload)fusion-app-react-devfusion-help-integrationfusion-skill-authoringfusion-issue-authoringApploader sufficesDetermine what the user needs:
When Fusion MCP is available, prefer mcp_fusion_search_framework with queries like "portal manifest definePortalManifest ffc portal" or "createFrameworkProvider PortalModuleInitiator portal configure" for latest API surface. Label guidance not confirmed by MCP as fallback.
Use the Fusion Framework CLI:
Create the required files:
portal.manifest.ts — portal metadata and configuration:portal.schema.ts (optional) — configuration validation schemasrc/index.tsx — portal entry point (see references/portal-architecture.md)Start the dev server:
Portal-level configuration uses FrameworkConfigurator (not AppModuleInitiator like apps). Enable modules in your configure callback:
Key difference from app configuration: the portal configures FrameworkConfigurator and its modules are hoisted to all child apps. MSAL/auth is configured at portal level and inherited by apps.
See references/portal-architecture.md for full module configuration and portal-analytics cookbook reference.
The portal routes /apps/:appKey/* to an app loader. Two approaches:
Simple embed — use the built-in Apploader component:
Warning:
Apploaderis an experimental POC. Embedded apps may have routing and context issues. Best for simple apps like PowerBI or PowerApps views.
Custom app loader — for full control over loading states, error handling, and mounting. Use useFramework<[AppModule]>(), observe fusion.modules.app.current$, and call app.initialize(). See references/portal-architecture.md for the annotated custom AppLoader pattern.
Portal routing typically uses react-router-dom via the navigation module:
Portal-level UI typically includes:
useCurrentContext or useContextSelectorApps don't build their own header — they receive it from the portal shell.
Portal-level analytics capture app lifecycle events. Enable with adapters and collectors:
For telemetry (OpenTelemetry / Application Insights), see references/portal-architecture.md.
Never paste tokens directly into commands. Use
az loginfor interactive auth or setFUSION_TOKENenv var for CI pipelines.
ffc portal dev starts without errors/apps/:appKeyFrameworkConfigurator usageSame companion infrastructure as fusion-app-react-dev:
fusion-research — source-backed Fusion ecosystem research when portal behavior is uncertainfusion-code-conventions — naming, TSDoc, and code style checksWhen Fusion MCP is available, prefer mcp_fusion_search_framework for portal-specific lookups.
Apploader is experimental — always mention routing/context limitations when advising on app embeddingpnpm fusion-framework-cli portal dev
# or: ffc portal devimport type { FrameworkConfigurator } from '@equinor/fusion-framework';
import { enableAppModule } from '@equinor/fusion-framework-module-app';
import { enableNavigation } from '@equinor/fusion-framework-module-navigation';
import { enableAnalytics } from '@equinor/fusion-framework-module-analytics';
const configure = (configurator: FrameworkConfigurator) => {
enableAppModule(configurator);
enableNavigation(configurator, '/');
enableAnalytics(configurator, { /* ... */ });
};import { Apploader } from '@equinor/fusion-framework-react-app/apploader';
<Apploader appKey="my-app" />const Router = () => {
const framework = useFramework();
const router = framework.modules.navigation.router;
return <RouterProvider router={router} />;
};import { enableAnalytics } from '@equinor/fusion-framework-module-analytics';
import { ConsoleAnalyticsAdapter } from '@equinor/fusion-framework-module-analytics/adapters';
import { AppLoadedCollector, AppSelectedCollector } from '@equinor/fusion-framework-module-analytics/collectors';
enableAnalytics(configurator, (builder) => {
builder.addAdapter(new ConsoleAnalyticsAdapter());
builder.addCollector(new AppLoadedCollector());
builder.addCollector(new AppSelectedCollector());
});# Build the portal template
ffc portal build
# Upload to the Fusion portal service (authenticate via `az login` or FUSION_TOKEN env var)
ffc portal upload --portal-id <id>
# Tag a specific version
ffc portal tag --portal-id <id> --tag latest --version <version>