Skip to content
Guide

Build an App screen

Customize the generated Note screen using SDK host components.

Build an App screen

Keep Note's status visible on narrow lists. After Create a Resource, open resources/js/resources/notes/section/NoteListSection.tsx from the App root. In noteColumns(), replace the existing status column with:

Code example
TSX
{
    key: 'status',
    header: t('workshop.note.status.label'),
    size: 'meta',
    priority: 1,
    cell: (row) => (
        <ResourceStatusBadge
            resourceKey="workshop.note"
            field="status"
            status={row.status}
        />
    ),
},

The generated file already imports ResourceStatusBadge. priority: 1 keeps this column visible when ordinary metadata columns collapse. Keep its stable key and descriptor-backed badge; a display change needs no migration or Composer update.

Verify

Reload Workshop's Note list and narrow the window. Status should remain visible, and selecting a readable row should still open its Inspector. Check a user without read permission receives the existing denied-access view.

To add a new field to form, detail, Inspector and list, continue with the complete Data Model and Migrations.

Keep route and display responsibilities separate

App-relative locationResponsibility
resources/js/resources/notes/note-resource-contract.tsRecord types, permission keys, ResourceRefs and route builders
resources/js/resources/notes/surface/Queries, URL state, mutation errors, authorization and completion
resources/js/resources/notes/section/List, form and detail presentation
resources/js/resources/notes/inspector/Inspector registration and composition
resources/js/index.tsApp frontend entry and discovery

Use #app/ for App-local imports. Import public types from @nexia/sdk and host components from @nexia/sdk/host. Core aliases such as @/, @shell/ and @shared/ui are not App APIs.

Preserve the generated interaction

The form already handles required names, server field errors, unsaved changes, create completion and navigation. Add fields to that flow rather than replacing it with a raw submit handler. Resource IDs and route builders belong in the contract file. Keep cache keys tenant-specific and include the list's selected targets.

The list uses meta.list_schema for supported filters and sorting, ResourceTable for table controls and response actions for permitted affordances. Preserve loading, empty, error/retry and permission states. A stable tableId identifies saved view preferences; do not localize it.

For a Legal Entity list, keep useOrganizationListScope in the route surface and render its selector in NxPageFrame.organizationScope. A create form chooses one target; detail and edit display the stored owner. Standard tenant-owned common data has no organization selector. For LE/OU list modes, a frame example, and the shared Legal Entity/Operating Unit form controls, see React components and hooks.

Register a standalone destination

If the page does not represent Note, register it through the App entry and declare an App-owned navigation contribution. Use React components and hooks for exact route, lazy registration, prefetch and component signatures. A registered route does not automatically create a menu item or grant access.

After a new frontend entry is activated, restart Vite. After changing contribution or route declarations, run task artisan -- nexia-runtime:refresh-runtime-caches from the Core root. Ordinary section edits use the running development server.

Check the experience

Use keyboard navigation, submit invalid input, cancel an unsaved edit, reload a filtered list and open a record without permission. See Test an App for focused checks. Reuse SDK controls so labels, errors, focus and loading behavior remain consistent.

Source of truth: docs/developers/content/en/building-apps/build-a-frontend-surface.md