From 427229cf6a13e1433254efc69aa4777db09d5809 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 28 Oct 2025 11:24:22 +0000 Subject: [PATCH 1/2] feat(next): add System Info page to settings menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new System Info page accessible from the settings menu displaying technical information about the Payload installation and runtime environment. Features: - System Info page at /system-info with version info (Payload, Next.js, Node.js), configuration (environment, server URL, database adapter), and session information - Dynamic version loading from package.json files using ES module imports - User-friendly database adapter display names (MongoDB, PostgreSQL, SQLite, Cloudflare D1 SQLite) - Settings menu reorganization: user-defined items first, separator line, then System Info - Config option to disable page via admin.routes.systemInfo = false - Fixed gear icon stroke-width to match logout icon (2px) - Comprehensive documentation in docs/admin/overview.mdx 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- docs/admin/overview.mdx | 76 ++++++++++++---- .../DefaultSystemInfoItem.tsx | 20 +++++ .../SettingsMenuButton/SettingsDivider.tsx | 7 ++ packages/next/src/elements/Nav/index.tsx | 22 ++++- packages/next/src/views/Root/getRouteData.ts | 15 +++- .../src/views/SystemInfo/index.client.tsx | 89 +++++++++++++++++++ packages/next/src/views/SystemInfo/index.scss | 74 +++++++++++++++ packages/next/src/views/SystemInfo/index.tsx | 69 ++++++++++++++ packages/payload/package.json | 3 +- packages/payload/src/admin/views/index.ts | 1 + packages/payload/src/config/defaults.ts | 1 + packages/payload/src/config/types.ts | 5 ++ packages/ui/src/icons/Gear/index.scss | 2 +- 13 files changed, 363 insertions(+), 21 deletions(-) create mode 100644 packages/next/src/elements/Nav/SettingsMenuButton/DefaultSystemInfoItem.tsx create mode 100644 packages/next/src/elements/Nav/SettingsMenuButton/SettingsDivider.tsx create mode 100644 packages/next/src/views/SystemInfo/index.client.tsx create mode 100644 packages/next/src/views/SystemInfo/index.scss create mode 100644 packages/next/src/views/SystemInfo/index.tsx diff --git a/docs/admin/overview.mdx b/docs/admin/overview.mdx index 8a959e2ebdb..139348ee4c7 100644 --- a/docs/admin/overview.mdx +++ b/docs/admin/overview.mdx @@ -257,16 +257,17 @@ const config = buildConfig({ The following options are available: -| Option | Default route | Description | -| ----------------- | -------------------- | ----------------------------------------- | -| `account` | `/account` | The user's account page. | -| `createFirstUser` | `/create-first-user` | The page to create the first user. | -| `forgot` | `/forgot` | The password reset page. | -| `inactivity` | `/logout-inactivity` | The page to redirect to after inactivity. | -| `login` | `/login` | The login page. | -| `logout` | `/logout` | The logout page. | -| `reset` | `/reset` | The password reset page. | -| `unauthorized` | `/unauthorized` | The unauthorized page. | +| Option | Default route | Description | +| ----------------- | -------------------- | ----------------------------------------------------------------------------------------- | +| `account` | `/account` | The user's account page. | +| `createFirstUser` | `/create-first-user` | The page to create the first user. | +| `forgot` | `/forgot` | The password reset page. | +| `inactivity` | `/logout-inactivity` | The page to redirect to after inactivity. | +| `login` | `/login` | The login page. | +| `logout` | `/logout` | The logout page. | +| `reset` | `/reset` | The password reset page. | +| `systemInfo` | `/system-info` | The system information page. Set to `false` to disable. [More details](#system-info-page) | +| `unauthorized` | `/unauthorized` | The unauthorized page. | **Note:** You can also swap out entire _views_ out for your own, using the @@ -274,6 +275,47 @@ The following options are available: Views](../custom-components/custom-views) for more information. +### System Info Page + +The System Info page displays important technical information about your Payload installation and runtime environment. This page is accessible from the settings menu (gear icon) in the top-right corner of the Admin Panel. + +The following information is displayed on the System Info page: + +**Version Information:** + +- Payload version +- Next.js version +- Node.js version + +**Configuration:** + +- Environment (NODE_ENV) +- Server URL +- Database Adapter (MongoDB, PostgreSQL, SQLite, or Cloudflare D1 SQLite) + +**Current Session:** + +- Logged-in user information + +#### Disabling the System Info Page + +If you want to disable the System Info page entirely, you can set `admin.routes.systemInfo` to `false`: + +```ts +import { buildConfig } from 'payload' + +const config = buildConfig({ + // ... + admin: { + routes: { + systemInfo: false, // highlight-line + }, + }, +}) +``` + +When disabled, the System Info page will not be accessible and will not appear in the settings menu. + ## I18n The Payload Admin Panel is translated in over [30 languages and counting](https://github.com/payloadcms/payload/tree/main/packages/translations). Languages are automatically detected based on the user's browser and used by the Admin Panel to display all text in that language. If no language was detected, or if the user's language is not yet supported, English will be chosen. Users can easily specify their language by selecting one from their account page. See [I18n](../configuration/i18n) for more information. @@ -312,19 +354,19 @@ const config = buildConfig({ timezones: { supportedTimezones: [ { - label: "Europe/Dublin", - value: "Europe/Dublin", + label: 'Europe/Dublin', + value: 'Europe/Dublin', }, { - label: "Europe/Amsterdam", - value: "Europe/Amsterdam", + label: 'Europe/Amsterdam', + value: 'Europe/Amsterdam', }, { - label: "Europe/Bucharest", - value: "Europe/Bucharest", + label: 'Europe/Bucharest', + value: 'Europe/Bucharest', }, ], - defaultTimezone: "Europe/Amsterdam", + defaultTimezone: 'Europe/Amsterdam', }, }, }) diff --git a/packages/next/src/elements/Nav/SettingsMenuButton/DefaultSystemInfoItem.tsx b/packages/next/src/elements/Nav/SettingsMenuButton/DefaultSystemInfoItem.tsx new file mode 100644 index 00000000000..649b51b5c87 --- /dev/null +++ b/packages/next/src/elements/Nav/SettingsMenuButton/DefaultSystemInfoItem.tsx @@ -0,0 +1,20 @@ +'use client' +import { PopupList, useConfig } from '@payloadcms/ui' +import React from 'react' + +export const DefaultSystemInfoItem: React.FC = () => { + const { + config: { + admin: { + routes: { systemInfo }, + }, + routes: { admin: adminRoute }, + }, + } = useConfig() + + return ( + + System Info + + ) +} diff --git a/packages/next/src/elements/Nav/SettingsMenuButton/SettingsDivider.tsx b/packages/next/src/elements/Nav/SettingsMenuButton/SettingsDivider.tsx new file mode 100644 index 00000000000..5d506f58021 --- /dev/null +++ b/packages/next/src/elements/Nav/SettingsMenuButton/SettingsDivider.tsx @@ -0,0 +1,7 @@ +'use client' +import { PopupList } from '@payloadcms/ui' +import React from 'react' + +export const SettingsDivider: React.FC = () => { + return +} diff --git a/packages/next/src/elements/Nav/index.tsx b/packages/next/src/elements/Nav/index.tsx index 4862c99a2dc..85083527726 100644 --- a/packages/next/src/elements/Nav/index.tsx +++ b/packages/next/src/elements/Nav/index.tsx @@ -8,7 +8,9 @@ import React from 'react' import { NavHamburger } from './NavHamburger/index.js' import { NavWrapper } from './NavWrapper/index.js' +import { DefaultSystemInfoItem } from './SettingsMenuButton/DefaultSystemInfoItem.js' import { SettingsMenuButton } from './SettingsMenuButton/index.js' +import { SettingsDivider } from './SettingsMenuButton/SettingsDivider.js' import './index.scss' const baseClass = 'nav' @@ -93,7 +95,13 @@ export const DefaultNav: React.FC = async (props) => { }, }) - const renderedSettingsMenu = + // Include the default System Info menu item only if not disabled + const defaultSystemInfoItem = + payload.config.admin.routes.systemInfo !== false ? ( + + ) : null + + const customSettingsMenuItems = settingsMenu && Array.isArray(settingsMenu) ? settingsMenu.map((item, index) => RenderServerComponent({ @@ -117,6 +125,18 @@ export const DefaultNav: React.FC = async (props) => { ) : [] + // Reorganize settings menu: user-defined items first, then divider (if custom items exist), then System Info + const settingsDivider = + customSettingsMenuItems.length > 0 && defaultSystemInfoItem ? ( + + ) : null + + const renderedSettingsMenu = [ + ...customSettingsMenuItems, + settingsDivider, + defaultSystemInfoItem, + ].filter(Boolean) + return (