Have you ever tried to create a plugin for the desktop application? Then you know that too often it is a long and uncomfortable process. Your plugins API is your interface and the simpler this interface the more people use it and the more plugins your have.

During development of plugins system for Cerebro I defined few steps to build a perfect plugins system. Since it is an electron application, I’ll share some javascript-related details, but main ideas are suitable for any kind of app.

Step 1: generate the code

In most cases when you want to create a plugin, you download an archive and use it as a skeleton for your plugin. Often it contains some mess, that is not actually related to your code. Sometimes you have to spend time looking for the latest version. So, too much work to do.

Cerebro plugin is a simple npm package. Is there any way to generate javascript? Sure, there is Yeoman, but it is not a standard. Yarn is closer to standard and it includes create command. Under the hood it is simple: yarn create something just looks for the npm package called create-something , installs it globally and runs the binary from this package. The most popular example is create-react-app.

Time to use this quote:

good artists borrow, great artists steal

If you want to do great javascript package generator — just steal ideas from create-react-app. React community did a great job here!

That is how we built create-cerebro-plugin that generates skeleton and installs all dependencies of the plugin with simple command:

yarn create cerebro-plugin demo

Step 2: hide details

Another cool thing about create-react-app is that it hides all configuration and build process from developer, so you care only about your code, not about environment.

How is it related to plugin development? Sometimes application requires to put plugin to certain directory to start. But what if I want to store all my code projects in one directory, like ~/projects ? We have to manually symlink the directory and again: care about too much stuff…

In case of prepared environment we hide these details and configuration from developers and give them only one simple command: yarn start that initialises prepares enviroument, so you can start development immediately:

Step 3: autoupdate

Do you remember this feeling when you have to restart or reload your application after each change in your plugin code? Such a waste of time! Especially when you work with modern frontend stack with hot module replacement where you forget about refresh button. Just provide the same user experience for your plugin developers. They will be happy to see immediate feedback:

Step 4: prepare building blocks

Most of Cerebro plugins related to search. Every developer can find npm package to fetch data and search, but in this case user experience will be inconsistent. What if applications search will be fuzzy, but everything else not? What if each plugin will have own UI elements and styles?

Photo by Kelly Sikkema / Unsplash

Let’s prepare building blocks: main functions (in case of Cerebro is memoization for faster responses and search) and UI elements. Just provide it as a separate package and again: plugin developer will be happy to care more about their code, not about UI and implementation details.

Step 5: unify publishing and distribution

I remember this times, when I had to search for extensions for some apps on forums, GitHub or other places, not supported by application creators. But I believe better when you see all plugins in one place. And much better when you don’t have to leave the app to manage them.

The same works for developers: provide unified way of publishing. When you work with node the best place is (unpredictable!) npm. Since the plugin is simple node package, it can be published to global npm registry and found using npm search API by keyword.

No extra tools and commands, just one simple known command npm publish ./ and all users can find new plugin in registry:

Conclusion

Looks like main ideas of this article works for everything, not only desktop applications and extensions: