Skip to content
Guide

Use the frontend SDK

Use the frontend SDK

Use the frontend SDK

Edit generated screens

Start with ListSurface.tsx for lists and RecordSurface.tsx for read, create, and edit forms. Types and queries live in the same resource directory.

NeedSDK component
Page title and actionsNxPageFrame
Form sections and fieldsNxFormSection, NxFormField
Text inputNxTextInput
Read-only detail valuesNxDetailRow

Retain the scaffold's imports and state handling when adding inputs. The field example connects input, saving, details, and lists.

Adding a field

  1. Update request and response types.
  2. Connect input state, initial values, and validation errors.
  3. Include the value in the save request.
  4. Show it in details and lists.
  5. Reopen or refresh after saving to verify persistence.

Preserve existing behavior

  • Use generated SDK clients and queries for API calls.
  • Handle duplicate submission, invalid input, and denied access.
  • Keep unsaved-input confirmation when leaving a screen.
  • Keep secrets out of frontend bundles, read responses, and form drafts.
  • Verify narrow layouts and real data even when using shared components.

Edit App screens · Test an App

Verify the changed screen

Code example
Shell
npm run build

Then open the App in its sandbox. Save a changed value, reopen the record and check the stored value. Check invalid input, denied access and navigation with unsaved input; a successful build does not cover those interactions.

Find exact component props and hooks

The installed package is the versioned reference; no Core checkout is needed. Use your editor's Go to definition on these imports, or read node_modules/@nexia/sdk/dist/index.d.ts and host.d.ts after npm install. Follow their relative declarations for each component. Do not copy a Core-private component path into App imports.

TaskPublic host API / type
Page-owned organization filteruseOrganizationListScope, NxPageFrame.organizationScope
Create target / stored ownerNxResourceFormLegalEntityField with the generated select/stored mode
List and record viewsPreserve generated ResourceTable, resource contract, ListSurface and RecordSurface adapters
Board, Calendar, Scheduler, ScheduleResourceBoard, NxCalendar, NxResourceScheduler, ResourceSchedule; projection guide
Profile widgetProfileSlotPropsV2; slot guide
Approval formApprovalBusinessFormSlotPropsV2, approvalComposerBusinessFormRegistry; Approval guide
Refresh after a projection eventuseResourceProjectionChange; refetch through the same authorized API

Types and portable contracts come from @nexia/sdk; host-bound renderers and hooks come from @nexia/sdk/host. Follow the existing generated app-scoped client and host registration. Do not create a second React root or install an unrelated router.

For a mutation, preserve generated query keys and organization context, prevent duplicate submission, map server validation to fields, and refetch/invalidate only affected records after success. A denial must clear protected content, not leave stale data under an error banner. Empty state is a successful empty response; loading, permission denial and network failure are different states.

App transport and host routes

The SDK api is bound to the calling App. Development frames and installed Apps enforce the same route policy. Prefer organization-target and Resource Reference hooks for scoped choices. Explicit Core host routes retain their normal permissions: tenant-wide organization reads and creation, party duplicate lookup, user provisioning and invitations, and the actor's profile. They do not grant access to arbitrary Core endpoints. Mail throttles still apply.

sendUserInvitation and useDataMigrationBackgroundOperation use this same App-bound transport. Background tickets require both the originating App and actor. APP_HOST_ROUTE_UNAVAILABLE means that a route is unsupported, distinct from a server-side business permission denial. Do not bypass it with a global HTTP client. Test through a real App frame or installed surface; mocked responses or direct HTTP requests alone do not verify this boundary. These paths require the Core host fix; updating the SDK alone does not add server capabilities.

Shared document field picker

NxDocumentDataFieldPicker from @nexia/sdk/host uses the same column browser as Signature and Business Process choices. Pass open, onClose, title, loadPage(filters) and onSelect(item). The App supplies an authorized backend endpoint that delegates to DocumentDataHost::catalog with its fixed purpose and subject type. Do not let browser input select a more privileged purpose.

loadPage receives stage: apps|sources|fields, optional app_key, source_key, source_version, q, offset, and limit. Return {data, next_offset}; optional local_fields: [{source, label_key}] describe App-owned request inputs such as free text. Metadata items carry App/source labels, a field descriptor, synthetic sample and the exact field binding. Selection returns that item or {local_source, label} for a local input. isDisabled(item) can enforce the consumer's layout constraints; validate those constraints again on save.

The picker loads each level on demand, searches on the server, supports more results and retry, and ignores superseded responses. It accepts scalar/date and Resource-label fields; richer value types need their own document renderer. Save the returned binding rather than a label or list position. Host adoption requires React SDK 0.8.13 and Core 0.8.152 or later. buildAppCatalogTree is also exported from @nexia/sdk for authorized in-memory catalogs that need the shared App Family → App → item grouping; it does not load data or authorize choices.

Dedicated lookup fields

Use NxLookupField from @nexia/sdk/host for a field that opens a record lookup. NxCombobox now owns only popover list selection. The earlier draft NxCombobox presentation="dialog" API and its lookup-only props are removed. Available with React SDK 0.8.13 and Core 0.8.152 or later. Adopt both before using the field; migrate the earlier dialog-only combobox props as shown below.

NxLookupField displays the applied value and opens the shared NxLookupDialog. It supports typed string/number values, single/multiple selection, create continuation, refresh, and optional selected-item chips. Single selection applies and closes immediately. Multiple selection stays in a draft until Apply; onChange(values, options) returns the complete chosen values and options, including ([], []) when cleared. Cancel preserves the applied value.

The resource owner supplies authorized options, columns, optional getCells (or each option's cells), filters, advancedFilters, activeFilterCount, and actions. Additional buttons belong in actions; the shared component retains Apply/Cancel. API calls, permissions, filter state, debounce and server sorting remain with the owner. sort/onSortChange expose sortable headers; they do not sort a loaded page. createAction and resourceCreateContinuation keep the existing create-and-return contract.

Supply pagination={{ page, pageSize, total, onPageChange }} for a server page. Without pagination, only the supplied collection is searched/paged locally in groups of 25; this does not fetch missing records. Controlled search uses searchValue/onSearchChange; the owner resets server pages when scope, filters or search change. Controlled search is retained on close, while local search is cleared. Optional open/onOpenChange can enable a query only while open. Provide loading, error, and onRetry for changing pages and recovery. Provide selectedOptions for applied choices absent from the initial page; applied labels are retained across subsequent page changes. Values remain the source of truth. Scope changes must clear unauthorized selections in the owner.

For a page scope with mode="legal-entity-operating-unit-list", set operatingUnitPicker="lookup" on NxOrganizationTargetSelector to use a lookup dialog for Operating Units while preserving the Legal Entity selector. This is a fixed choice made by the page, independent of result count. Exact pairs, authority checks and URL query handling are unchanged. Use the matching SDK and Core host; omitting this optional prop retains the existing picker.

Earlier draft propNxLookupField prop
presentation="dialog"Remove; the component always opens a dialog
lookupColumns / lookupCellscolumns / getCells
lookupFilters / lookupAdvancedFiltersfilters / advancedFilters
lookupActiveFilterCount / lookupErroractiveFilterCount / error
Multi onChange(values, changedOption)onChange(values, selectedOptions)

NxLookupDialog remains available for composition that already owns its trigger. Current-page select-all never means every matching record on the server.

Table-context exports

Pass transferMeta to ResourceTable to carry visible data columns into the shared export flow. ResourceTableColumn.exportKey optionally maps a stable UI column key to its export schema key; it defaults to key. Action columns are excluded. The selected order is retained. With React SDK 0.8.17 and Core 0.8.170, permission-excluded fields are identified and unsupported schema fields show a warning. Only available, authorized selected fields are exported; at least one field must remain selected.

Include validated filter context in the advertised export action URL. The host preserves search, sort, filter[...], and table_filter[...], but omits pagination. The App export source must validate those filters again and apply the same authorization and filtering as its table across all pages. This mapping is available with React SDK 0.8.14 and Core 0.8.159 or later.

Table menu commands and excluded fields

React SDK 0.8.17 adds optional ResourceListToolbarConfig.moreItems (NxDropdownMenuItem[]) for App commands in the standard menu. Use the matching Core 0.8.170 host so export, print and column controls remain available; the earlier more slot remains supported.

Transfer metadata may declare export_restricted_columns: [{ key, label }] to explain field permission exclusions. The host excludes those fields, warns about unsupported schema fields and retains the permitted column selection. Export sources must still validate filters and authorize rows and fields on every page. Verify allowed/excluded/missing columns and menu actions with the real actor. See the React SDK artifact and import/export guide.

Date filters and record print layouts

React SDK 0.8.14 with Core 0.8.159 supports a meta.list_schema.filterable entry with kind: "dateRange", multiple: false and options: []. Its value is one YYYY-MM-DD..YYYY-MM-DD string; either bound can be empty. Preserve URL state, validate date order and apply the same authorized filter before pagination and export. Omitted kind keeps categorical options. Ordinary categorical filters should explicitly use multiple: true.

React SDK 0.8.15 adds recordPrint: { label, title, columnKeys } to resource table/transfer props. Use stable keys from the authorized columns and the compatible Core host; Core 0.8.173 supports it. This is an optional record layout alongside the list layout, not permission to print hidden fields. Verify the actual actor's print and export results as well as empty/error states.

See the React SDK 0.8.14 note, 0.8.15 note and import/export guide.

Read-only POST queries

React SDK 0.8.16 and Core 0.8.167 support NEXIA_READ_ONLY_HEADER from @nexia/sdk or @nexia/sdk/host. Use it only on a POST that performs no mutation. Pass the following config as the third argument to the existing App-owned api.post preview call. Keep that call's actual route and input:

Code example
TSX
import { NEXIA_READ_ONLY_HEADER } from '@nexia/sdk/host';

const previewRequestConfig = {
    headers: { [NEXIA_READ_ONLY_HEADER]: 'true' },
    timeout: 30_000,
};

The host applies read semantics and forwards transport failure instead of placing the query in uncertain-write recovery. It does not make a mutating handler safe or authorize a denied route; keep server validation and permissions. Never send the header for saves. Verify success, a blocked request, error presentation and retry after unblocking without changing business records. See the React SDK declaration and Core read handling.

Published React package · Shared document data

Source of truth: docs/developers/content/en/app-sdk/frontend-host-contracts.md