|
| 1 | +--- |
| 2 | +name: fusion-developer-portal |
| 3 | +description: '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.' |
| 4 | +license: MIT |
| 5 | +compatibility: Requires @equinor/fusion-framework-cli for portal scaffolding and dev server. Requires @equinor/fusion-framework and @equinor/fusion-framework-react for portal runtime. |
| 6 | +metadata: |
| 7 | + version: "0.0.0" |
| 8 | + status: active |
| 9 | + owner: "@equinor/fusion-core" |
| 10 | + skills: |
| 11 | + - fusion-research |
| 12 | + - fusion-code-conventions |
| 13 | + tags: |
| 14 | + - fusion-portal |
| 15 | + - portal-development |
| 16 | + - app-loader |
| 17 | + - portal-shell |
| 18 | + - micro-frontend |
| 19 | + - fusion-framework-cli |
| 20 | + - portal-manifest |
| 21 | + - context-selector |
| 22 | + - portal-routing |
| 23 | + mcp: |
| 24 | + suggested: |
| 25 | + - fusion |
| 26 | +--- |
| 27 | + |
| 28 | +# Fusion Developer Portal |
| 29 | + |
| 30 | +Guide development of Fusion portal shells — the host applications that load, route, and render Fusion apps inside a shared chrome (header, context selector, navigation). |
| 31 | + |
| 32 | +## When to use |
| 33 | + |
| 34 | +- User wants to scaffold a new Fusion portal |
| 35 | +- User asks about `portal.manifest.ts` or `ffc portal dev` |
| 36 | +- User wants to configure portal-level framework modules (telemetry, analytics, navigation, services, app module) |
| 37 | +- User wants to build a custom app loader or portal shell |
| 38 | +- User wants to add portal-level routing (`/apps/:appKey/*`) |
| 39 | +- User asks about the `Apploader` component or `useApploader` hook for embedding apps |
| 40 | +- User wants to wire up a portal header, context selector, or bookmark side sheet |
| 41 | +- User asks how portals load and initialize Fusion apps at runtime |
| 42 | +- User wants to add portal-level analytics or telemetry |
| 43 | +- User asks about portal deployment (`ffc portal build`, `ffc portal upload`) |
| 44 | + |
| 45 | +## When not to use |
| 46 | + |
| 47 | +- App-level feature development inside a Fusion app → use `fusion-app-react-dev` |
| 48 | +- Backend service changes → separate repository |
| 49 | +- Fusion Help Center integration → use `fusion-help-integration` |
| 50 | +- Skill authoring → use `fusion-skill-authoring` |
| 51 | +- Issue authoring → use `fusion-issue-authoring` |
| 52 | + |
| 53 | +## Required inputs |
| 54 | + |
| 55 | +### Mandatory |
| 56 | + |
| 57 | +- What to build: scaffold a portal, add a portal feature, configure a module, or understand portal architecture |
| 58 | +- Portal context: new portal from scratch, or modifying an existing one |
| 59 | + |
| 60 | +### Conditional |
| 61 | + |
| 62 | +- Portal name/ID when scaffolding |
| 63 | +- MSAL client ID and service discovery URL when configuring auth |
| 64 | +- Specific modules to enable (analytics, telemetry, bookmarks, feature flags, AG Grid) |
| 65 | +- Whether the portal needs a custom app loader or the default `Apploader` suffices |
| 66 | + |
| 67 | +## Instructions |
| 68 | + |
| 69 | +### Step 1 — Classify the portal task |
| 70 | + |
| 71 | +Determine what the user needs: |
| 72 | + |
| 73 | +- **Scaffold a new portal** → go to step 2 |
| 74 | +- **Configure portal modules** → go to step 3 |
| 75 | +- **App loading and routing** → go to step 4 |
| 76 | +- **Portal chrome (header, context, bookmarks)** → go to step 5 |
| 77 | +- **Analytics and telemetry** → go to step 6 |
| 78 | +- **Build and deploy** → go to step 7 |
| 79 | + |
| 80 | +When Fusion MCP is available, prefer `mcp_fusion_search_framework` with queries like `"portal manifest definePortalManifest ffc portal"` or `"createFrameworkProvider PortalModuleInitiator portal configure"` to retrieve the latest API surface. Label any guidance not confirmed by MCP as fallback. |
| 81 | + |
| 82 | +### Step 2 — Scaffold a new portal |
| 83 | + |
| 84 | +Use the Fusion Framework CLI: |
| 85 | + |
| 86 | +```sh |
| 87 | +mkdir my-fusion-portal && cd my-fusion-portal |
| 88 | +pnpm init |
| 89 | +pnpm add -D @equinor/fusion-framework-cli |
| 90 | +``` |
| 91 | + |
| 92 | +Create the required files: |
| 93 | + |
| 94 | +- **`portal.manifest.ts`** — portal metadata and configuration: |
| 95 | + |
| 96 | +```typescript |
| 97 | +import { definePortalManifest } from '@equinor/fusion-framework-cli/portal'; |
| 98 | + |
| 99 | +export default definePortalManifest((env, { base }) => ({ |
| 100 | + name: 'my-portal', |
| 101 | + version: '1.0.0', |
| 102 | + entry: './src/index.tsx', |
| 103 | +})); |
| 104 | +``` |
| 105 | + |
| 106 | +- **`portal.schema.ts`** (optional) — configuration validation schema |
| 107 | +- **`src/index.tsx`** — portal entry point (see [references/portal-architecture.md](references/portal-architecture.md)) |
| 108 | + |
| 109 | +Start the dev server: |
| 110 | + |
| 111 | +```sh |
| 112 | +pnpm fusion-framework-cli portal dev |
| 113 | +# or: ffc portal dev |
| 114 | +``` |
| 115 | + |
| 116 | +### Step 3 — Configure portal modules |
| 117 | + |
| 118 | +Portal-level configuration uses `FrameworkConfigurator` (not `AppModuleInitiator` like apps). Enable modules in your configure callback: |
| 119 | + |
| 120 | +```typescript |
| 121 | +import type { FrameworkConfigurator } from '@equinor/fusion-framework'; |
| 122 | +import { enableAppModule } from '@equinor/fusion-framework-module-app'; |
| 123 | +import { enableNavigation } from '@equinor/fusion-framework-module-navigation'; |
| 124 | +import { enableAnalytics } from '@equinor/fusion-framework-module-analytics'; |
| 125 | + |
| 126 | +const configure = (configurator: FrameworkConfigurator) => { |
| 127 | + enableAppModule(configurator); |
| 128 | + enableNavigation(configurator, '/'); |
| 129 | + enableAnalytics(configurator, { /* ... */ }); |
| 130 | +}; |
| 131 | +``` |
| 132 | + |
| 133 | +Key difference from app configuration: the portal configures `FrameworkConfigurator` and its modules are hoisted to all child apps. MSAL/auth is configured at the portal level and inherited by apps. |
| 134 | + |
| 135 | +See [references/portal-architecture.md](references/portal-architecture.md) for the full module configuration pattern and the `portal-analytics` cookbook reference. |
| 136 | + |
| 137 | +### Step 4 — App loading and routing |
| 138 | + |
| 139 | +The portal routes `/apps/:appKey/*` to an app loader. Two approaches: |
| 140 | + |
| 141 | +**Simple embed** — use the built-in `Apploader` component: |
| 142 | + |
| 143 | +```tsx |
| 144 | +import { Apploader } from '@equinor/fusion-framework-react-app/apploader'; |
| 145 | + |
| 146 | +<Apploader appKey="my-app" /> |
| 147 | +``` |
| 148 | + |
| 149 | +> **Warning**: `Apploader` is an experimental POC. Embedded apps may have routing and context issues. Best for simple apps like PowerBI or PowerApps views. |
| 150 | +
|
| 151 | +**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](references/portal-architecture.md) for the annotated custom AppLoader pattern. |
| 152 | + |
| 153 | +Portal routing typically uses `react-router-dom` via the navigation module: |
| 154 | + |
| 155 | +```tsx |
| 156 | +const Router = () => { |
| 157 | + const framework = useFramework(); |
| 158 | + const router = framework.modules.navigation.router; |
| 159 | + return <RouterProvider router={router} />; |
| 160 | +}; |
| 161 | +``` |
| 162 | + |
| 163 | +### Step 5 — Portal chrome |
| 164 | + |
| 165 | +Portal-level UI typically includes: |
| 166 | + |
| 167 | +- **Header** — top bar with Fusion logo, context selector, bookmarks, person settings |
| 168 | +- **Context selector** — wired to the current app's context module via `useCurrentContext` or `useContextSelector` |
| 169 | +- **Bookmark side sheet** — toggle via the navigation module |
| 170 | +- **App navigation** — sidebar or top-level nav for switching between hosted apps |
| 171 | + |
| 172 | +These components are portal-specific. Apps do not build their own header — they receive it from the portal shell. |
| 173 | + |
| 174 | +### Step 6 — Analytics and telemetry |
| 175 | + |
| 176 | +Portal-level analytics capture app lifecycle events. Enable with adapters and collectors: |
| 177 | + |
| 178 | +```typescript |
| 179 | +import { enableAnalytics } from '@equinor/fusion-framework-module-analytics'; |
| 180 | +import { ConsoleAnalyticsAdapter } from '@equinor/fusion-framework-module-analytics/adapters'; |
| 181 | +import { AppLoadedCollector, AppSelectedCollector } from '@equinor/fusion-framework-module-analytics/collectors'; |
| 182 | + |
| 183 | +enableAnalytics(configurator, (builder) => { |
| 184 | + builder.addAdapter(new ConsoleAnalyticsAdapter()); |
| 185 | + builder.addCollector(new AppLoadedCollector()); |
| 186 | + builder.addCollector(new AppSelectedCollector()); |
| 187 | +}); |
| 188 | +``` |
| 189 | + |
| 190 | +For telemetry (OpenTelemetry / Application Insights), see [references/portal-architecture.md](references/portal-architecture.md). |
| 191 | + |
| 192 | +### Step 7 — Build and deploy |
| 193 | + |
| 194 | +```sh |
| 195 | +# Build the portal template |
| 196 | +ffc portal build |
| 197 | + |
| 198 | +# Upload to the Fusion portal service (authenticate via `az login` or FUSION_TOKEN env var) |
| 199 | +ffc portal upload --portal-id <id> |
| 200 | + |
| 201 | +# Tag a specific version |
| 202 | +ffc portal tag --portal-id <id> --tag latest --version <version> |
| 203 | +``` |
| 204 | + |
| 205 | +> **Never paste tokens directly into commands.** Use `az login` for interactive auth or set the `FUSION_TOKEN` environment variable for CI pipelines. |
| 206 | +
|
| 207 | +### Step 8 — Validate |
| 208 | + |
| 209 | +1. `ffc portal dev` starts without errors |
| 210 | +2. Apps load correctly at `/apps/:appKey` |
| 211 | +3. Context selector and header render properly |
| 212 | +4. TypeScript compiles with no errors |
| 213 | +5. Analytics events fire on app load/select (if enabled) |
| 214 | + |
| 215 | +## Expected output |
| 216 | + |
| 217 | +- Working portal shell with app loading, routing, and chrome |
| 218 | +- Portal-level module configuration with correct `FrameworkConfigurator` usage |
| 219 | +- Loading and error states handled for app initialization |
| 220 | +- Brief summary of what was created or changed |
| 221 | + |
| 222 | +## Helper agents |
| 223 | + |
| 224 | +This skill uses the same companion infrastructure as `fusion-app-react-dev`: |
| 225 | + |
| 226 | +- **`fusion-research`** — for source-backed Fusion ecosystem research when portal behavior is uncertain |
| 227 | +- **`fusion-code-conventions`** — for naming, TSDoc, and code style checks |
| 228 | + |
| 229 | +When Fusion MCP is available, prefer `mcp_fusion_search_framework` for portal-specific lookups. |
| 230 | + |
| 231 | +## Safety & constraints |
| 232 | + |
| 233 | +- **MSAL is portal-level** — never configure auth in individual apps; it is hoisted from the portal |
| 234 | +- **Do not invent portal APIs** — only reference APIs confirmed by MCP or documented in references |
| 235 | +- **`Apploader` is experimental** — always mention routing/context limitations when advising on app embedding |
| 236 | +- **No secrets in source** — MSAL client IDs must come from environment variables, not hardcoded |
| 237 | +- **Do not modify the production Fusion portal** — this skill covers custom portal development only |
| 238 | +- **Conventional commits** for all changes |
0 commit comments