---
title: Gate by System or Admin
description: Decision table and recipes for gating routes, sidebar entries, and UI elements by Organization Model system ID or admin role.
---
<!-- @generated by packages/sdk/scripts/copy-reference-docs.mjs -- DO NOT EDIT -->
<!-- Regenerate: pnpm scaffold:sync -->


# Gate by System or Admin

System visibility starts in `core/config/organization-model.ts`. Routes still enforce access with guards.

## Decide the gate

| Scenario | Gate to use |
| --- | --- |
| Surface can be enabled or disabled per organization/member | `SystemGuard` with the system ID |
| Surface is always available to members but restricted to admins | `AdminGuard` plus `requiresAdmin: true` on the system node |
| Surface is both system-gated and admin-only | Both guards, plus `requiresAdmin: true` on the system node |

## System gate in the org model

Add or update the system in the id-keyed `systems` map.

```ts
systems: {
  analytics: {
    id: 'analytics',
    order: 10,
    label: 'Analytics',
    enabled: false,
    path: '/analytics',
    icon: 'custom.analytics',
    uiPosition: 'sidebar-primary'
  }
}
```

Set `enabled: true` to enable it for all members by default. Dotted IDs such as `analytics.reports` inherit system state and shell placement from their ancestors unless they declare their own value.

## Route-level system gate

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

export const Route = createFileRoute('/analytics')({ component: AnalyticsLayout })

function AnalyticsLayout() {
  return (
    <ProtectedRoute>
      <SystemGuard systemKey="analytics">
        <Outlet />
      </SystemGuard>
    </ProtectedRoute>
  )
}
```

The sidebar is derived from `OrganizationModel.systems`; hiding a node there is display behavior only. Keep route guards in place for direct URL access.

## Admin-only route

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

export const Route = createFileRoute('/admin')({ component: AdminLayout })

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

Pair the route guard with the system node:

```ts
systems: {
  admin: {
    id: 'admin',
    order: 10,
    label: 'Admin',
    enabled: true,
    path: '/admin',
    uiPosition: 'sidebar-bottom',
    requiresAdmin: true
  }
}
```

## Per-member override

Membership config overrides enabled state per member.

```ts
{
  systems: { analytics: false }
}
```

Settings and admin-only pages should use admin checks, not per-member system flags.

## Verify

Check the state matrix:

| Org system enabled | Member override | Admin | Expected result |
| --- | --- | --- | --- |
| true | absent | any | Route accessible, sidebar visible |
| true | false | any | Route redirects, sidebar hidden |
| false | absent | any | Route redirects, sidebar hidden |
| true | absent | non-admin | Admin route redirects, admin sidebar hidden |
| true | absent | admin | Admin route accessible, admin sidebar visible |
