How do I create a settings page for my plugin?

Developer FAQ
  • The Quickstart plugin has everything you need to get started, including an example of how to create a settings page for the plugin.

    However, it is not readily apparent what parts of the code pertain to that ask, so this topic tries to disambiguate.

    To create a settings page in the ACP, you'll want to do five things.

    1. Create a template so you can add your form fields, etc.
    2. Mount a route that loads that template
    3. Have a link to that template show up in the ACP navigation
    4. Allow settings to be saved
    5. Access those settings from within your library.js

    Create a template so you can add your form fields, etc.

    In plugin-quickstart, you can see where templates are defined by checking plugin.json:

    "templates": "static/templates"

    Any templates you add to this directory will be merged with NodeBB's core template files, and bundled together during ./nodebb build. Any templates you define that conflict with core templates override the core template.

    You'll notice a template file: static/templates/admin/plugins/quickstart.tpl

    Since this is your own plugin, you'll want to rename this file to something more relevant, e.g. foobar.tpl.

    Update the template as necessary to include any settings you'd like to define. Later on, we'll be using the NodeBB-provided settings module to persist settings to the database, so the only considerations for the template are:

    • That a <form> element exists with a corresponding className, e.g. <form role="form" class="foobar-settings">
    • That form fields have a name attribute (these names are the property names saved into the database)
    • That a save button exists. You can probably use this partial: <!-- IMPORT admin/partials/save_button.tpl -->. add it to the bottom of the template if it's not there already.

    Mount a route that loads that template

    To do this, you'll need to listen to the static:app.load hook (see how it is registered in plugin-quickstart, here).

    We call the helper function .setupAdminPageRoute in order to mount the route:

    routeHelpers.setupAdminPageRoute(router, '/admin/plugins/quickstart', [], controllers.renderAdminPage);

    Have a link to that template show up in the ACP navigation

    To do this, you'll need to listen to the hook (see how it is registered in plugin-quickstart, here).

    Relevant code:

    plugin.addAdminNavigation = (header) => {
    		route: '/plugins/quickstart',
    		icon: 'fa-tint',
    		name: 'Quickstart',
    	return header;

    Allow settings to be saved

    The modules property allows you to define require.js or CommonJS modules that can be automatically run by NodeBB (or imported/required via other files).

    You can add one for ../admin/plugins/foobar.js.

    Note: ../admin and ../client are magic keywords that allow NodeBB to determine whether a module is loaded for the ACP or for a client-side page. NodeBB will load the corresponding file based on template name, and if a method called init() exists, will execute it.

    If you look inside static/lib/admin.js, you'll see the code that wires up the form and hooks into the Settings module in NodeBB.

    You probably also want to change the module name too:

    define('admin/plugins/foobar', [...

    Access those settings from within your library.js

    Lastly, now that the mount is routed and settings can be saved, you can retrieve them from within your library.js by directly invoking the meta module:

    const { mySetting } = await meta.settings.get('foobar');
  • julianJ julian referenced this topic on
  • thank you for this.

  • TheBronxT TheBronx referenced this topic on

Suggested Topics

  • 1 Votes
    1 Posts

    Your plugin may want to expose some user-specific options, and to accomplish that, you'll want to create a page accessible from within their user profile.

    In Harmony, plugin-added pages are added to the left-hand sidebar:

    In Persona, plugin-added pages are behind the overflow menu:

    You'll need to add listeners to two hooks, and modify your page template accordingly.


    Live example

    You'll need to specify a route in the user profile using this hook. In it, note the accountMiddlewares block, which contains some common middlewares that are sensible defaults. You'll need middleware.buildAccountData in order to retrieve some boilerplate data that all account routes need.


    Live example

    You'll then want to specify the menu option, including label, icon, and visibility options. visibility allows you to specify which users can see the option (e.g. self only, admins only, etc.)

    The template

    In your template for the user page, you'll want to prefix it with <!-- IMPORT partials/account/header.tpl --> and suffix it with <!-- IMPORT partials/account/footer.tpl -->. These two lines will wrap your template content with the theme-specific structure. For example, in Harmony, a sidebar is used in the accounts pages. The header and footer partials will ensure they are also present in your template. The middleware.buildAccountData middleware you added in the first step will ensure the data necessary is present.

  • 0 Votes
    10 Posts

    I would really like to get this working.
    Does anyone have any thoughts on why this code above might not work?
    The board was converted from phpbb using a plugin. Is it possible that left something behind that is breaking the code shared above?

  • 0 Votes
    9 Posts

    I have found the issue.
    Previously settings have been used for extra block creation, now it's customSettings
    Changing everything accordingly fixes issue.

  • 1 Votes
    1 Posts


    ACP as a plugin/module. Introduce new namespace, for example nodebb-acp-somename

    So you will have:

    For themes: nodebb-theme-somename For plugins: nodebb-plugin-somename For ACP: nodebb-acp-somename

    Encapsulate current ACP to acp-module, and see, in near future, how 3rd party ACP panel will popup (Angular based, or Material based, or something another...) 😉

  • 0 Votes
    4 Posts

    Update to latest version and try again.