Adding pages to the webapp
Before reading this guide, make sure you know how to build, deploy, and debug a plugin.
Create a Java class implementing PageDefinition
For each page, you'll need to set a key and a name. The page key should have the format
plugin_key is computed from the
<artifactId> in your
pom.xml, or can be set explicitly in the pom using the
<pluginKey> parameter in the
sonar-packaging-maven-plugin configuration. All the pages should be declared in this class. Here is an example.
Configuring each page
There are 3 settings available when you define the page extensions using the
setAdmin(boolean admin): flag this page as restricted to users with "administer" permission. Defaults to
setScope(org.sonar.api.web.page.Page.Scope scope): set the scope of this page. Available scopes are
GLOBAL(default), which will add this page to the main menu, and
COMPONENT, which will add the page to a project, application, or portfolio menu (applications and portfolios only apply to Enterprise Edition and above).
setComponentQualifiers(org.sonar.api.web.page.Qualifier... qualifiers): if
setScope()is set to
COMPONENT, this sets to what kind of component the page applies to. Available qualifiers are
SUB_VIEWonly apply to Enterprise Edition and above). You can pass multiple qualifiers. If no qualifier is set, it will apply to all types.
/static/ directory, and boot up your page's application. This file should have the same name as the
page_id you defined in your
Each file must call the global
window.registerExtension() function, and pass its full key as a first argument (
governance/project_dump). The second argument is the start callback. This function will be called once your page is started, and receive information about the current page as an argument (see below). The return value of the start callback depends on how you want to implement your page:
If you want to use React, you should return a React Component:
If you want to use any other framework, you should perform any start logic directly inside the start function body, and return a shutdown callback:
options object will contain the following:
options.el: A DOM node you must use to inject your content.
options.currentUser: Information about the current user.
options.component: Contains the information of the current project, application, or portfolio.
options.branchLike: Contains the information of the current branch or pull request.
If you want a static CSS file to be loaded when your extension is bootstrapped, rather than using run-time inclusion of styles, you can pass
true as a third parameter to the
window.registerExtension() function. This will trigger the loading of a CSS file that must have the same basename as the registering JS file. I.e., if your extension JS file is
/static/global_page.js, the CSS file must be called
/static/global_page.css. The bootstrap will wait for the CSS file to be fully loaded before calling the
We recommend checking out the sonar-custom-plugin-example repository. It contains detailed examples using several front-end frameworks, and its code is thoroughly documented. It also describes how to run a local development server to speed up the front-end development, without requiring a full rebuild and re-deploy to test your changes.
© 2008-2023, SonarSource S.A, Switzerland. Except where otherwise noted, content in this space is licensed under a Creative Commons Attribution-NonCommercial 3.0 United States License. SONARQUBE is a trademark of SonarSource SA. All other trademarks and copyrights are the property of their respective owners.