Skip to content

Getting Started

Apps enable you to extend the capability of Vibe's platform and integrate your product seamlessly. Apps are highly configurable and scalable, requiring no provisioning or infrastructure on your end.

Requirements

All contrail apps are built using NodeJS and NPM. The apps are managed using the publicly available Contrail cli tool.

CLI Commands

The contrail CLI is your main tool to creating, managing, and installing apps. To list all the commands available to you, run contrail app --help. You can view how each of these commands are used in an app's lifecycle

contrail app --help
# Create, deploy, and manage apps
#
# USAGE
#   $ contrail app COMMAND
#
# COMMANDS
#   app create     Create an app from a template
#   app delete     Delete the app from the app marketplace
#   app getApiKey  Get an api key for an app
#   app install    Install an app from the marketplace
#   app publish    Publish the app
#   app uninstall  Uninstall an app that is currently installed
#   app upgrade    Upgrade an installed app

App Structure

The app template offers a simple place to start coding your integration. It comes with existing compilation configuration and the necessary node modules to run and request information from the Vibe platform.

.
├── README.md
├── app.yml
├── package-lock.json
├── package.json
├── src
│   ├── actions
│   │   └── logItem.ts
│   └── main.ts
└── tsconfig.json

Actions

You will spend most of your time in the actions directory. This is where all your app actions will live. The files in the actions directory will be scanned for a class definition matching the expected criteria:

  • All actions must be in a class definition that implements AppAction
  • The execute function of the class must be decorated to match the identifier in the app.yml file.
logItem.ts
import { Entities } from '@contrail/sdk';
import { Action, AppAction, AppActionCallBack, AppActionCallbackStatus, Logger } from '@contrail/app-framework';

export class LogItemAction implements AppAction { // (1)

  @Action('logItem') // (2)
  public async execute(event, config: any, logger: Logger): Promise<AppActionCallBack> {
    logger.log('Starting Example Action');
    logger.log('Getting item from SDK');

    const item = await new Entities().get({
      entityName: 'item',
      id: event.id,
    });
    logger.log('Got item: ', item);

    return {
      output: {
        item,
      },
      status: AppActionCallbackStatus.SUCCESS
    };
  }
}
  1. The action class must implement AppAction
  2. The execute function must be decorated with the same identifier as the one used in the app.yml file.
app.yml
actions:
  logItem: # (1)
    name: "Log Item"
    description: "Fetches an item from the API and returns it to the log."
  1. This identifier maps directly to one declared in the @Action('logItem') decorator.

App Manifest

The app.yml file declares your app's specs, visibility, and how other developers can interact with it. Every detail in this file is important and will significantly impact the way your app appears and works in the marketplace.

appIdentifier (string)

The app identifier is a unique string that others can use to install your app. Once claimed, an identifier is reserved throughout the Vibe platform, and can not be duplicated. Additionally, an app's identifier can not be altered after creation. It is good practice to include the publisher name in the identifier (e.g. @vibe/vntana is an identifier for the native Vntana plugin published by Vibe's internal team).

appName (string)

The app's name as it appears in the marketplace.

appDescription (string)

The app's detailed description as it appears in the marketplace. This is the best place to include detailed app information, such as any required post-installation setup.

visibility (string)

public or private (default). Controls whether your app appears in the marketplace or not. See App visibility.

accessGrants (list)

A list of orgs that can install the app. Each org must have a orgSlug and a list of permissions that can be granted. The only permission available at the time of writing is install.

Example Access Grants
accessGrants:
  - orgSlug: recipient-org-1
    permissions:
      - install
  - orgSlug: recipient-org-2
    permissions:
      - install

publisher (string)

The publisher of the app, usually a company or team's name (e.g. Nike, Salesforce, VibeIQ, etc.)

thumbnail (string)

A public URL that points to an image. Used as the display icon in the marketplace.

Example Thumbnail Link
thumbnail: https://www.shutterstock.com/image-photo/birds-eye-view-pine-forest-600w-2239370259.jpg

appConfiguration (object)

Properties you can configure when you install the app. These property values will be available to all of your actions when they run.

Example App Configuration
appConfiguration:
  apiHost:
    label: "API Host"
    propertyType: "string"

actions (object)

An object that maps each key to an action name. Each action name should match exactly one Action decorator in one of the files in the actions directory. See Actions.

Example Actions List
actions:
  logItem:
    name: "Log Item"
    description: "Fetches an item from the API and returns it to the log."
    async: false
    actionConfiguration:
      message:
        label: "Additional message to log."
        propertyType: "string"

A list of external links. Each external link will appear on the app's page once the app has been installed. The links can be used to direct the user to external pages that may be required for documentation or additional post-install integration. Note that the external link support a few computed properties that can be helpful to include:

  • orgSlug: the slug of the org that's launching the external link (e.g. nasa-suits-prod).
  • appOrgId: the id of the specific installed app in that org.
  • appApiKey: the api key of the specific app installed in that org. This key can be used to make API requests.
  • referer: The referer site from which the external link was launched (e.g. https://admin.vibeiq.com/).
Example External Link
externalLinks:
  - name: "openGoogle"
    label: "Open Google"
    link: "https://google.com?scope=foo&orgSlug={orgSlug}&referer={referer}"
    extraAttributes:
      - name: "foo"
        value: "bar"

extensions (list)

The extensions that are published as part of this app. Each extension requires an identifier unique throughout the system, and a name for the user to see. The extensionType control what functionality the extension provides. userApps defines what apps the extension will appear in. iframeUrl is a link to where the extension is hosted (must be a publicly accessible URL). If your extension requires a modal, then modalDimensions can be used to define its size in the iframe.

Example Extensions List
extensions:
  - identifier: "colorChipGenerator"
    name: "Color Chip Generator"
    extensionType: DOCUMENT_AUTOMATION
    userApps:
      - BOARDS
    modalDimensions:
      width: 800px
      height: 800px
      maxWidth: 95vw
    iframeUrl: "https://d3i3vkef9zjhwv.cloudfront.net/"

Extension Types

  • DOCUMENT_AUTOMATION: manipulates documents in Board and Showcase apps. Has access to read and create elements on a document. For example, this can be used to add images or text to a board, or to run analysis of selected products in a board.

User Apps

  • BOARDS
  • SHOWCASE
  • PLAN
  • ALL

eventWorkflowTriggerKeyMapping (string)

This is an advanced feature that can 'derive' a trigger key for external events. External events are events sent to the VibeIQ API's /external-events end point from another system Here, you can define a string based on properties from the event payloads (which are custom to your payload). i.e. an event {details: {eventType: 'apparel'}, actionType: 'create'} can be parsed to apparel|create with "{details.eventType}|{actionType}". When this is defined, any event coming from your app's credentials will define a trigger key using this logic. You can then define workflows to run based on those external events, based on this trigger key definition.

Example Event Workflow Trigger Mapping
eventWorkflowTriggerKeyMapping: "{details.eventType}|{actionType}"