Skip to content

Building Features

This guide is for teams building feature apps on the Favn micro-frontend platform.

Quick start

bash
# 1. Scaffold a new feature
pnpm run create-feature my-feature

# 2. Develop with hot-reload
pnpm run dev:feature examples/feature-my-feature

# 3. Build and publish locally
pnpm run build
pnpm run publish:local

# 4. Run the host
pnpm run dev:host
# Visit http://localhost:3000/my-feature

Project structure

examples/feature-my-feature/
  manifest.json          # Feature contract (routes, auth, shared deps)
  package.json           # Standard npm package
  vite.config.js         # Vite build config
  vite.config.server.js  # Server functions build config
  scripts/publish.js     # Local publish script
  src/
    main.jsx             # Entry point (bootstraps React)
    App.jsx              # Root component
    actions.server.js    # Server functions (RPC)

Bootstrapping your feature

Every feature entry point follows this pattern:

jsx
// src/main.jsx
import { createRoot } from 'react-dom/client';
import {
  getBootstrapConfig,
  getMountElement,
  registerReactUnmount,
  createFeatureHostApi,
} from '@favn/feature-sdk';
import App from './App.jsx';

const bootstrap = getBootstrapConfig({
  defaultFeatureId: 'feature-my-feature',
  defaultBasename: '/my-feature',
  defaultDomElementId: 'feature-root',
});

const container = getMountElement(bootstrap.domElementId);
const root = createRoot(container);
root.render(<App bootstrap={bootstrap} />);
registerReactUnmount(root, bootstrap.featureId);

registerReactUnmount does two things:

  1. Signals to the host that bootstrap succeeded (disabling the fallback error handler)
  2. Registers cleanup so the host can unmount your feature on page transitions

Shared dependencies

Declare shared deps to avoid bundling React/ReactDOM in every feature:

json
{
  "shared": {
    "react": { "singleton": true, "requiredVersion": "^19.0.0" },
    "react-dom": { "singleton": true, "requiredVersion": "^19.0.0" },
    "react-router-dom": { "singleton": true, "requiredVersion": "^7.1.0" }
  }
}

The host provides these via import maps. Your Vite config should externalize them:

js
// vite.config.js
export default {
  build: {
    rollupOptions: {
      external: ['react', 'react/jsx-runtime', 'react-dom', 'react-dom/client', 'react-router-dom'],
      output: { format: 'esm' },
    },
  },
};

Reuse and data ownership

If you are building reusable UI modules, use featureType: "facet" and keep data orchestration in the consuming domain feature (the feature that owns the route/workflow and mounts the facet).

For patterns and flow diagrams, see Reuse and Data Flow.

Development workflow

Local development with HMR

bash
pnpm run dev:feature examples/feature-my-feature

This starts a standalone Vite dev server with:

  • Hot module replacement
  • Mock host event bus, store, and lifecycle
  • RPC endpoint for server functions with mock ServerContext
  • Shared deps served from workspace

Running against the full host

bash
pnpm run build
pnpm run publish:local
pnpm run dev:host

Validating compatibility

bash
pnpm run validate:compat          # Standard check
pnpm run validate:compat:strict   # Warnings become errors

Error handling

The host provides three layers of error resilience:

  1. Resource load failures — If your JS/CSS fails to load, the host shows a fallback UI with a retry button.
  2. Bootstrap runtime errors — If your code throws during initial render, the host catches it and shows a fallback.
  3. React runtime errors — After successful mount, errors are handled by React's ErrorBoundary. Use @favn/error-boundary for feature-level error boundaries.

The host also caches the last-known-good HTML for each feature path as a fallback.

CI checklist

Before deploying a feature:

  • [ ] pnpm run validate:compat passes
  • [ ] pnpm run lint:routes passes (no route conflicts)
  • [ ] pnpm run doctor passes (manifest schema validation)
  • [ ] Feature manifest has explicit authRequired setting
  • [ ] Server functions enforce authorization checks for write operations

Reference example

See examples/feature-reference/ for a comprehensive example demonstrating all host API integrations, server functions with ServerContext, and team-owned authorization.