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.
| Need | SDK component |
|---|---|
| Page title and actions | NxPageFrame |
| Form sections and fields | NxFormSection, NxFormField |
| Text input | NxTextInput |
| Read-only detail values | NxDetailRow |
Retain the scaffold's imports and state handling when adding inputs. The field example connects input, saving, details, and lists.
Adding a field
- Update request and response types.
- Connect input state, initial values, and validation errors.
- Include the value in the save request.
- Show it in details and lists.
- 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
npm run buildThen 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.
| Task | Public host API / type |
|---|---|
| Page-owned organization filter | useOrganizationListScope, NxPageFrame.organizationScope |
| Create target / stored owner | NxResourceFormLegalEntityField with the generated select/stored mode |
| List and record views | Preserve generated ResourceTable, resource contract, ListSurface and RecordSurface adapters |
| Board, Calendar, Scheduler, Schedule | ResourceBoard, NxCalendar, NxResourceScheduler, ResourceSchedule; projection guide |
| Profile widget | ProfileSlotPropsV2; slot guide |
| Approval form | ApprovalBusinessFormSlotPropsV2, approvalComposerBusinessFormRegistry; Approval guide |
| Refresh after a projection event | useResourceProjectionChange; 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 prop | NxLookupField prop |
|---|---|
presentation="dialog" | Remove; the component always opens a dialog |
lookupColumns / lookupCells | columns / getCells |
lookupFilters / lookupAdvancedFilters | filters / advancedFilters |
lookupActiveFilterCount / lookupError | activeFilterCount / 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:
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.