Skip to content

Reuse and Data Flow

This page defines how to build reusable features in Favn without blurring ownership boundaries.

Core model

Favn supports two feature shapes:

  • featureType: "domain": route-mounted feature that owns a URL surface.
  • featureType: "facet": reusable CSR feature loaded by another feature through @favn/feature-sdk.

Legacy aliases are still accepted for compatibility:

  • application -> domain
  • module -> facet

Important: both are still "features". The difference is role, not product maturity.

Terminology

  • Domain feature: a featureType: "domain" feature that owns URL, page flow, and composition for a route.
  • Facet module: a featureType: "facet" feature that is embedded and reused by domain features.
  • Data owner: the feature that decides what data to fetch, normalize, and pass into composed modules.

Recommended default for reuse:

  • Keep data ownership in the consuming domain feature.
  • Keep facet modules UI-focused and prop-driven.
  • Let each team decide business authorization in its own backend and server functions.

Ownership boundaries

Host owns

  • Manifest discovery, signature/integrity verification, and runtime loading.
  • Routing for domain features.
  • Transport/authentication plumbing for RPC (/rpc/:feature/:fn).
  • Capability-scoped runtime APIs (event bus, host store, lifecycle wrappers).

Feature team owns

  • Business rules and authorization semantics.
  • Data contracts and backend integrations.
  • Redaction policy and domain-level security behavior.
  • UI composition inside each feature.

Reuse-first data pattern

Use this when you want strong reuse across applications.

  1. Domain feature fetches and normalizes data.
  2. Domain feature mounts one or more facet modules.
  3. Domain feature passes required input via props.
  4. Facet module emits user intent back to the domain feature (callbacks or event bus).
  5. Domain feature decides what to persist/call next.

Benefits:

  • Reusable facet modules stay independent from domain-specific data services.
  • Reuse across multiple domain features is straightforward.
  • Data/security policy remains explicit and domain-feature-owned.

Feature-owned data pattern

Use this when the feature is a full vertical slice.

  1. Route-mounted domain feature renders.
  2. Feature calls its own server functions through host RPC transport.
  3. Feature server logic enforces business authorization and data policy.

Benefits:

  • Strong team autonomy.
  • Clear end-to-end ownership for a domain slice.
  • Works well for independently deployed product areas.

Choosing between the two

Choose domain-feature-owned data with facet modules when:

  • Multiple domain features need the same UI behavior.
  • Data shape differs per domain context.
  • You want a clean separation between presentation and orchestration.

Choose feature-owned data when:

  • One team owns both UI and backend for a full domain slice.
  • The feature is primarily route-based, not embedded.
  • Reuse pressure is low.

Implementation checklist

  • Decide feature shape early (domain or facet).
  • For facet modules, expose a stable mount contract (mount/unmount or custom names).
  • Keep facet props explicit and versioned.
  • Avoid hidden data access in facet modules unless intentionally domain-coupled.
  • Keep business authorization in feature-owned services/server functions.
  • Document data contracts between domain features and facet modules.

Practical APIs

  • Module discovery/mounting: listModules(), mountModule(), unmountModule()
  • Runtime host APIs: createFeatureHostApi()
  • Manifest contract details: Manifest Contract
  • SDK details: Feature SDK