Skip to content
Guide

Resource projections

Understand the shared Board, Calendar, Resource Scheduler, and Schedule views, their App-owned action and creation boundaries, and their current SDK availability.

Show App records as a Board, Calendar, Resource Scheduler, or Schedule using SDK React components.

Connect a view to your App API

  1. Choose the component below and return its typed projection from an actor-authorized App endpoint. Include only visible records and allowed action bindings.
  2. Import portable projection types from the SDK root and renderers from /host. Supply loading, error, empty, and read-only states.
  3. Route onMove or onAction to an App-owned mutation. Recheck organization, current permission, expected version, idempotency, and the domain rule on the server; return the authoritative accepted projection or a rejection.
  4. Use onSelectRange or onCreateResource to open an App-owned create flow, then refetch after its successful save.

Start with a read-only Board adapter. Its caller supplies the authorized projection and localized labels; an empty lanes array represents an empty result. Add onMove only after implementing the protected mutation.

Code example
TSX
import type { ResourceBoardProps } from "@nexia/sdk";
import { ResourceBoard } from "@nexia/sdk/host";

type BoardViewProps = Pick<
    ResourceBoardProps,
    "projection" | "state" | "labels" | "onRetry" | "onOpenResource"
>;

export function BoardView(props: BoardViewProps) {
    return <ResourceBoard {...props} readOnly />;
}

Confirm the result

A permitted gesture updates the record and projection; denied or stale writes restore the authoritative view. Selecting empty space opens creation but does not persist a record by itself. Follow Build an App screen for surface registration and Test an App for checks.

Components and interaction contracts

A Resource projection presents App-owned records in a shared non-list view. The host supplies the renderer and transport shape; the owning App remains responsible for selecting visible records and performing every business action.

ProjectionViewOwner action
BoardKanban lanes and cardsMove a card through an App-defined action
CalendarMonth, week, day, or list occurrencesReschedule or resize an occurrence
Resource SchedulerResource timeline or resource time-grid lanesReschedule, resize, or reassign an occurrence; select an empty lane range to start caller-owned creation
ScheduleGantt grid or schedule timelineReschedule work or create/delete a dependency

The public frontend boundary exposes pure projection types at the package root and lazily bound React renderers at /host. This import is backed by packages/app-sdk/packages/react/src/resources/resource-projections.ts and packages/app-sdk/packages/react/src/host.ts:

Code example
TSX
import type {
    NxCalendarOccurrence,
    NxResourceSchedulerActionCommand,
    NxResourceSchedulerOccurrence,
    NxResourceSchedulerResource,
    NxResourceSchedulerSelection,
    ResourceBoardProjection,
    ResourceScheduleProjection,
} from "@nexia/sdk";
import {
    NxCalendar,
    NxResourceScheduler,
    ResourceBoard,
    ResourceSchedule,
} from "@nexia/sdk/host";

Each component receives an actor-authorized projection, and a typed callback crosses back to the App for a mutation. The current design owner is docs/reference/RESOURCE-PROJECTIONS.md.

How it fits

All four projections follow the same ownership flow:

LayerResponsibility
App domainOwn records, domain state, dates, dependencies, permissions, audit, and outbox writes
Projection providerSelect actor-visible records and expose only allowed actions
Shared contractCarry stable Resource References, versions, display fields, and typed commands
Host rendererDraw Board, Calendar, Resource Scheduler, or Schedule and apply reversible optimistic feedback

After an owning App commits a projection that consumers may already have cached, it may publish ResourceProjectionChanged::draft(...). The resource.projection.changed.v1 payload contains only the canonical App key, Resource key, and public record id under an explicit Legal Entity scope. Frontend consumers use useResourceProjectionChange() for that exact identity and refetch through their authorized API. The event carries no display data and grants no authority.

A projected record crosses the boundary as a Resource Reference containing an App key, Resource key, public record identity, display value, and optional owner route. The projection does not expose an Eloquent model or grant access to the record behind the reference.

Board lanes declare which action keys they accept. Calendar occurrences may be fully visible, redacted to neutral busy time, or omitted. Schedule items carry task or milestone dates, progress, optional baseline and actual dates, and dependency references. The provider has already filtered every item and action for the active actor and optional Legal Entity context before the renderer sees them.

Resource Scheduler uses NxResourceSchedulerResource for its lanes and NxResourceSchedulerOccurrence for occurrences. Each occurrence carries resource_ids and typed allowed-action bindings. Moving within a lane emits a reschedule command, changing duration emits resize, and moving to another lane emits reassign. Selecting an empty range calls onSelectRange with an NxResourceSchedulerSelection containing start, end, all_day, timezone, and resource_ids. The callback may seed the App's creation UI, but the renderer does not create or persist an occurrence.

Calendar exposes the same caller-owned boundary without resource lanes through NxCalendarProps.onSelectRange. Schedule exposes ResourceScheduleProps.onCreateResource, optionally with a parent Resource Reference. These callbacks open caller-owned creation flows; they do not add a default endpoint or transfer domain ownership to Core.

Boundaries

The SDK publishes component facades and TypeScript contracts, not the concrete renderers. Core keeps NxCalendar, NxResourceScheduler, ResourceBoard, and ResourceSchedule behind its own aliases and binds them lazily during host configuration. App Packages import only @nexia/sdk and its /host subpath; importing @shared/* or @shell-primitives/* is still forbidden.

The components also provide no default endpoint. An App must load its own actor-authorized projection and implement the typed onMove or onAction callback against an App-owned API operation. onSelectRange and onCreateResource likewise open App-owned creation flows. The renderer never turns a drag or selection gesture into a generic field patch or persisted record.

Backend provider interfaces remain host-only under App\ResourceBoard, App\ResourceCalendar, and App\ResourceSchedule; they are not public Nexia\* contracts. Resource Scheduler adds no public PHP provider interface; it uses the public frontend occurrence/resource contracts with an App-owned API. No production provider registry currently installs one. An App can use the public React components with its own API, but it must not implement or import those Core PHP interfaces.

Board is also not Business Process. It visualizes projected state and offers owner actions; BPMN Process owns long-running execution. Schedule Timeline is a planned-work view, while an activity timeline is chronological evidence and has no projection action contract.

Source of truth: docs/developers/content/en/platform-extensions/resource-projections.md