Shared foundation for building Cockpit plugins with React and PatternFly v6. Extracts the boilerplate that every plugin needs — bootstrapping, i18n, dark theme, async patterns, systemd integration, shared tooling config, and a full QEMU VM test harness — so each plugin only contains its own logic.
Plugin runtime
bootstrapPlugin — mounts your React app into the Cockpit frame with i18n and error boundary wired updark-theme — side-effect module that automatically syncs the pf-v6-theme-dark class with the Cockpit shell, responding to user preference changes and system themeinitCockpitI18n — sets up i18next with Cockpit's locale loading conventionsHooks
useAsyncAction — wraps an async operation with loading, error, and execute state; ideal for buttons that trigger backend callsuseAutoRefresh — runs a callback on a configurable interval, with manual refresh supportuseAsyncStream — consumes a Cockpit channel as a line-buffered async streamuseConfirmAction — multi-step confirmation flow with typed state transitionsusePollingFetch — fetch with automatic polling, refresh, and loading stateuseAdminMode — reactively tracks whether the Cockpit session has administrative (superuser) accessuseDialogState — manages open/close state and associated data for a fixed set of named dialogsuseLayout — persists a "current layout" choice (e.g. table vs grid) to localStorage, validated against allowed values, with optional cross-tab syncuseLocalStorage / useSessionStorage — typed, JSON-serialized read/write hooks for localStorage/sessionStorageusePersistedSet — a localStorage-backed Set<string> with toggle/clear and optional cross-tab syncuseDarkMode — reactively tracks PatternFly's dark theme class on <html> via a MutationObserveruseOperationCounter — tracks active in-flight operations via increment()/decrement(); useful to suppress auto-refresh during mutationsuseKeyboardShortcuts — binds global single-key shortcuts, skipping form fields and open modalsComponents
ConfirmDialog — confirmation modal driven by useConfirmAction, supports multi-step flowsErrorBoundary — catches render errors and shows a PatternFly alert with detailsHelpPopover — PatternFly popover for contextual help textLogViewer — scrollable terminal-style log display backed by an async streamStatusBadge — color-coded badge for service or resource statesToastProvider + hook — global toast notification systemPluginPage — root layout wrapper composing ErrorBoundary + ToastProvider + PatternFly Page/PageSectionExternalLinkModal — confirmation modal shown before navigating to an external URLTooltip — thin wrapper around PatternFly's Tooltip with exitDelay defaulted to 0CollapsibleSearch — search input that collapses to an icon-only button when empty and unfocusedLayoutSelector — PatternFly ToggleGroup for switching between named layout optionsPluginFooter — footer bar showing the plugin's version string and a row of linksCodeEditor — CodeMirror 6-based code editor with dark/light theme following useDarkModeDiffEditor — side-by-side/unified diff view built on CodeMirror's merge extensionEnvEditor — CodeEditor preconfigured with a linter for .env-file syntaxEnvTable — structured key/value table editor for environment variables with secret maskingExternalAddressInput — two-row input for an external listener address (protocol/host + port)CodeEditor, DiffEditor, EnvEditor, and EnvTable require the optional codemirror and @codemirror/* peer dependencies (see package.json's peerDependenciesMeta) — only needed if you import them.
Systemd layer
useServiceStatus — reactive hook for a systemd service state (active, failed, inactive…)ServiceControl — start/stop/restart/enable control componentServiceStatusBadge — StatusBadge preconfigured for the five systemd unit states, with built-in colors and i18n labelsapi — typed wrappers around cockpit.spawn for systemctl operationsShared tooling config
tsconfig.base.json — TypeScript base config tuned for Cockpit pluginseslint.config.base — createEslintConfig() factory with TS, React, and react-hooks rulesvitest.config.base — createVitestConfig() factory with jsdom and PatternFly setupplaywright.config.base — createPlaywrightConfig(pluginName) factory for E2E tests against live VMsTesting utilities
mockProcess, mockCockpitFile, mockCockpitPermission, mockCockpitUser — mock return values for individual cockpit.* methodsmockHttpClient — mock for Cockpit HTTP client used in tests./e2e — pluginPage Playwright fixture that handles Cockpit login and navigates to your plugin automaticallyQEMU VM test harness
npm run vm — spins up real cloud VMs (Arch, Debian, Fedora) with Cockpit installed and your plugin mounted via virtfs. Used for manual and automated browser testing against a live Cockpit instance. See VM Testing.Reusable CI/CD workflows
docs/wiki/npm install @rxtx4816/cockpit-plugin-base-react
Peer dependencies: react >=19, react-dom >=19, i18next >=26, react-i18next >=17
// src/index.tsx
import "./i18n";
import "@rxtx4816/cockpit-plugin-base-react/dark-theme";
import { bootstrapPlugin } from "@rxtx4816/cockpit-plugin-base-react/bootstrap";
import App from "./App";
bootstrapPlugin(App);
For full setup guidance, config sharing, and workflow integration see the wiki.
Translation completeness for src/i18n/locales/, checked on every push by scripts/i18n-coverage.mjs.
| Coverage | Languages |
|---|---|
| 100% | English (en) — source, de, pl |
API Reference — auto-generated from source, updated on every release.
Secrets must never be committed to this repository. GitHub Secret Scanning and Push Protection are active — see SECURITY.md for the vulnerability reporting process and the false-positive bypass flow if a push is blocked.
AGPL-3.0-only © 2026 RXTX4816.
This is free and open-source software (copyleft): use it, study it, modify it, and redistribute it. If you distribute a modified version — or run one as a service that users interact with over a network — you must make your modified source available under the same license (AGPL §13). A plugin that bundles this package into its build is a combined work and must also be AGPL-3.0 / GPL-3.0.
npm versions 1.x and earlier remain under the MIT License — the change to
AGPL-3.0 takes effect from 2.0.0. See LICENSE-HISTORY.md.