Fixed i18n to fetch and use the current language when the plugin initializes, instead of always defaulting to English. Now the plugin will show the correct language immediately on first load, and also update reactively when the language changes. Changes: - Added getCurrentLanguage() call in useTranslate initialization - Changed onMount to createEffect for reactive language loading - Updated both App.tsx and ProcrastinationInfo.tsx to use createEffect - Applied fixes to both procrastination-buster and boilerplate - Added debug logging to troubleshoot language change events This fixes the issue where plugins always started in English regardless of the user's selected language. |
||
|---|---|---|
| .. | ||
| i18n | ||
| scripts | ||
| src | ||
| .gitignore | ||
| .prettierrc | ||
| eslint.config.js | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| vite.config.ts | ||
Solid.js Boilerplate Plugin for Super Productivity
A modern, TypeScript-based boilerplate for creating Super Productivity plugins using Solid.js.
Features
- 🚀 Solid.js - Fast, reactive UI framework
- 📘 TypeScript - Full type safety with Super Productivity Plugin API
- 🎨 Modern UI - Clean, responsive design with dark mode support
- 🔧 Vite - Lightning-fast development and build tooling
- 📦 Ready to Use - Complete setup with examples for all plugin features
Getting Started
Prerequisites
- Node.js 16+
- npm or yarn
- Super Productivity 8.0.0+
Installation
- Clone this boilerplate:
cd packages/plugin-dev
cp -r boilerplate-solid-js my-plugin
cd my-plugin
- Install dependencies:
npm install
- Update plugin metadata in
src/manifest.json:- Change
idto a unique identifier - Update
name,description, andauthor - Modify
permissionsandhooksas needed
- Change
Development
Run the development server:
npm run dev
This starts Vite in watch mode. Your plugin will rebuild automatically when you make changes.
Building
Build the plugin for production:
npm run build
This creates optimized files in the dist/ directory.
Packaging
Create a ZIP file for distribution:
npm run package
This will:
- Build the plugin
- Create a ZIP file containing all necessary files
- Place the ZIP in the root directory
Deployment (for Plugins with HTML UI)
If your plugin has an index.html file (for UI components, side panels, etc.), use the deploy command instead:
npm run deploy
This will:
- Build the plugin
- Inline all CSS and JavaScript assets into the HTML file
- Create a ZIP file for distribution
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.
Project Structure
src/
├── assets/ # Static assets (icons, images)
│ └── icon.svg # Plugin icon
├── app/ # Solid.js application
│ ├── App.tsx # Main app component
│ └── App.css # App styles
├── utils/ # Helper utilities
│ └── useTranslate.ts # i18n hook for translations
├── index.html # Plugin UI entry point
├── index.ts # UI initialization
├── plugin.ts # Plugin logic and API integration
└── manifest.json # Plugin metadata
i18n/ # Translation files (optional)
├── en.json # English translations (required)
└── de.json # German translations (example)
scripts/ # Build and utility scripts
└── build-plugin.js # Plugin packaging script
dist/ # Build output (gitignored)
├── assets/
├── i18n/ # Copied translation files
├── index.html
├── index.js
├── plugin.js
└── manifest.json
Internationalization (i18n)
This boilerplate includes built-in support for multi-language plugins.
Translation Files
Translation files are located in the i18n/ directory and use JSON format with nested keys:
{
"APP": {
"TITLE": "My Plugin",
"SUBTITLE": "Description"
},
"BUTTONS": {
"SAVE": "Save",
"CANCEL": "Cancel"
},
"MESSAGES": {
"SUCCESS": "Task \"{{title}}\" created!"
}
}
Note: English (en.json) is required and used as a fallback when translations are missing.
Using Translations in Components
Use the useTranslate() hook in your Solid.js components:
import { useTranslate } from '../utils/useTranslate';
function MyComponent() {
const t = useTranslate();
const [title, setTitle] = createSignal('');
// Load translation
createEffect(async () => {
setTitle(await t('APP.TITLE'));
});
return <h1>{title()}</h1>;
}
With parameters (for interpolation):
createEffect(async () => {
const message = await t('MESSAGES.SUCCESS', { title: 'My Task' });
// Returns: 'Task "My Task" created!'
setMessage(message);
});
Adding New Languages
- Add the language code to
manifest.json:
{
"i18n": {
"languages": ["en", "de", "fr"]
}
}
- Create the translation file (e.g.,
i18n/fr.json):
{
"APP": {
"TITLE": "Mon Plugin"
}
}
- Rebuild the plugin:
npm run build
Translation Key Format
- Use hierarchical keys:
APP.TITLE,SETTINGS.THEME - Use parameter interpolation:
"message": "Hello {{name}}" - Keep keys descriptive and consistent
- English is the fallback language
For complete i18n documentation, see Plugin i18n Guide.
Plugin API Usage
Basic Setup
The plugin API is exposed through the global plugin object in plugin.ts:
import { PluginInterface } from '@super-productivity/plugin-api';
declare const plugin: PluginInterface;
Common API Methods
UI Registration
// 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(),
});
Data Operations
// 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();
Event Hooks
// 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);
});
Communication with UI
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' });
Customization
Styling
The boilerplate includes:
- CSS custom properties for theming
- Dark mode support
- Responsive design
- Minimal, clean styling
Modify src/app/App.css to customize the appearance.
Adding Features
- New UI Components: Add them in
src/app/as.tsxfiles - New API Endpoints: Add handlers in
src/plugin.tsusingplugin.onMessage() - New Hooks: Register them in
manifest.jsonand handle inplugin.ts - Permissions: Add required permissions to
manifest.json
Best Practices
- Type Safety: Always use TypeScript types from
@super-productivity/plugin-api - Error Handling: Wrap async operations in try-catch blocks
- Performance: Use Solid.js signals and effects efficiently
- Security: Never expose sensitive data or operations
- User Experience: Provide loading states and error feedback
Deployment
- Build the plugin:
npm run build - Package it:
npm run package - Upload the ZIP file to Super Productivity:
- Open Super Productivity
- Go to Settings → Plugins
- Click "Upload Plugin"
- Select your ZIP file
Troubleshooting
Plugin not loading
- Check browser console for errors
- Verify
manifest.jsonis valid JSON - Ensure
minSupVersionmatches your Super Productivity version
API calls failing
- Check if you have required permissions in
manifest.json - Verify Super Productivity is running the correct version
- Look for error messages in the console
Build errors
- Run
npm run typecheckto check for TypeScript errors - Ensure all dependencies are installed
- Clear
node_modulesand reinstall if needed
Resources
License
This boilerplate is provided as-is for creating Super Productivity plugins. Feel free to modify and distribute your plugins as you see fit.