iolite/Nebula

Components as Query Refiners

Components in Nebula aren't just data containers — they're query surface area. Every component you add to an entity changes which systems can see it. This means adding a component isn't just storing information; it's routing the entity into new processing pipelines. The entity's component composition determines its visibility across the entire system.

The Scenario

Your application processes healthcare accounts through a multi-stage pipeline. An account starts with basic data and gradually accumulates components as different systems analyze it. At each stage, new systems "light up" and begin processing the account — not because they were told to, but because the entity now matches their queries.

The Pattern

Design your components so that each one represents a meaningful stage of processing. Systems declare queries that match entities at their required stage. When an entity gains the right components, it automatically enters the next system's scope.

Entity StateAccount + Customer+ DenialOpportunity+ DenialPriority+ LocationMatchSystems That MatchTeamAssignmentreceived('DenialOpportunity')PriorityScoringhas('DenialOpportunity')WorkQueue UIhas('DenialPriority')LocationReportshas('LocationMatch')

Stage 2: DenialOpportunitySystem

and
hasAccount
hasCustomer
notDenialOpportunity
hasDenialOpportunity
child
hasClaim

Stage 3: DenialPrioritySystem

and
hasAccount
hasCustomer
hasDenialOpportunity
hasAppealTimelyFiling

The same pattern works on the frontend. React components subscribe to queries that match entities at specific stages:

DenialWorkQueue (frontend)

and
hasAccount
hasDenialPriority

In Practice

Here's the timeline of a single Account entity as it accumulates components:

  1. Ingestion — Entity has Account + Customer. Visible to basic account listings, invisible to the denial pipeline.
  2. Denial detection — System adds DenialOpportunity. The account is now visible to TeamAssignment (via received('DenialOpportunity')) and to PriorityScoring.
  3. Priority scoring — System adds DenialPriority. The account now appears in the work queue UI, which queries for has('DenialPriority').
  4. Location matching — System adds LocationMatch. Location-based reports can now include this account.

Each component addition is a state transition. No explicit state machine is needed — the entity's component composition is its state, and the query engine is the router.

Why This Works

Traditional architectures use status fields, state machines, or message routing to control which systems process an entity. This requires explicit wiring: "when status changes to X, notify system Y."

In Nebula, systems are self-selecting. Each one declares what it needs, and the platform handles routing. Adding a component to an entity is like flipping a switch that makes it visible to every system that cares about that component. No dispatch table, no event bus, no subscription management — just data composition and declarative queries.


Behaviors explains how system queries work. Lightweight Tags covers zero-field components used purely for filtering. Relationship Patterns shows how links add another dimension of queryable state.