How does a Volto add-on works?#
Volto addon packages are just CommonJS packages. The only requirement is that
they point the main
key of their package.json
to a module that exports, as
a default function that acts as a Volto configuration loader.
Similarly to how you develop a Plone backend Python Add-on, you can control all aspects of Volto from a Volto Add-on.
This gives you the ability to move all your project configuration, components, customizations and even theme files to an add-on. This has the advantage to render the project configuration empty, so you could at any point not only reuse the add-on(s) outside the current project, but also have the project as simply boilerplate that could be replaced at any point (eg. a Volto update).
An add-on can be published in an npm registry, just as any other package. However, Volto Add-ons should not be transpiled. They should be released as "source" packages.
See @kitconcept/volto-blocks-grid
as an example.
Loading a Volto Add-on in a project#
You should declare in your project that you are using an add-on.
This is done in the project package.json
, addons
key:
{
"name": "my-nice-volto-project",
...
"addons": [
"acme-volto-foo-addon",
"@plone/some-addon",
"collective-another-volto-addon"
],
...
}
```{warning}
Adding the addon package to the `addons` key is obligatory! It allows Volto
to treat that package properly and provide it with BabelJS language
features. In Plone terminology, it is like including a Python egg to the
`zcml` section of zc.buildout.
By including the addon name in the addons
key, the addon's default export
function is executed, being passed the Volto configuration registry. In that
function, the addon can customize the registry. The function needs to return
the config
(Volto configuration registry) object, so that it's passed further
along to the other addons.
Loading a Volto Add-on optional configuration#
Some addons might choose to allow the Volto project to selectively load some of
their configuration, so they may offer additional optional configuration functions,
which you can load by overloading the addon name in the addons
package.json
key, like so:
{
"name": "my-nice-volto-project",
"addons": [
"acme-volto-foo-addon:loadOptionalBlocks,overrideSomeDefaultBlock",
"volto-ga"
],
}
Note
If coming from the Plone backend development, you could map the main add-on configuration to the default
GenericSetup profile, as it's loaded always. These optional configurations could be mapped to optional GenericSetup profiles that could be applied at any time on demand.
Providing add-on configuration#
The default export of your addon main index.js
file should be a function with
the signature config => config
.
That is, it should take the global
configuration object and return it,
possibly mutated or changed. So your main index.js
will look like:
export default function applyConfig(config) {
config.blocks.blocksConfig.faq_viewer = {
id: 'faq_viewer',
title: 'FAQ Viewer',
edit: FAQBlockEdit,
view: FAQBlockView,
icon: chartIcon,
group: 'common',
restricted: false,
mostUsed: true,
sidebarTab: 1,
security: {
addPermission: [],
view: [],
},
};
return config;
}
And the package.json
file of your addon:
{
"main": "src/index.js",
}
Warning
An addon's default configuration method will always be loaded.
Providing optional add-on configurations#
You can export additional configuration functions from your addon's main
index.js
.
import applyConfig, {loadOptionalBlocks,overrideSomeDefaultBlock} from './config';
export { loadOptionalBlocks, overrideSomeDefaultBlock };
export default applyConfig;
Addon dependencies#
Addons can depend on any other JavaScript package, but they can also depend on
other Volto addons. To do this, specify the name of your Volto addon dependency
in your dependencies
key of package.json
and create a new addons
key in
the package.json
of your addon, where you specify the extra Volto addon
dependency.
By doing this, the addons can "chain-load" one another, so you don't have to keep track of intermediary dependencies.