Skip to main content

Tutorial: Hello World Plugin

Build a simple panel plugin that displays "Hello World" and registers a tool for the AI assistant.

What you'll build

  • A sidebar panel that displays a greeting
  • An LLM tool called sayHello that the AI can use

Prerequisites

  • Node.js 18+
  • pnpm (recommended) or npm
  • Basic React knowledge

Step 1: Create the project

Create a new folder for your plugin:

mkdir hello-world-plugin
cd hello-world-plugin

Initialize the project:

pnpm init

Install dependencies:

pnpm add @practicalkit/plugin-sdk react react-dom
pnpm add -D typescript vite @vitejs/plugin-react @types/react @types/react-dom

Step 2: Create the manifest

Create manifest.json in your project root:

{
"id": "hello-world-plugin",
"name": "Hello World Plugin",
"modules": [
{
"id": "hello-panel",
"name": "Hello World",
"main": "index.html",
"type": "panel"
}
]
}

Key fields:

  • id - Unique identifier for your plugin (use lowercase with hyphens)
  • name - Human-readable name shown in the UI
  • modules - Array of modules your plugin provides
  • modules[].type - Use panel for sidebar panels

Step 3: Create the HTML entry point

Create index.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hello World Plugin</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

Step 4: Configure TypeScript

Create tsconfig.json:

{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"strict": true
},
"include": ["src"]
}

Step 5: Configure Vite

Create vite.config.ts:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
plugins: [react()],
build: {
outDir: "dist",
rollupOptions: {
input: "index.html",
},
},
});

Step 6: Create the SDK instance

Create src/sdk.ts:

import { PracticalKitSdk } from "@practicalkit/plugin-sdk";

// Create a single SDK instance for the entire plugin
export const sdk = new PracticalKitSdk();

// Initialize the SDK (connects to the host application)
sdk.init();
Single Instance

Always create one SDK instance and export it. Multiple instances will cause issues.

Step 7: Create the React app

Create src/main.tsx:

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);

Create src/App.tsx:

import { useEffect, useState } from "react";
import { sdk } from "./sdk";

export default function App() {
const [greeting, setGreeting] = useState("Hello, World!");

useEffect(() => {
// Register an LLM tool when the component mounts
sdk.llm.registerTool({
name: "sayHello",
description:
"Greets someone by name. Use this when the user asks you to say hello to someone.",
parameters: {
type: "object",
properties: {
name: {
type: "string",
description: "The name of the person to greet",
},
},
required: ["name"],
},
handler: async (args) => {
const { name } = args as { name: string };
const message = `Hello, ${name}!`;

// Update the UI
setGreeting(message);

// Return the result to the LLM
return message;
},
});

sdk.logs.info("Hello World plugin loaded");

// Cleanup: unregister the tool when unmounting
return () => {
sdk.llm.unregisterTool("sayHello");
};
}, []);

return (
<div style={{ padding: "16px" }}>
<h1>{greeting}</h1>
<p>Ask the AI to say hello to someone!</p>
</div>
);
}

Step 8: Add build scripts

Update your package.json:

{
"name": "hello-world-plugin",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build && cp manifest.json dist/"
}
}

Step 9: Build the plugin

pnpm build

This creates a dist/ folder with your bundled plugin and manifest.

Step 10: Install in PracticalKit

  1. Open PracticalKit
  2. Go to Plugins > Add Plugin...
  3. Navigate to your plugin's dist/ folder
  4. Select manifest.json
  5. Restart PracticalKit when prompted

Your "Hello World" panel should now appear in the sidebar!

Try it out

  1. Click on the Hello World panel in the sidebar
  2. Open the chat and ask: "Say hello to Alice"
  3. The AI will use your sayHello tool
  4. Watch the panel update with the greeting!

Next steps