Skip to main content

Personnel Plugin Example

Complete working example of a Personnel/HR plugin for Framework M.

Structure

personnel-plugin/
├── package.json # Plugin metadata
├── tsconfig.json
└── src/
├── plugin.config.ts # Plugin manifest
└── pages/
├── Directory.tsx # Employee directory
└── OrgChart.tsx # Organization chart

Files

package.json

{
"name": "@personnel/frontend",
"version": "0.1.0",
"private": true,
"framework-m": {
"plugin": "./src/plugin.config.ts",
"type": "frontend-module"
},
"dependencies": {
"@framework-m/desk": "^0.1.0",
"@framework-m/plugin-sdk": "^0.1.0"
}
}

src/plugin.config.ts

import type { FrameworkMPlugin } from "@framework-m/plugin-sdk";

const plugin: FrameworkMPlugin = {
name: "personnel",
version: "0.1.0",

menu: [
{
name: "personnel.directory",
label: "Employee Directory",
route: "/personnel/directory",
icon: "users",
module: "Personnel",
category: "HR",
order: 1,
},
{
name: "personnel.org-chart",
label: "Org Chart",
route: "/personnel/org-chart",
icon: "sitemap",
module: "Personnel",
category: "HR",
order: 2,
},
{
name: "personnel.leave",
label: "Leave Management",
route: "/personnel/leave",
icon: "calendar",
module: "Personnel",
category: "Self-Service",
order: 3,
},
],

routes: [
{
path: "/personnel/directory",
element: () => import("./pages/Directory"),
},
{
path: "/personnel/org-chart",
element: () => import("./pages/OrgChart"),
},
],
};

export default plugin;

src/pages/Directory.tsx

import { AutoTable, useDocTypeMeta } from "@framework-m/desk";

export default function Directory() {
const { schema, isLoading } = useDocTypeMeta("Employee");

if (isLoading) return <div>Loading...</div>;

return (
<div style={{ padding: "2rem" }}>
<h1>Employee Directory</h1>
<AutoTable
resource="Employee"
schema={schema}
onRowClick={(row) => console.log("Selected employee:", row)}
/>
</div>
);
}

src/pages/OrgChart.tsx

export default function OrgChart() {
return (
<div style={{ padding: "2rem" }}>
<h1>Organization Chart</h1>
<p>Visual organization hierarchy.</p>
{/* Implement tree/chart visualization here */}
</div>
);
}

Multi-Plugin Composition

This plugin works alongside the WMS Plugin seamlessly:

m new:app wms --with-frontend
m new:app personnel --with-frontend
pnpm dev # Both auto-discovered, sidebar shows both modules

Sidebar result:

WMS
├── Overview: WMS Dashboard
├── Operations: Inventory, Receiving
PERSONNEL
├── HR: Employee Directory, Org Chart
├── Self-Service: Leave Management

Cross-Plugin Communication

Access WMS services from Personnel:

import { useService } from "@framework-m/plugin-sdk";

export default function Directory() {
// Access inventory data from the WMS plugin
const { service: inventory } = useService("inventoryService");
// ...
}