Skip to content
Authors
  • Sem Tadema
    Sem TademaCTO

App bars are the UI an installed app adds to Caraer. A button on a record, a dialog that collects a file, a tab next to traits, or a tool in the sidebar — those are all app bars.

Define them in app.caraer.yaml (appBars). There is no caraer apps add app-bar scaffold. Push deploys the bar; the installer chooses where it is visible (which objects, or which suites for the sidebar tool).

If you have not scaffolded an app yet, start with How to create a Caraer app.

KindLocationsWhat the user seesWhat you ship
ActionRECORD_PREVIEW, RECORD_OVERVIEW, RECORD_TRAITA button. Click opens a dialog, then a webhook runswebhook + optional settingsSchema. No iframeUrl
IframeRECORD_DETAIL, TOOL_BAR, TRAIT_BARAn embedded pageiframeUrl (required). Webhook is optional

Action bars must not set iframeUrl. Iframe bars must set it. The platform rejects the other combination.

Where they appear

locationIn the Caraer appContext passed through
RECORD_PREVIEWAction buttons under the record preview cardCurrent record
RECORD_OVERVIEWAction buttons in the object view header (list / board)Current object, view, and trait
RECORD_TRAITAction buttons on a trait overview (page cards now; other traits later)Current record, object, view, and trait
RECORD_DETAILEmbedded iframe on the record detail pageCurrent record
TOOL_BARTool entry in the left sidebar, with the other toolsCompany (no record)
TRAIT_BARExtra tab next to the record's traitsCurrent view and trait

Preview and overview are the usual place for “do something to this record” (parse a CV, sync now). Detail and trait bar are for a persistent UI on the record. The tool bar is a company-wide surface — calendars, inboxes, dashboards.

Who sees a bar

Declaring appBars on the app is not enough. After install, visibility lives on the HAS_APP edge (appBarVisibility), keyed by app-bar UUID:

  • Record locations (RECORD_PREVIEW, RECORD_OVERVIEW, RECORD_DETAIL, and TRAIT_BAR) — list of object names. The bar shows only on those objects. An empty list means hidden.
  • RECORD_TRAITobject names and trait names. Both lists must match the current object and trait. Installers can currently pick page; other traits will be added when those overviews have a mount. An empty traits list hides the bar.
  • TOOL_BAR — list of suites. The bar shows when the company has one of those suites. An empty list means hidden.

Installers set this in Settings → Apps on the installation. Authors do not hard-code object names in the manifest for placement.

Action bars

Give the bar a webhook. Topic is always app.bar.triggered — not record.{object}.created. Delivery is SERVERLESS (a function in your app) or HTTP.

settingsSchema on the bar (not the app) is the dialog the user fills before the webhook runs. FILE and MULTI_FILE belong here, not on installation settings.

appBars:
  - name: upload_cv
    location: RECORD_OVERVIEW
    label: Upload CV
    actionLabel: Parse CV
    tooltipLabel: Parse a CV onto this candidate
    description: Upload a CV. Caraer will parse it onto this record.
    icon: file-arrow-up
    webhook:
      topic: app.bar.triggered
      deliveryMode: SERVERLESS
      serverlessFunction:
        name: upload-cv
    settingsSchema:
      - name: cv_file
        label: CV
        type: FILE
        required: true

label is the button. actionLabel is the primary button in the dialog. tooltipLabel is the hover / overflow tooltip.

The function receives the usual install envelope (installationToken, caraerApiBase, installation settingsSchema) plus app-bar fields:

{
  "event": "app.bar.triggered",
  "appBarUuid": "…",
  "appBarLabel": "Upload CV",
  "location": "RECORD_OVERVIEW",
  "recordUuid": "…",
  "object": "candidate",
  "viewId": "…",
  "trait": "…",
  "appBarSettingsValues": { "cv_file": "files/…" },
  "appBarSettingsSchema": [{ "name": "cv_file", "type": "FILE", "value": "files/…" }],
  "installationToken": "inst_…",
  "caraerApiBase": "https://api.caraer.com/api",
  "settingsSchema": []
}

Read the dialog from appBarSettingsValues. settingsSchema is still the installation settings — serverless delivery would overwrite a single settingsSchema with those, so the dialog is keyed separately.

Resolve a FILE / MULTI_FILE value with GET {caraerApiBase}/v2/files/?key=<value> (absolute URLs pass through).

Iframe bars

Set iframeUrl. Placeholders Caraer substitutes:

{recordUuid}, {object}, {viewId}, {trait}, {companyUuid}

appBars:
  - name: inbox_panel
    location: RECORD_DETAIL
    label: Inbox
    iframeUrl: https://apps.example.com/inbox?record={recordUuid}&object={object}
appBars:
  - name: calendar_tool
    location: TOOL_BAR
    label: Calendar
    tooltipLabel: Google Calendar
    iframeUrl: https://apps.example.com/calendar?company={companyUuid}

Caraer opens a short-lived iframe session. The embedded page can validate it and receive context (recordUuid, object, viewId, trait, companyUuid, userUuid) plus apiToken — the same short-lived inst_… Bearer used in webhooks. Call Caraer APIs with Authorization: Bearer plus that token.

Authoring notes

  • Put appBars in src/app/app.caraer.yaml. Push with caraer apps push --deploy.
  • Give each bar a stable name so push can reuse the existing node without a hand-written uuid.
  • Wire webhook.serverlessFunction.name to a local function folder.
  • Action bars need a webhook. Iframe bars need iframeUrl.
  • Do not put caraer_api_base or other platform URLs in bar settings. The runtime injects installationToken / apiToken and caraerApiBase.
  • Hide a bar by leaving its install visibility empty — do not delete the bar from the manifest unless you mean to remove it for every install.