# Add a backend component to an app plugin

A backend component for an app plugin allows you to extend the app plugin for additional functionality such as custom authentication methods and integration with other services.

The following are typical use cases for backend components in app plugins:

* Use custom authentication methods that aren't supported in Grafana
* Use authorization checks that aren't supported in Grafana
* Run workloads on the server side
* Connect to non-HTTP services that normally can't be connected to from a browser

## Before you begin[​](#before-you-begin "Direct link to Before you begin")

Install the following prerequisites before adding a backend component:

* Go ([Version](https://github.com/grafana/plugin-tools/blob/main/packages/create-plugin/templates/backend/go.mod#L3))
* [Mage](https://magefile.org/)
* [LTS](https://nodejs.dev/en/about/releases/) version of Node.js
* [Docker](https://docs.docker.com/get-docker/)

## Create a new app plugin[​](#create-a-new-app-plugin "Direct link to Create a new app plugin")

The Grafana [create-plugin tool](https://www.npmjs.com/package/@grafana/create-plugin) is a CLI application that simplifies Grafana plugin development, so that you can focus on code. The tool scaffolds a starter plugin, all the required configuration, and a development environment using [Docker Compose](https://docs.docker.com/compose/) for you.

1. In a new directory, create a plugin from a template using the create-plugin tool. When prompted for the kind of plugin, select <!-- -->app<!-- --> and answer yes to "Do you want a backend part of your plugin?":

   ```shell
   npx @grafana/create-plugin@latest

   ```

2. Go to the directory of your newly created plugin:

   ```shell
   cd <your-plugin>

   ```

3. Install the dependencies:

   ```shell
   npm install

   ```

4. Build the plugin frontend:

   ```shell
   npm run dev

   ```

5. In a new terminal window, build the plugin backend:

   ```shell
   mage -v build:linux

   ```

6. Start Grafana:

   ```shell
   docker compose up

   ```

7. Open Grafana, by default <http://localhost:3000>, and then go to **Administration** > **Plugins**. Make sure that your <!-- -->app<!-- --> plugin is there.

You can also verify that Grafana has discovered the plugin by checking the logs:

```text
INFO[01-01|12:00:00] Plugin registered       logger=plugin.loader pluginID=<your-plugin>

```

## Anatomy of a plugin with a backend component[​](#anatomy-of-a-plugin-with-a-backend-component "Direct link to Anatomy of a plugin with a backend component")

The folders and files used to build the backend for the <!-- -->app<!-- --> are:

| file/folder        | description                                                                                                                                            |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Magefile.go`      | It’s not a requirement to use mage build files, but we strongly recommend using them so that you can use the build targets provided by the plugin SDK. |
| `/go.mod`          | Go [modules dependencies](https://golang.org/cmd/go/#hdr-The_go_mod_file).                                                                             |
| `/src/plugin.json` | A JSON file describing the plugin.                                                                                                                     |
| `/pkg/main.go`     | Starting point of the plugin binary.                                                                                                                   |

#### The plugin.json file[​](#the-pluginjson-file "Direct link to The plugin.json file")

The [`plugin.json`](https://grafana.com/developers/plugin-tools/reference/plugin-json.md) file is required for all plugins. When building a plugin backend component, pay attention especially to these properties:

| property     | description                                                                                                                                                                           |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `backend`    | Set to `true` for plugins with a backend component. This tells Grafana that it should start a binary when loading the plugin.                                                         |
| `executable` | This is the name of the executable that Grafana expects to start. Refer to [plugin.json reference](https://grafana.com/developers/plugin-tools/reference/plugin-json.md) for details. |
| `alerting`   | If your backend data source supports alerting, set to `true`. Requires `backend` to be set to `true`.                                                                                 |

## Add authentication to your app plugin[​](#add-authentication-to-your-app-plugin "Direct link to Add authentication to your app plugin")

To learn more about adding authentication to your app plugin (for example, to call a custom backend or third-party API) and handling secrets, refer to [Add authentication for app plugins](https://grafana.com/developers/plugin-tools/how-to-guides/app-plugins/add-authentication-for-app-plugins.md).

## Access app settings[​](#access-app-settings "Direct link to Access app settings")

Settings are part of the `AppInstanceSettings` struct. They are passed to the app plugin constructor as the second argument. For example:

src/app.go

```go
func NewApp(ctx context.Context, settings backend.AppInstanceSettings) (instancemgmt.Instance, error) {
  jsonData := settings.JSONData // json.RawMessage
  secureJsonData := settings.DecryptedSecureJSONData // map[string]string
}

```

You can also get the settings from a request `Context`:

src/resources.go

```go
func (a *App) handleMyRequest(w http.ResponseWriter, req *http.Request) {
  pluginConfig := backend.PluginConfigFromContext(req.Context())
  jsonData := pluginConfig.AppInstanceSettings.JSONData // json.RawMessage
}

```

## Add a custom endpoint to your app plugin[​](#add-a-custom-endpoint-to-your-app-plugin "Direct link to Add a custom endpoint to your app plugin")

Here's how to add a `ServeMux` or `CallResource` endpoint to your app plugin.

### ServeMux (recommended)[​](#servemux-recommended "Direct link to ServeMux (recommended)")

Your scaffolded app plugin already has a default `CallResource` that uses [`ServeMux`](https://pkg.go.dev/net/http#ServeMux). It looks like this:

app.go

```go
type App struct {
	backend.CallResourceHandler
}

// NewApp creates a new example *App instance.
func NewApp(_ context.Context, _ backend.AppInstanceSettings) (instancemgmt.Instance, error) {
	var app App

	// Use an httpadapter (provided by the SDK) for resource calls. This allows us
	// to use a *http.ServeMux for resource calls, so we can map multiple routes
	// to CallResource without having to implement extra logic.
	mux := http.NewServeMux()
	app.registerRoutes(mux)
  // implement the CallResourceHandler interface
	app.CallResourceHandler = httpadapter.New(mux)

	return &app, nil
}

```

Now you can add custom endpoints to your app plugin.

The scaffolded code already contains a `resources.go` file with the `registerRoutes` function.

resources.go

```go
// this function already exists in the scaffolded app plugin
func (a *App) registerRoutes(mux *http.ServeMux) {
	mux.HandleFunc("/myCustomEndpoint", a.handleMyCustomEndpoint)
}

func (a *App) handleMyCustomEndpoint(w http.ResponseWriter, r *http.Request) {
  // handle the request
  // e.g. call a third-party API
  w.Write([]byte("my custom response"))
  w.WriteHeader(http.StatusOK)
}

```

### CallResource[​](#callresource "Direct link to CallResource")

You can also add custom endpoints to your app plugin by adding a `CallResource` handler to your backend component directly. You must implement the logic to handle multiple requests.

app.go

```go
func (a *App) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
	switch req.Path {
	case "myCustomEndpoint":
		sender.Send(&backend.CallResourceResponse{
			Status: http.StatusOK,
			Body:   []byte("my custom response"),
		})
	default:
		return sender.Send(&backend.CallResourceResponse{
			Status: http.StatusNotFound,
		})
	}
	return nil
}

```

You can also see the data sources [documentation on resource handler](https://grafana.com/developers/plugin-tools/how-to-guides/data-source-plugins/add-resource-handler.md) which you can also apply to your app plugin.

### Call your custom endpoint from frontend code[​](#call-your-custom-endpoint-from-frontend-code "Direct link to Call your custom endpoint from frontend code")

To call your custom endpoint from frontend code, you can use the `fetch` function from `getBackendSrv`. For example:

```ts
import { getBackendSrv } from '@grafana/runtime';
import { lastValueFrom } from 'rxjs';

function getMyCustomEndpoint() {
  const response = await getBackendSrv().fetch({
    // replace ${PLUGIN_ID} with your plugin id
    url: '/api/plugins/${PLUGIN_ID}/myCustomEndpoint',
  });
  return await lastValueFrom(response);
}

```

## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting")

### Grafana doesn't load my plugin[​](#grafana-doesnt-load-my-plugin "Direct link to Grafana doesn't load my plugin")

Ensure that Grafana has been started in development mode. If you are running Grafana from source, add the following line to your `conf/custom.ini` file:

```ini
app_mode = development

```

note

If you don't have a `conf/custom.ini` file already, create it before proceeding.

You can then start Grafana in development mode by running `make run & make run-frontend` in the Grafana repository root.

If you are running Grafana from a binary or inside a Docker container, you can start it in development mode by setting the environment variable `GF_DEFAULT_APP_MODE` to `development`.

note

By default, Grafana requires plugins to be signed. To load unsigned plugins, you need to configure Grafana to [allow unsigned plugins](https://grafana.com/docs/grafana/latest/administration/plugin-management/#allow-unsigned-plugins). For more information, refer to [Plugin signature verification](https://grafana.com/docs/grafana/latest/administration/plugin-management/#backend-plugins).
