Architecture

Portal-core contracts

Edit page
Navigation, modules, dashboard widgets, audiences, and policies exposed to feature layers.

PortalFeatureDefinition is the public contract a feature registers with portal core.

interface PortalFeatureDefinition<Action extends string = string> {
  id: string
  navigation?: readonly PortalNavigationItem[]
  modules?: readonly PortalModuleContribution[]
  dashboardWidgets?: readonly PortalDashboardWidget[]
  surfaces?: readonly PortalSurfaceContribution[]
  policy: PortalFeaturePolicy<Action>
}

Audiences

Contributions declare who may see them:

AudienceMeaning
publicNo authenticated session required
authenticatedAny signed-in user
organizationAdminOrganization owner or administrator
adminSystem administrator

Visibility is not authorization. Server routes must still enforce the feature policy.

navigation contributes top-level destinations. modules describe a cohesive area with:

  • a landing route;
  • route prefixes used to detect the active module;
  • an audience and order;
  • a module-specific sidebar menu.

One feature may contribute multiple modules. The timesheets feature, for example, contributes separate Timesheets and Invoices modules while sharing domain data and policies.

Dashboard widgets

A widget declares a registered component plus its placement:

  • area: attention, main, or aside;
  • size: full, half, or third;
  • numeric order.

The UI package sorts all installed widgets, so the dashboard does not import feature components directly. Components are registered by serializable name.

Surface contributions

Surfaces let an optional package contribute a named panel to another package's screen. Timesheets registers an organization panel for administration.organization.detail; Administration renders registered panels without importing Timesheets.

Typed policies

Features define their own action vocabulary and map actions to organization roles:

const actions = ['read', 'create', 'update', 'submit', 'approve'] as const

const policy = {
  owner: actions,
  admin: actions,
  member: ['read', 'create', 'update', 'submit']
}

Server routes pass the policy and requested action to requireFeatureAccess. That adapter authenticates the request, resolves the active organization, checks membership, evaluates the role, and returns tenant context for the query.

Registration behavior

Feature IDs are unique. Registering the same ID again replaces the previous definition, which supports Nuxt development reloads without duplicate navigation or widgets.

For every field and allowed value, see the feature contract reference. For a complete layer workflow, continue with Create a feature layer.