This quick start guide explains the basics of writing a Mattermost app. In this guide you will build an app that:
manifest.json
, declares itself an HTTP application that acts as a bot, and attaches to locations in the user interface.send-modal
in its bindings
to a button in the channel header, and the form send
to a /helloworld
command.send
function that sends a parameterized message back to the user.send-modal
function that forces displaying the send
form as a modal.Before you can start with your app, you first need to set up a local developer environment following the server and webapp setup guides. You must enable the apps feature flag before starting the Mattermost server by setting the environment variable MM_FEATUREFLAGS_AppsEnabled
to true
by e.g. adding export MM_FEATUREFLAGS_AppsEnabled=true
to your .bashrc
or using make run-server MM_FEATUREFLAGS_AppsEnabled=true
.
In the System Console, ensure that the following are set to true:
Enable Bot Account Creation
Enable OAuth 2.0 Service Provider
You also need at least go1.16
installed. Please follow the guide here to install the latest version.
The apps plugin is a communication bridge between your app and the Mattermost server. To install it on your local server, start by cloning the code in a directory of your choice run:
git clone https://github.com/mattermost/mattermost-plugin-apps.git
Then build the plugin using:
cd mattermost-plugin-apps
make dist
Then upload it to your local Mattermost server via the System Console.
Start building your app by creating a directory for the code and setting up a new go module:
mkdir my-app
cd my-app
go mod init my-app
go get github.com/mattermost/mattermost-plugin-apps@master
Your app has to provide a manifest, which declares app metadata. In this example, the following permissions are requested:
Create a file called manifest.json
containing:
{
"app_id": "hello-world",
"version":"0.8.0",
"display_name": "Hello, world!",
"icon": "icon.png",
"homepage_url": "https://github.com/mattermost/mattermost-plugin-apps/examples/go/hello-world",
"requested_permissions": [
"act_as_bot"
],
"requested_locations": [
"/channel_header",
"/command"
],
"http": {
"root_url": "http://localhost:4000"
}
}
Locations are named elements in the Mattermost user interface. Bindings specify how an app’s calls should be displayed and invoked from these locations.
The app creates a channel header button, and adds a /helloworld send
command.
Create a file called bindings.json
containing:
{
"type": "ok",
"data": [
{
"location": "/channel_header",
"bindings": [
{
"location": "send-button",
"icon": "icon.png",
"label":"send hello message",
"call": {
"path": "/send-modal"
}
}
]
},
{
"location": "/command",
"bindings": [
{
"icon": "icon.png",
"label": "helloworld",
"description": "Hello World app",
"hint": "[send]",
"bindings": [
{
"location": "send",
"label": "send",
"call": {
"path": "/send"
}
}
]
}
]
}
]
}
Functions handle user events and webhooks. The Hello World app exposes two functions:
/send
that services the command and modal./send-modal
that forces the modal to be displayed.The functions use a simple form with one text field named "message"
, the form submits to /send
.
Create a file called send_form.json
containing:
{
"type": "form",
"form": {
"title": "Hello, world!",
"icon": "icon.png",
"fields": [
{
"type": "text",
"name": "message",
"label": "message"
}
],
"call": {
"path": "/send"
}
}
}
Apps may include static assets. One example that was already used above is the icon
for the two bindings. Static assets must be served under the static
path.
Download an example icon using:
curl https://github.com/mattermost/mattermost-plugin-apps/raw/master/examples/go/hello-world/icon.png -o icon.png
Finally, add the application logic that gets executed when either the slash command is run or the modal submitted by creating a file named main.go
with the following content:
package main
import (
_ "embed"
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/mattermost/mattermost-plugin-apps/apps"
"github.com/mattermost/mattermost-plugin-apps/apps/appclient"
"github.com/mattermost/mattermost-plugin-apps/utils/httputils"
)
//go:embed icon.png
var iconData []byte
//go:embed manifest.json
var manifestData []byte
//go:embed bindings.json
var bindingsData []byte
//go:embed send_form.json
var formData []byte
func main() {
// Serve its own manifest as HTTP for convenience in dev. mode.
http.HandleFunc("/manifest.json", httputils.HandleJSONData(manifestData))
// Returns the Channel Header and Command bindings for the app.
http.HandleFunc("/bindings", httputils.HandleJSONData(bindingsData))
// The form for sending a Hello message.
http.HandleFunc("/send/form", httputils.HandleJSONData(formData))
// The main handler for sending a Hello message.
http.HandleFunc("/send/submit", send)
// Forces the send form to be displayed as a modal.
http.HandleFunc("/send-modal/submit", httputils.HandleJSONData(formData))
// Serves the icon for the app.
http.HandleFunc("/static/icon.png",
httputils.HandleData("image/png", iconData))
addr := ":4000" // matches manifest.json
fmt.Println("Listening on", addr)
fmt.Println("Use '/apps install http http://localhost" + addr + "/manifest.json' to install the app") // matches manifest.json
log.Fatal(http.ListenAndServe(addr, nil))
}
func send(w http.ResponseWriter, req *http.Request) {
c := apps.CallRequest{}
json.NewDecoder(req.Body).Decode(&c)
message := "Hello, world!"
v, ok := c.Values["message"]
if ok && v != nil {
message += fmt.Sprintf(" ...and %s!", v)
}
appclient.AsBot(c.Context).DM(c.Context.ActingUserID, message)
httputils.WriteJSON(w,
apps.NewOKResponse(nil, "Created a post in your DM channel."))
}
The app is a simple HTTP server that serves the files you created above. The only application logic is in send
, which takes the received "message"
field and sends a message back to the user as the bot. Also, an ephemeral message is posted in the current channel.
Run your app using:
go run .
Then run the following slash commands on your Mattermost server:
/apps install http http://localhost:4000/manifest.json
Confirm the installation in the modal that pops up. You can leave the App secret field blank, the app does not require one.
Select the “Hello World” channel header button in Mattermost, which brings up a modal:
Type testing
and select Submit, you should see:
You can also use the /helloworld send
command by typing /helloworld send --message Hi!
. This posts the message to the Mattermost channel that you’re currently in.
Uninstall the app using:
/apps uninstall hello-world