---
title: UI Recipes
description: Current recipes for adding pages, system-gated routes, system components, theme tokens, Organization Model sidebar entries, and executable resources.
---
<!-- @generated by packages/sdk/scripts/copy-reference-docs.mjs -- DO NOT EDIT -->
<!-- Regenerate: pnpm scaffold:sync -->


# UI Recipes

## 1. Add a Top-Level Page

Create `ui/src/routes/my-system.index.tsx`:

```tsx
import { createFileRoute } from '@tanstack/react-router'
import { ProtectedRoute } from '@/features/auth'
import { AppShellContentContainer, AppTopbarAdjusterWrapper, PageContainer } from '@elevasis/ui/layout'
import { MySystemPage } from '@/features/my-system/components/MySystemPage'

export const Route = createFileRoute('/my-system/')({
  component: MySystemRouteComponent
})

function MySystemRouteComponent() {
  return (
    <ProtectedRoute>
      <AppTopbarAdjusterWrapper>
        <AppShellContentContainer>
          <PageContainer>
            <MySystemPage />
          </PageContainer>
        </AppShellContentContainer>
      </AppTopbarAdjusterWrapper>
    </ProtectedRoute>
  )
}
```

Add the sidebar entry as a system node in `core/config/organization-model.ts`:

```ts
systems: {
  systems: [
  {
    id: 'my-system',
    label: 'My System',
    enabled: true,
    path: '/my-system',
    icon: 'star',
    uiPosition: 'sidebar-primary'
  }
  ]
}
```

TanStack Router derives the path from the filename. The sidebar is derived from `OrganizationModel.systems`.

## 2. Add an Access-Gated Page

Wrap the route with `AccessGuard` and use the same system path as the org model node.

```tsx
import { AccessGuard } from '@elevasis/ui/auth'

function MySystemRouteComponent() {
  return (
    <ProtectedRoute>
      <AccessGuard accessKey="my-system">
        <AppTopbarAdjusterWrapper>
          <AppShellContentContainer>
            <PageContainer>
              <MySystemPage />
            </PageContainer>
          </AppShellContentContainer>
        </AppTopbarAdjusterWrapper>
      </AccessGuard>
    </ProtectedRoute>
  )
}
```

Set `lifecycle` to an inactive state in the system node to hide or deny access by default. Use `AccessKeys.platformAdmin` with `AccessGuard` for platform-admin-only pages.

## 3. Add a Nested Page

Create a layout file for the section and child route files under the same directory.

```tsx
import { createFileRoute, Outlet } from '@tanstack/react-router'
import { ProtectedRoute } from '@/features/auth'

export const Route = createFileRoute('/reporting')({
  component: ReportingLayoutComponent
})

function ReportingLayoutComponent() {
  return (
    <ProtectedRoute>
      <Outlet />
    </ProtectedRoute>
  )
}
```

Add dotted system nodes for the sidebar hierarchy:

```ts
{ id: 'reporting', label: 'Reporting', enabled: true, uiPosition: 'sidebar-primary' },
{ id: 'reporting.overview', label: 'Overview', enabled: true, path: '/reporting/overview' },
{ id: 'reporting.reports', label: 'Reports', enabled: true, path: '/reporting/reports' }
```

Containers omit `path`; leaves provide `path`.

## 4. Add a System-Scoped Component

Use `ui/src/features/<name>/` when logic is shared across routes or owns local state.

```text
ui/src/features/reporting/
  components/
    ReportingOverviewPage.tsx
    ReportCard.tsx
  hooks/
    useReports.ts
  utils/
    formatReportDate.ts
  types.ts
```

Use `@/*` imports for app-local cross-system imports and keep route layout concerns in route files.

## 5. Change Theme Tokens

Edit `ui/src/config/theme.ts`.

```ts
default: {
  label: 'Default',
  description: 'Project brand theme',
  colors: ['#2563eb', '#080808', '#f2f2f5'],
  dark: {
    primary: '#2563eb',
    primaryContrast: '#ffffff',
    background: '#050507',
    surface: '#0f0f14',
    surfaceHover: '#1a1a22',
    text: '#ffffff',
    textDimmed: '#b0b0c0',
    textSubtle: '#888898',
    border: 'rgba(255, 255, 255, 0.07)'
  }
}
```

All tokens flow into CSS variables. Change `defaultPreset` to alter the initial preset for new users.

## 6. Execute a Resource from a Surface

Declare the resource descriptor in the Organization Model, then derive runtime metadata from that descriptor:

```ts
// core/config/organization-model.ts
import { defineResources } from '@elevasis/core/organization-model'

export const resourceDescriptors = defineResources({
  writeNote: {
    id: 'write-note',
    kind: 'workflow',
    systemPath: 'sys.sales',
    ownerRoleId: 'role-sales-ops',
    status: 'active',
    codeRefs: [
      {
        path: 'operations/src/write-note/index.ts',
        role: 'entrypoint',
        symbol: 'writeNoteWorkflow'
      }
    ]
  }
})

// operations/src/write-note/index.ts
config: {
  resource: resourceDescriptors.writeNote,
  resourceId: resourceDescriptors.writeNote.id,
  name: 'Write Note',
  type: resourceDescriptors.writeNote.kind,
  version: '1.0.0',
  status: 'prod',
  category: 'production'
}
```

Render the deployed workflow with `RunResourceButton`:

```tsx
import { RunResourceButton } from '@elevasis/ui/components'
import { writeNoteInputSchema } from '@core/types'

export function DealPanel({ dealId }: { dealId: string }) {
  return (
    <RunResourceButton
      resourceId="write-note"
      resourceType="workflow"
      label="Write Note"
      getInput={() => ({
        schema: writeNoteInputSchema,
        defaults: { dealId }
      })}
    />
  )
}
```

`resourceDescriptors.writeNote.id` is the single authored ID. `RunResourceButton` still receives the deployed runtime ID. `codeRefs` point agents and operators at implementation files, while `links[].nodeId` binds the resource into the Organization Model graph. `category` drives operational filtering for production, diagnostic, internal, and testing resources.

## Cross-References

- `./feature-flags-and-gating.md` -- system and admin access model
- `./feature-shell.mdx` -- provider and sidebar derivation
- `./customization.md` -- system sidebar customization
- `ui/src/config/README.md` -- theme, background, and loader config
