Change the admin menu

List your app's admin links in CUSTOM_NAV, in src/custom/nav.ts: they appear in the admin side menu just before Profile, translated like the core items. To change, hide, add or move items anywhere in the menu, Arc CMS's own included, use CUSTOM_NAV_CHANGES in src/custom/nav-changes.ts (Change Arc CMS's items).

The menu only shows links. Who may open a page is decided by its route guard alone (Who may open a page). Hiding an item does not keep anyone out of its page, and showing one to a role does not let that role in.

Add an item

  1. Add the item to src/custom/nav.ts:

    import type { MenuItem } from '../shared/components/side-navbar/side-navbar.component';
    
    export const CUSTOM_NAV: MenuItem[] = [
      {
        label: 'Lessons',
        labelKey: 'custom.nav.lessons',
        route: '/admin/lessons',
        icon: 'fa-solid fa-book-open',
        allowRoles: ['admin'],
      },
    ];
  2. Add the label to src/custom/i18n/en.json, and the same key to src/custom/i18n/hi.json:

    { "custom": { "nav": { "lessons": "Lessons" } } }
  3. Make sure the route exists. An admin page needs an explicit route with the admin shell (Add an admin page). npm run test fails on an item whose address no route serves, yours or Arc CMS's.

The fields of an item

FieldFor
idThe item's identity, unique in the menu: what CUSTOM_NAV_CHANGES names. Optional for your own items; give one to an item you want to change for some roles
labelThe English label, shown when there is no labelKey
labelKeyThe translation key shown instead of label
routeThe address the item opens
externalUrlAn outside address, opened in a new tab, instead of route
iconFont Awesome classes, such as fa-solid fa-book-open
allowRolesThe roles that see the item, such as ['admin'] or ['admin', 'user']
subItemsItems shown under this one, which makes it a group that opens and closes
queryParamsQuery parameters added to the item's link
separatortrue for a dividing line instead of a link (give it label: '' and allowRoles)
featureA feature id: the item is left out when that feature is off

An item without allowRoles is never shown, for anyone. Set it on every top-level item. Sub-items are shown to whoever sees their group.

The menu finds Profile and Logout by their id, and clicking the item with the id logout opens the sign-out dialog. Never give your own item a core item's id: the test suite fails on it. A group's open or closed state is kept by its id, or by its label when it has none, so give every group of yours an id or a unique label.

Group items

export const CUSTOM_NAV: MenuItem[] = [
  {
    label: 'Classroom',
    labelKey: 'custom.nav.classroom',
    icon: 'fa-solid fa-school',
    allowRoles: ['admin'],
    subItems: [
      { label: 'Lessons', labelKey: 'custom.nav.lessons', route: '/admin/lessons', icon: 'fa-solid fa-book-open' },
      { label: 'Classes', labelKey: 'custom.nav.classes', route: '/admin/classes', icon: 'fa-solid fa-users' },
    ],
  },
];

A group opens by itself when the current page is one of its sub-items.

Hide an item when a feature is off

Set feature on an item or a sub-item that only makes sense with that feature (Choose your app's features):

{ label: 'Refunds', labelKey: 'custom.nav.refunds', route: '/admin/refunds', icon: 'fa-solid fa-rotate-left',
  allowRoles: ['admin'], feature: 'payments' },

A group whose sub-items all go goes with them.

Where the items appear

Your items are placed together, in the order you list them, just before Profile, with a dividing line before Profile. To put one somewhere else, give it an id and move it with CUSTOM_NAV_CHANGES, or add it there with CUSTOM_NAV_CHANGES instead. The menu shows only the items whose allowRoles include the signed-in person's role.

Change Arc CMS's items

Fill in CUSTOM_NAV_CHANGES in src/custom/nav-changes.ts. Its admin list changes the admin menu; its member list changes the member menu the same way (Change the member menu). Each change names an item by its id (The admin menu's ids), never by its label, which is translated:

import type { NavChanges } from '../app/core/nav/nav-changes';

export const CUSTOM_NAV_CHANGES: NavChanges = {
  admin: [
    // Dashboard opens the app's own page
    { id: 'dashboard', route: '/admin/extension-dashboard' },
    // Media Manager is gone from the menu
    { id: 'media', hide: true },
    // Users is reworded with the app's own key
    { id: 'users', labelKey: 'custom.nav.people' },
    // A new item just after Dashboard, for admins and editors
    { add: { id: 'reports', label: 'Reports', labelKey: 'custom.nav.reports', route: '/admin/reports',
             icon: 'fa-solid fa-chart-line', allowRoles: ['admin', 'editor'] }, after: 'dashboard' },
    // Settings moves to the top, for admins only
    { id: 'settings', before: 'dashboard', roles: ['admin'] },
  ],
};

Older copies of Arc CMS had CUSTOM_NAV_CHANGES in src/custom/nav.ts, and that file still ships it, empty. If your app wrote its changes there, they still work: Arc CMS applies the ones in nav.ts first, then the ones in nav-changes.ts. Move them to nav-changes.ts when you next touch the menu, and leave nav.ts's CUSTOM_NAV_CHANGES empty.

A change can:

ToWrite
Change an item{ id, ...fields } with any of route, queryParams, externalUrl, icon, label, labelKey and allowRoles
Hide an item{ id, hide: true }
Add an item{ add: item, before: id }, { add: item, after: id }, or { add: item } for the end of the menu. The item takes the fields above and needs an id of its own
Move an item{ id, before: id } or { id, after: id }
Do any of these for some roles onlyAdd roles: ['editor'] to the change (below)

How the changes are made:

Change the menu for some roles

A change with roles applies only when the signed-in person's role is one of them. Without roles it applies to every role. This is how one app shows admins, editors and its own roles different menus:

admin: [
  // Editors see Media Manager, without Settings
  { id: 'media', allowRoles: ['admin', 'editor'], roles: ['editor'] },
  { id: 'settings', hide: true, roles: ['editor'] },
  // Profile and Logout for editors too
  { id: 'profile', allowRoles: ['editor'] },
  { id: 'logout', allowRoles: ['editor'] },
],

The menu shows an item to the roles in its allowRoles; roles on a change decides who the change is for. Each page an editor can now see in the menu still needs a route guard that lets editors in: the menu never gives anyone access.

What the test suite checks

npm run test (in src/app/custom-space.spec.ts) reads your src/custom/nav.ts and src/custom/nav-changes.ts and fails, with the list of valid ids, on:

The admin menu's ids

Arc CMS's items and their ids, in menu order. Each signup form's own group and each content type's link are built from your data and have no id.

IdItemOpensSub-items
dashboardDashboard/admin/dashboard
signup-formsSignup Forms/admin/waitlists
mediaMedia Manager/admin/media
contentContentcontent-types (Content types), authors (Authors)
usersUsers/admin/users
audienceAudiencecontacts (Contacts), lists (Lists), contact-tags (Tags), contact-fields (Fields), app-users (App users)
emailEmail + SMSbrand-kit (Brand Kit), composer (Composer), broadcasts (Broadcasts), drip-campaigns (Drip Campaigns), announcements (Announcements), email-logs (Email Logs), sms-logs (SMS Logs)
feedbackFeedback/admin/feedback
messagesMessages/admin/messages
productsProducts/admin/products
transactionsTransactions/admin/transactions
dataDataexport-data (Export Data), import-data (Import Data), export-files (Export Files), import-files (Import Files)
profileProfile/admin/profile
settingsSettings/admin/settings
aboutAbouthttps://arccms.com/about
logoutLogoutThe sign-out dialog

The ids are in src/app/core/nav/admin-menu.ts; the changes are made by applyNavChanges() in src/app/core/nav/nav-changes.ts.

Choose an icon

The admin loads Font Awesome Free 6.5.1 (see index.html), so any free icon works. Write the style class and the icon class: fa-solid fa-book-open, fa-regular fa-calendar, fa-brands fa-youtube.

To see which icons and styles exist, search public/assets/icons/fa-index.json: each entry has the icon name (n), its label, its free styles (s) and search terms. npm run icons:index builds that file for the admin's icon picker; it is a core file, so you never need to run it in an app.

A Pro-only icon or style renders as an empty box. Check the styles in the index before you pick one.