Skip to main content

Getting Started with Plugin Development

This guide will walk you through creating your first Headlamp plugin from start to finish, whether you're a beginner or experienced developer.

What are Headlamp Plugins?​

Headlamp plugins are JavaScript/TypeScript modules that extend the functionality of Headlamp's web interface. Plugins can:

  • Add custom components to various parts of the UI (app bar, sidebar, details views)
  • Create new routes and pages
  • Customize how Kubernetes resources are displayed
  • Add new themes and branding
  • Integrate with external tools and services
  • Provide custom settings and configuration options
  • Setting up tokens for clusters, so users do not have to manually enter them
  • Customize how and what columns of lists/tables are displayed

Prerequisites​

Before starting plugin development, ensure you have:

  • Node.js (v22.0.0 or later) - Download here
  • npm (v11.0.0 or later) - npm is typically installed with Node.js, but may require a separate upgrade
  • A running Headlamp instance - Either the desktop app or development setup
  • Basic knowledge of JavaScript/TypeScript and React

Quick Start: Your First Plugin​

Let's create a simple plugin that displays "Hello Headlamp!" in the top navigation bar.

Step 1: Create the Plugin​

Run the following command to scaffold a new plugin using the headlamp-plugin tool. This command should be run where your plugin project (code) will live, typically in a dedicated projects directory (do not run this in Headlamp's plugin installation directory).

# Create a new plugin
npx --yes @kinvolk/headlamp-plugin create my-first-plugin

# Navigate to the plugin directory
cd my-first-plugin

# Install dependencies
npm install

Step 2: Understand the Plugin Structure​

Your new plugin will have this structure:

my-first-plugin/
├── src/
│ └── index.tsx # Main plugin entry point
├── package.json # Plugin metadata and dependencies
├── tsconfig.json # TypeScript configuration
├── dist/ # Built plugin files (created after build)
└── README.md # Plugin documentation

Step 3: Examine the Default Code​

Open src/index.tsx to see the default plugin code:

import { registerAppBarAction } from '@kinvolk/headlamp-plugin/lib';

// Below are some imports you may want to use.
// See README.md for links to plugin development documentation.
// import { SectionBox } from '@kinvolk/headlamp-plugin/lib/CommonComponents';
// import { K8s } from '@kinvolk/headlamp-plugin/lib/K8s';
// import { Typography } from '@mui/material';

registerAppBarAction(<span>Hello</span>);

Step 4: Start Development Mode​

npm run start

This command:

  • Makes the plugin available to Headlamp
  • Watches file changes to automatically rebuild the plugin

When using a packaged Headlamp Desktop app, open Settings > Plugins. Under the Installed Plugins list, expand Advanced and enable Load development plugins. Packaged apps do not load plugins from the local development directory by default. Only enable this setting when you trust every plugin in that directory.

Step 5: See Your Plugin in Action​

  1. Desktop App: Open Headlamp Desktop after enabling Load development plugins under Advanced in Settings > Plugins; or
  2. Run Headlamp in development mode: Start the Headlamp development server (see development guide).

You should see "Hello" text in the top navigation bar!

Step 6: Make Your First Change​

Let's create a more interactive component. Replace the content of src/index.tsx:

import { registerAppBarAction } from '@kinvolk/headlamp-plugin/lib';
import { Button } from '@mui/material';

function HelloButton() {
const handleClick = () => {
alert('Hello from your Headlamp plugin!');
};

return (
<Button
variant="outlined"
size="small"
onClick={handleClick}
sx={{ mx: 2 }} // Add some horizontal margin
>
Hello Headlamp!
</Button>
);
}

registerAppBarAction(<HelloButton />);

Save the file and watch Headlamp automatically reload with your changes!

TypeScript versions​

Generated plugins use TypeScript 5.6.2 by default. You can opt into stable TypeScript 7 for headlamp-plugin tsc while keeping a legacy compiler API for ESLint, Storybook, and translation extraction.

This setup requires a headlamp-plugin release containing the TypeScript 7 opt-in support described here; it is not available in the published 0.14.0 tooling.

  1. Add these development dependencies to your plugin's package.json:

    {
    "devDependencies": {
    "@typescript/native": "npm:typescript@^7.0.2",
    "typescript": "npm:@typescript/typescript6@^6.0.2"
    }
    }

    Keep your existing dependencies, including @kinvolk/headlamp-plugin.

  2. Remove only the typescript entry from the root overrides object. Do not override every TypeScript dependency to version 7: tools importing typescript still need the legacy JavaScript compiler API.

  3. Refresh the lockfile and verify a clean install:

    npm install
    npm ci
    npm run lint
    npm run tsc

When @typescript/native is declared in dependencies or devDependencies, headlamp-plugin tsc runs that package's installed compiler directly. A missing, broken, prerelease, or non-7 compiler produces an error instead of falling back to a legacy compiler. Projects without this dependency keep their existing checker. The compatibility package provides tsc6; the native package provides tsc, so those executables do not conflict.

You can check the two compiler versions with:

node node_modules/@typescript/native/bin/tsc --version
node -p "require('typescript').version"

The compatibility checks use Node 24/npm 11, TypeScript 7.0.2, @typescript/typescript6 6.0.2, and typescript-eslint 8.72.0 or newer. The compatibility package resolves a TypeScript 6 compiler; individual tools may also retain a supported nested TypeScript 5 dependency. This is TypeScript 7 checking alongside legacy tooling, not native TypeScript 7 support throughout the toolchain. Syntax that legacy parsers cannot handle is not covered.

Prefer Headlamp's public exports, such as useTranslation from @kinvolk/headlamp-plugin/lib. If you import another library directly, declare it as a dependency rather than relying on a transitive package being hoisted.

headlamp-plugin upgrade preserves this opt-in by leaving out the template's TypeScript override. Its existing behavior for other overrides is unchanged: it replaces them with the template values rather than merging custom entries.

Understanding Plugin Development​

Core Concepts​

1. Plugin Registry​

The plugin registry is the central system that manages all plugin functionality. Import functions from @kinvolk/headlamp-plugin/lib to register your functionality. For example:

import {
registerAppBarAction,
registerRoute,
registerSidebarEntry,
registerDetailsViewSection,
} from '@kinvolk/headlamp-plugin/lib';

2. Shared Dependencies​

Headlamp provides common libraries that plugins can use without bundling them:

  • React & React DOM - For building UI components
  • React Router - For navigation and routing
  • Redux - For state management
  • Material-UI (@mui/material) - UI component library
  • Material-UI Lab (@mui/lab) - Additional Material-UI components
  • Lodash - Utility functions
  • Iconify - Icon library
  • Notistack - Snackbar notifications
  • Monaco Editor - Code editor component
  • @iconify/react - Icon components

I.e., even though these components can be imported by the plugin as normal in its code, they are not bundled with the plugin. Instead, they are provided by Headlamp itself. This means there is no need to add them as dependencies in your plugin's package.json.

3. Kubernetes API Access​

Access Kubernetes resources using the built-in K8s module:

import { K8s } from '@kinvolk/headlamp-plugin/lib';

function PodList() {
const [pods, error] = K8s.ResourceClasses.Pod.useList();

if (error) return <div>Error loading pods</div>;
if (!pods) return <div>Loading...</div>;

return (
<div>
<h3>Pods ({pods.length})</h3>
{pods.map(pod => (
<div key={pod.metadata.uid}>{pod.metadata.name}</div>
))}
</div>
);
}

Development Workflow​

1. Development Mode​

Always use npm run start during development for:

  • Automatic rebuilding
  • Hot reloading
  • Real-time error checking

2. Code Quality Tools​

Your plugin comes with built-in quality tools:

# Format code
npm run format

# Check for linting issues
npm run lint

# Fix auto-fixable linting issues
npm run lint-fix

# Type checking
npm run tsc

# Run tests
npm run test

3. Building for Production​

When ready to deploy:

npm run build
npm run package

This will create a tarball archive that can be then extracted into the Headlamp plugins directory.

# Created tarball: "/tmp/my-first-plugin/my-first-plugin-0.1.0.tar.gz".
# Tarball checksum (sha256): c45397ff5f8fac563c2b85a18c0dbbe732017bed71b24bf852b809911993be6f

Next Steps​

Now that you've created your first plugin, explore these advanced topics:

  1. Common Patterns - Learn best practices and reusable patterns for plugin development
  2. Example Plugins - Learn from real-world examples
  3. Plugin Functionality - Complete reference of available APIs
  4. Building & Shipping - Production deployment strategies
  5. Publishing Plugins - Share your plugins with the community

Troubleshooting​

Plugin Not Loading​

  • Ensure Headlamp is running and accessible
  • Check the browser console for JavaScript errors
  • Verify your plugin's package.json has correct metadata
  • Make sure you're running npm run start in the plugin directory

Plugin's Changes Not Reflecting​

  • Ensure you saved your changes
  • Check if the development server is running (npm run start) without errors
  • Remove the installed plugin from Headlamp's plugins folder (see plugin locations) and re-run npm run start
  • Restart Headlamp if necessary

Build Errors​

  • Run npm run lint to check for code issues
  • Ensure all imports are correct
  • Check TypeScript errors with npm run tsc

Hot Reloading Issues​

  • Restart the development server (npm run start)
  • Make sure you do not have several Headlamp tabs in case you are running in development mode
  • Clear browser cache
  • Check file permissions in the plugin directory

Getting Help​