packages/plugin-dev/automations/README.md
A modern, TypeScript-based boilerplate for creating Super Productivity plugins using Solid.js.
cd packages/plugin-dev
cp -r boilerplate-solid-js my-plugin
cd my-plugin
npm install
src/manifest.json:
id to a unique identifiername, description, and authorpermissions and hooks as neededRun the development server:
npm run dev
This starts Vite in watch mode. Your plugin will rebuild automatically when you make changes.
Build the plugin for production:
npm run build
This creates optimized files in the dist/ directory.
Create a ZIP file for distribution:
npm run package
This will:
If your plugin has an index.html file (for UI components, side panels, etc.), use the deploy command instead:
npm run deploy
This will:
Note: The deploy command is necessary for any plugin with HTML UI because Super Productivity loads plugin HTML as data URLs, which cannot access external files. The inline-assets script ensures all assets are embedded directly in the HTML.
src/
āāā assets/ # Static assets (icons, images)
ā āāā icon.svg # Plugin icon
āāā app/ # Solid.js application
ā āāā App.tsx # Main app component
ā āāā App.css # App styles
āāā index.html # Plugin UI entry point
āāā index.ts # UI initialization
āāā plugin.ts # Plugin logic and API integration
āāā manifest.json # Plugin metadata
scripts/ # Build and utility scripts
āāā build-plugin.js # Plugin packaging script
dist/ # Build output (gitignored)
āāā assets/
āāā index.html
āāā index.js
āāā plugin.js
āāā manifest.json
The plugin API is exposed through the global plugin object in plugin.ts:
import { PluginInterface } from '@super-productivity/plugin-api';
declare const plugin: PluginInterface;
// Register header button
plugin.registerHeaderButton({
icon: 'rocket',
tooltip: 'Open Plugin',
action: () => plugin.showIndexHtmlAsView(),
});
// Register menu entry
plugin.registerMenuEntry({
label: 'My Plugin',
icon: 'rocket',
action: () => plugin.showIndexHtmlAsView(),
});
// Register keyboard shortcut
plugin.registerShortcut({
keys: 'ctrl+shift+m',
label: 'Open My Plugin',
action: () => plugin.showIndexHtmlAsView(),
});
// Get tasks
const tasks = await plugin.getTasks();
const archivedTasks = await plugin.getArchivedTasks();
// Create task
const newTask = await plugin.addTask({
title: 'New Task',
projectId: 'project-id',
});
// Update task
await plugin.updateTask('task-id', {
title: 'Updated Title',
isDone: true,
});
// Get projects and tags
const projects = await plugin.getAllProjects();
const tags = await plugin.getAllTags();
// Task completion
plugin.on('taskComplete', (task) => {
console.log('Task completed:', task.title);
});
// Task updates
plugin.on('taskUpdate', (task) => {
console.log('Task updated:', task);
});
// Context changes
plugin.on('contextChange', (context) => {
console.log('Context changed:', context);
});
In plugin.ts:
plugin.onMessage('myCommand', async (data) => {
// Handle message from UI
return { result: 'success' };
});
In your Solid.js component:
const sendMessage = async (type: string, payload?: any) => {
return new Promise((resolve) => {
const messageId = Math.random().toString(36).substr(2, 9);
const handler = (event: MessageEvent) => {
if (event.data.messageId === messageId) {
window.removeEventListener('message', handler);
resolve(event.data.response);
}
};
window.addEventListener('message', handler);
window.parent.postMessage({ type, payload, messageId }, '*');
});
};
// Usage
const result = await sendMessage('myCommand', { foo: 'bar' });
The boilerplate includes:
Modify src/app/App.css to customize the appearance.
src/app/ as .tsx filessrc/plugin.ts using plugin.onMessage()manifest.json and handle in plugin.tsmanifest.json@super-productivity/plugin-apinpm run buildnpm run packagemanifest.json is valid JSONminSupVersion matches your Super Productivity versionmanifest.jsonnpm run typecheck to check for TypeScript errorsnode_modules and reinstall if neededThis boilerplate is provided as-is for creating Super Productivity plugins. Feel free to modify and distribute your plugins as you see fit.