Skip to content

Feature SDK

Import from @favn/feature-sdk to interact with host runtime APIs.

Bootstrap

js
import { getBootstrapConfig, getMountElement } from '@favn/feature-sdk';

const config = getBootstrapConfig();
// { featureId, version, basename, domElementId, hostVersion }

const container = getMountElement(config.domElementId);
// Returns the correct mount element (handles Shadow DOM automatically)

Host API

js
import { createFeatureHostApi } from '@favn/feature-sdk';

const api = createFeatureHostApi('feature-my-feature');

Event Bus

Publish events to other features and subscribe to cross-feature communication:

js
// Publish
api.eventBus.publish('my-feature', 'patient-selected', { id: '123' });

// Subscribe
const unsub = api.eventBus.subscribe('navigation', 'route-changed', (event) => {
  console.log('Route changed:', event);
});
// Call unsub() to unsubscribe

Host Store

Read and write shared global state:

js
// Read
const locale = api.store.get('locale', 'en');
const theme = api.store.get('theme', 'light');

// Write
api.store.set('locale', 'nb');

// Subscribe to changes
const unsub = api.store.onChange('locale', (value) => {
  console.log('Locale changed:', value);
});

Lifecycle

Register cleanup handlers and track timers:

js
// Runs when the host unmounts your feature
api.lifecycle.onCleanup(() => {
  console.log('Cleaning up...');
});

// Auto-cleared on unmount
api.lifecycle.trackInterval(
  setInterval(() => console.log('tick'), 1000)
);

Shadow DOM

If your feature needs CSS isolation, set isolation.shadowDOM: true in your manifest.

js
import { getFeatureShadowRoot } from '@favn/feature-sdk';

const shadowRoot = getFeatureShadowRoot();
// null if Shadow DOM is not enabled
// ShadowRoot if enabled — use for dynamic style injection

When Shadow DOM is enabled:

  • Your CSS files are injected into the shadow root (not <head>)
  • getMountElement() returns the inner element inside the shadow root
  • Global styles from the host won't affect your feature
  • Your styles won't leak to other features

Capability enforcement

The host wraps all runtime APIs to enforce your manifest's runtime.permissions declarations. Denied operations:

  • Log warnings in browser console
  • Return safe values (false, noop, undefined) rather than throwing

Reusable modules

The host also exposes a module registry for featureType: "facet" manifests ("module" alias is also accepted).

js
import { listModules, mountModule, unmountModule } from '@favn/feature-sdk';

const modules = listModules();
// [{ id, displayName, version, entrypoint, mountExport, unmountExport, ... }]

const target = document.querySelector('#summary-slot');
await mountModule('feature-summary-module', target, {
  patientId: '123',
  locale: 'nb-NO',
});

// Later
await unmountModule('feature-summary-module', target);

Module contract:

  • mountExport defaults to mount
  • unmountExport defaults to unmount
  • mountModule() calls the mount export with (target, props)
  • unmountModule() calls the unmount export with (target, mountHandle)