# Example apps

> Annotated walkthroughs of the bundled support, incident, approval and contact-form app definitions, block by block, for builders reading YAML.

Canonical HTML page: https://conclude.io/doc/reference/examples/
Last updated: 2026-11-02

---

This page walks through four of the app definitions that ship with Conclude. The YAML below is rendered directly from the product's bundled files, so it cannot drift from what you install. Read it with the [YAML reference](https://conclude.io/doc/reference/yaml/) and the [attributes reference](https://conclude.io/doc/reference/attributes/); the annotations say only what each block does in that app.

Three of the four (`support`, `incident`, `approval`) are in the installable catalog. `contact-form` is bundled but not listed there; see [its section](#contact-form) for how to use it.

## Support

The smallest useful ticketing app: a subject, a description and a resolution.

The complete definition is the bundled template [support.yaml](https://conclude.io/doc/examples/support.yaml).

- `settings.subject: ticket` names the activity in default UI text, so buttons and messages say "ticket"
- `settings.alert: ${__channel} ${initiator}` notifies the install channel and the ticket's creator on every event. `${__channel}` is an [install-time macro](https://conclude.io/doc/reference/macros-and-roles/#install-time-macros), replaced with the concrete channel at install
- `roles.owner: ${__blank}` opts out of the default owner (the installer), so a new ticket starts unowned. `roles.members` makes everyone in the install channel plus the creator a participant
- The three attributes are all [reserved names](https://conclude.io/doc/reference/attributes/#reserved-attribute-names): `title` is required on every app; `body` is the long description; `conclusion` is filled in when the ticket is closed. The app only relabels them (Subject, Description, Resolution) and adds placeholders

## Incident

Adds a status list, a severity scale and a field that stays hidden until the incident is closed.

The complete definition is the bundled template [incident.yaml](https://conclude.io/doc/examples/incident.yaml).

- `roles.owner: ${__blank}` again starts each incident unowned. No `alert` is set, so it takes the default: the install channel
- `root_cause` has `postmortem: true`: the field appears only on the conclude form and on closed incidents, which keeps root-cause analysis out of the create and edit forms
- `status` is a `select` on the reserved `status` attribute with `defaultValue: open` and `visible: edit,conclude`, so it is not shown on the create form. All six option names are [built-in statuses](https://conclude.io/doc/reference/statuses/#built-in-statuses); the app only relabels them (for example `on_hold` becomes "Snoozed", `closed` becomes "Resolved"). Because the names are built in, no `state:` binding is needed: `closed`, `duplicate` and `rejected` map to the closed state by default
- `severity` is a `select` with `defaultValue: none` and `visible: always`. The option labels carry emoji; the option names are plain identifiers
- `notes` has `visible: edit`, so internal notes can only be added after creation

## Approval

Shows a `superusers` role and an option that closes the request when chosen.

The complete definition is the bundled template [approval.yaml](https://conclude.io/doc/examples/approval.yaml).

- `roles.superusers: ${__installer}` gives the elevated role to whoever installs the app. Any other user or channel can be substituted after install
- `status` has `editors: ${superusers}`, so only superusers can set the decision. `important: true` highlights it in the activity banner and list, and `hint:` explains the effect on the form
- The `approved` option sets `state: closed`, so selecting it concludes the request. `rejected` needs no `state:` because it is a built-in status that already maps to closed (see [custom statuses](https://conclude.io/doc/reference/statuses/#custom-statuses-on-the-status-attribute)). Either decision closes the approval, as the hint says
- `conclusion` is declared with `visible: never`, which removes the resolution field from every form; the decision itself is the outcome

## Contact form

Turns inbound web form posts into activities through a web connector.

**Not in the installable catalog.** `contact-form.yaml` is bundled with the product but is not one of the ten templates offered at install time ([bundled templates](https://conclude.io/doc/apps/templates/#bundled)). To use it, install any template and paste this definition into the Expert tab ([editor: Expert](https://conclude.io/doc/apps/editor/expert/)).

The complete definition is the bundled template [contact-form.yaml](https://conclude.io/doc/examples/contact-form.yaml).

- `settings.rateLimit: 6/min` throttles inbound connector traffic; the reference default is `10/min` (see [settings](https://conclude.io/doc/reference/yaml/#settings))
- `roles.owner: ${initiator}` makes the creator the owner, and `roles.members: ${__channel}` adds the install channel as participants
- `webConnector.id: <auto-generated>` is a placeholder; it fails validation, so the product replaces it with a generated connector ID when the app is saved. The ID becomes part of the `POST /v1/form/<cid>` URL (see [endpoints](https://conclude.io/doc/reference/endpoints/#form))
- The attribute map is meant to fill `body` from the form field `message`, falling back to `<no message>`, and to build `title` from a default value only, using the submitted `name` and `email` fields as macros. Entries use the keys `external`, `internal`, `defaultValue` and `description`. When a mapped field is submitted empty or missing, or an entry has no `external` at all, its `defaultValue` is used
- `texts` overrides the launch button, form captions and chat intros so the UI says "request" rather than a generic subject

**The attribute_map key is ignored.** The bundled file spells the map `attribute_map`, but the product reads `attributeMap`, and unknown keys are dropped silently when the app is parsed. Until the file is fixed, the map in this example has no effect: submitted fields are stored under their own names, `title` gets no default from the map, and a mandatory `title` with no value is filled with `-`. If you paste this definition, rename the key to `attributeMap`.

## Related pages

- [YAML reference](https://conclude.io/doc/reference/yaml/) for every top-level field
- [Attributes](https://conclude.io/doc/reference/attributes/) and [Statuses](https://conclude.io/doc/reference/statuses/) for the keys used above
- [Macros and roles](https://conclude.io/doc/reference/macros-and-roles/) for `${__blank}`, `${__installer}` and `${__channel}`
- [Connectors](https://conclude.io/doc/reference/connectors/#web-connector) for the web connector and [Templates](https://conclude.io/doc/apps/templates/) for installing from the catalog

