Skip to content

Layers And Capabilities

Chris Michael edited this page Jul 18, 2026 · 2 revisions

Effuse

Layers And Capabilities

defineLayer({ name, services?, store?, extends?, server?, setup? })

Status: Current. The broader framework compatibility contract remains experimental.

A layer is an application capability. It can own services, reactive state, dependencies, lifecycle, components, tracing, API routes, and actions.

Define A Layer

export const AuthLayer = defineLayer({
  name: 'platformAuth',
  services: {
    auth: () => ({
      currentUser: () => ({ id: 'u1', name: 'Chris' }),
    }),
  },
  server: {
    api: {
      '/api/me': ({ services }) => services.auth.currentUser(),
    },
    actions: {
      refreshSession: ({ services }) => services.auth.currentUser(),
    },
  },
});

services is the preferred term. provides remains a compatibility alias.

Composition Root

const app = await createApp(App).useLayers([AuthLayer]);
await app.mount('#app');

The composition root resolves dependencies, initializes services, runs setup, and owns cleanup. It is the only operation that builds the runtime graph.

Component Binding

const ProfileButton = define({
  name: 'ProfileButton',
  layers: { auth: AuthLayer } as const,
  script({ layers: { auth } }) {
    return { user: auth.service('auth').currentUser() };
  },
  template: ({ user }) => <button>{user.name}</button>,
});

The alias auth is local. The runtime identity remains platformAuth.

The equivalent entry properties remain available:

auth.props
auth.services.auth
auth.prop('mode')
auth.service('auth')

For one direct dependency, use useLayer(AuthLayer) or useService(AuthLayer, 'auth') without an alias record.

Registration Invariant

define({ layers }) and defineHook({ layers }) do not auto-register layers. They validate bindings before user script or setup executes. Missing runtime registration raises LayerBindingNotRegisteredError with:

  • component or hook name;
  • local alias;
  • concrete layer name;
  • the app.useLayers(...) registration path.

This avoids mutating an asynchronous layer graph while a nested or lazy route component is executing synchronously.

Dependencies And Lifecycle

Layers may extend compiled layers or declare dependency names. Dependencies are ordered before dependents. Service factories and setup receive a context with props, store, dependencies, service lookup, components, and the complete layer list.

Lifecycle hooks include setup, onMount, onReady, onUnmount, and onError. Setup may return cleanup.

Server Ownership

Layer server configuration supports API routes, actions, middleware, runtime hints, cache/CORS metadata, validation, and diagnostics. See Routing, SSR, And Server APIs.

Failure Rules

  • Duplicate global layer names fail before DOM mount.
  • Missing dependencies produce typed dependency errors.
  • Circular dependencies produce a chain diagnostic.
  • Missing services fail rather than returning a silently unusable binding.
  • Multiple applications dispose and restore their runtime context deliberately.

Related

Clone this wiki locally