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
- Choose the component below and return its typed projection from an actor-authorized App endpoint. Include only visible records and allowed action bindings.
- Import portable projection types from the SDK root and renderers from
/host. Supply loading, error, empty, and read-only states. - Route
onMoveoronActionto 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. - Use
onSelectRangeoronCreateResourceto 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.
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.
| Projection | View | Owner action |
|---|---|---|
| Board | Kanban lanes and cards | Move a card through an App-defined action |
| Calendar | Month, week, day, or list occurrences | Reschedule or resize an occurrence |
| Resource Scheduler | Resource timeline or resource time-grid lanes | Reschedule, resize, or reassign an occurrence; select an empty lane range to start caller-owned creation |
| Schedule | Gantt grid or schedule timeline | Reschedule 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:
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:
| Layer | Responsibility |
|---|---|
| App domain | Own records, domain state, dates, dependencies, permissions, audit, and outbox writes |
| Projection provider | Select actor-visible records and expose only allowed actions |
| Shared contract | Carry stable Resource References, versions, display fields, and typed commands |
| Host renderer | Draw 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.