# Integration marketplace app

On this page, we will take you through our Integration marketplace app - a NextJS application for quickly deploying an integration/automation marketplace so that your end users can discover and use your Embedded solutions.

## Overview

On this page, we will take you through our [**Integration marketplace app**](https://github.com/trayio/nextjs-marketplace-app)\*\* \*\*- a NextJS application for quickly deploying an integration/automation marketplace so that your end users can discover and use your Embedded solutions.
The end users will see a library of solutions like this:
![integrationMaketplace](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/714Xmejj80naCG9PsXz0SH_marketplace_homepage.png)
They can also see their Solution Instances:
![solutionInstances marketplace](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/5VeQ6snzUgpZHKYRKWXR9f_solutionInstances_marketplace.png)
**Features:**

* Quickly get up and running with Tray Native Embedded
* Abstracts away all of the GraphQL API calls needed to provision users and create solutions
* Can be embedded in an iframe within your own product
* Simple JSON Web Token based authentication/authorization flow
* Simple JSON configuration for customising the look and feel of the marketplace
* Can be used as a template to build a more customised marketplace user experience

## Prerequisites

You will need a [master token](#)
This requires an Embedded account and owner / admin privileges.

## Getting Started

### Cloning the repo

For this step, we are assuming you are using Github, Vercel supports other git clients such as Gitlab, Bitbucket, and others.

### 1 - Create a private repository for marketplace

[Create](https://github.com/new) a private repository that you will use for the Marketplace.
![private repo marketplace](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/6YJ2bbVGPWAsYG2Bw1j4Us_private%20repo%20marketplace.png)

### 2 - Add files to your private repository

Clone [Tray's Marketplace repository.](https://github.com/trayio/nextjs-marketplace-app)
![clone repo marketplace](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/7CQlEvTXWgfjXaEfFFR4xf_clone%20repo%20marketplace.png)
Add files from this repository to your private repo, commit changes and publish branch.
![commit files marketplace](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/3yVu4MJ8VblAbKSVbsSye5_commit%20files%20marketplace.png)
The above screenshot is from [Github Desktop](https://desktop.github.com/). We recommend using GUI clients for simplicity.

### Deploying to Vercel

You can deploy this repository directly through Vercel's [dashboard](https://vercel.com/dashboard).

### 1 - Create new project

![vercel step1](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/3foomyIMIuoV0EBleCR4DG_vercel_step1.png)
Choose create a new project from your dashboard. Here you will be asked to choose your git client. Choose your git client, you will be redirected to authorize Vercel. Upon doing this you will see your repositories listed as shown above. Now, click on 'Import' next to your marketplace repo.

### 2 - Configure the project

![vercel mastertoken](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/46zaPHqxAzHj8G88jCOmYW_vercel_mastertoken.png)
When configuring the project, add the MASTER\_TOKEN in the environment variables, and pass the value of the token. (this is used to verify requests which you send to the application. You can find your Tray API master token in your account by following [these instructions](https://tray.io/documentation/embedded/getting-started/embedded-id-and-master-token/).)

### 3 - Deploy

You can see the status of deployment through various stages.
![vercel deployment stages](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/7lZp1Q36Ed0mAdoROeTiWW_vercel_deployment_stages.png)

## Using the marketplace

The goal of this application is to be integrated directly into your own product so that your users can easily take advantage of the integration library you have been building out using Tray Native Embedded.
You can either:

* embed the application in your own product using an `<iframe>` tag,
* or forward users onto the app directly.

### 1. Generate Verification JSON Web Token

You can authorize your end users through a JSON Web token (JWT). [Here](https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImFsaUB0cmF5LmlvIiwibmFtZSI6IkFsaXN0YWlyIFJ1c3NlbGwiLCJleHBpcmVzIjoiMjAyMy0wNC0yMlQxMjozNDozMFoiLCJ0YWdGaWx0ZXIiOlsic2hvdyIsInByZW1pdW0iXX0.DIg1nJlREcnyvOYe-eEP3DFqdsomUG8hx1AaNC-x87o) is the required JWT format.
A brief explanation of three sections of your JWT:

### Header

It specifies algorithm and token type:

```json
\{
  "alg": "HS256",
  "typ": "JWT"
\}
```

### Payload

This contains user data, token expiry time and tags which you can use to present a filtered list of solutions.

```json
\{
  // A unique identifier for your user that
  // wont change across sessions.  It can be
  // any string, but should usually correspond
  // to an id in your own product/system so that
  // you can easily find the user via our API.
  "id": "jdoe@acme.com",
  // A pretty name used to identify the user in the
  // Tray dashboard UI and also for things like naming
  // user created authentications.
  "name": "John Doe",
  // (Optional) An ISO 8601 date that indicates when the
  // token/payload should expire.  Used for extra security
  // so that json web tokens cannot be reused in the future.
  "expires": "2023-04-22T12:34:30Z",
  // (Optional) A list of tags to filter the library by
  "tagFilter": ["basic", "premium"]
\}
```

### Signature

The signature is used to verify the identity of the sender of the JWT and ensures that the message wasn't changed along the way.

```json
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),  
	MASTER_TOKEN //Unencrypted
)
```

You can read more about how JWT tokens work [here](https://auth0.com/docs/secure/tokens/json-web-tokens).

> **Info:** Make sure that you sign this JSON web token on the server side, rather than the client side, as you should make sure your master token remains private.

### 2. Embed/Forward users to the application

Once you have signed a JSON web token, you should then forward the user (either directly or via an iframe) to the application url with the JSON web token in a `jwt` query parameter.
Example URL:
`https://example.com/?jwt={YOUR_JWT_TOKEN_HERE}`
This request will validate the JSON web token you provided and create/update the end user as needed in your Tray account. The end user can then browse and configure the solutions that you have published and create their solution instances.
...thats all
Yep, you read it right. This is all you have to do to get a Tray powered integration marketplace integrated with your own product!

## Customizing the deployment

The goal of this project is to provide a lightweight, but customisable way to deploy an integration marketplace. There are a number of different configuration/customisation options available.

### Solution tile

You can customize the Solution tile for a solution in [Solution settings](https://tray.io/documentation/tray-uac/embedded-integrations/key-embedded-concepts/solutions/) in the Tray UI
![marketplace solutionTileCustomize](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/6JqwpQpWRUyeoNqPrumFwb_marketplace_solutionTileCustomize.png)
Here is a list of custom fields that you can add in Solution settings:

| Field             | Type               | Required | Description                                                                                                                                                                                                                                                                                                             |
| ----------------- | ------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| image             | string             |          | An absolute URL to an image for that particular solution which will be displayed in the solution tile component. Requires [features.image](https://github.com/trayio/tray-integration-marketplace-app/blob/3e66edbef2c3457ae20f94e9f27f39aaec4a6b99/utils/config.js#L18 "features.image") configuration to be turned on |
| forceUnique       | yes/no, true/false | false    | A flag indicating if the solution can only have a single instance created, i.e. the user should only be able to configure this solution once, not multiple times                                                                                                                                                        |
| disableAutoEnable | yes/no, true/false | false    | By default all solutions will be auto enabled when they are confitured, and the only way to disable them is to delete them completely. If this is set to true, then configured solutions will have enable/disabled controls that the user can interact with, and they will not be enabled by default                    |

### Environment variables

| Name              | Required | Description                                                                                        |
| ----------------- | -------- | -------------------------------------------------------------------------------------------------- |
| MASTER\_TOKEN     | Yes      | Your Tray.io Master API token for validating JSON Web Tokens and making GraphQL API calls          |
| GRAPHQL\_ENDPOINT | No       | The GraphQL endpoint to use, if you want to do a regional (EU/APAC) deployment of your marketplace |

You can set these on Vercel's project settings page:
![envVariablesVercel](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/NrAfaiCPceZxxD66Xal0F_envVariablesVercel.png)

### App Settings

In [/utils/config.js](https://github.com/trayio/nextjs-marketplace-app/blob/e6a1882c2a6b79473bb463ca76be7feb7a0d9e83/utils/config.js#L38) you can configure these three common settings:

| Path                  | Type    | Default            | Description                                                                                                                                                                                                              |
| --------------------- | ------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| settings.windowMode   | boolean | true               | Launch the configuration wizard in a new popup window. If set to false, will navigate to the configuration wizard in the current iframe/page                                                                             |
| settings.partnerId    | text    | 'demo'             | The partner ID to be used in the configuration wizard, used to load wizard CSS styles                                                                                                                                    |
| settings.wizardDomain | text    | 'embedded.tray.io' | The domain name to use for launching the configuration wizard. Can be used for [white labelling](https://tray.ai/documentation/platform/embedded/advanced-features/whitelabelling/introduction "white labelling") the UX |

### App layout

You can configure other aspects of the look and feel of the application by editing [/utils/config.js](https://github.com/trayio/nextjs-marketplace-app/blob/e6a1882c2a6b79473bb463ca76be7feb7a0d9e83/utils/config.js#L5).
The available configuration options are:

| Path                                     | Type         | Default                                                  | Description                                                                                      |
| ---------------------------------------- | ------------ | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| color.pageBackground                     | CSS Color    | #f6f6f6                                                  | The general page background color                                                                |
| color.tileBackground                     | CSS Color    | #ffffff                                                  | The background color of the solution tiles                                                       |
| color.fgColor                            | CSS Color    | #333333                                                  | The main font/text color of the app                                                              |
| color.highlightBgColor                   | CSS Color    | #0068ed                                                  | The background color used for highlight buttons/controls                                         |
| color.highlightFgColor                   | CSS Color    | #ffffff                                                  | The foreground color used for highlight buttons/controls                                         |
| color.successBgColor                     | CSS Color    | #009e67                                                  | The background color used for success buttons/controls                                           |
| color.successFgColor                     | CSS Color    | #ffffff                                                  | The foreground color used for success buttons/controls                                           |
| color.dangerBgColor                      | CSS Color    | #e52c37                                                  | The background color used for danger buttons/controls                                            |
| color.dangerFgColor                      | CSS Color    | #ffffff                                                  | The foreground color used for danger buttons/controls                                            |
| features.tags                            | Boolean      | true                                                     | Show the solutions tags on the solution tile and allow searching/filtering by tag                |
| features.image                           | Boolean      | true                                                     | Show an image on each solution tile, based on the image custom field                             |
| features.tabs                            | Boolean      | true                                                     | Show the Library/My Connections tab control on the root view                                     |
| features.logo                            | Boolean      | true                                                     | Show a logo, only on the individual configuration pages (for now)                                |
| layout.grid.columns                      | Number       | 3                                                        | Number of columns in the solution grid                                                           |
| layout.grid.loadingCols                  | Number       | 9                                                        | Number of tiles to show when loading data on the solution grid                                   |
| layout.grid.gap                          | CSS Property | 24px 24px                                                | The CSS property for the table layout gap                                                        |
| layout.image.maxWidth                    | CSS Size     | 100%                                                     | The maximum width of a solution image                                                            |
| layout.image.maxHeight                   | CSS Size     | 96px                                                     | The maximum height of a solution image                                                           |
| layout.image.height                      | CSS Size     | 96px                                                     | The specific height of a solution image                                                          |
| layout.logo.maxWidth                     | CSS Size     | 48px                                                     | The maximum width of the logo image                                                              |
| layout.logo.maxHeight                    | CSS Size     | 48px                                                     | The maximum height of the logo image                                                             |
| content.connectCTAText                   | Text         | Connect                                                  | The connect CTA button text                                                                      |
| content.disconnectCTAText                | Text         | Disconnect                                               | The disconnect CTA button text                                                                   |
| content.modifyCTAText                    | Text         | Update                                                   | The modify CTA button text                                                                       |
| content.updateCTAText                    | Text         | Edit                                                     | The update CTA button text                                                                       |
| content.libraryTitle                     | Text         | Library                                                  | The library title text, used on the library tab                                                  |
| content.connectionsTitle                 | Text         | My Connections                                           | The connections title text, user on the my connections tab                                       |
| content.connectionText                   | Text         | connection                                               | Text for a "connection"                                                                          |
| content.connectedText                    | Text         | connected                                                | Text for "connected"                                                                             |
| content.enableText                       | Text         | Enable                                                   | Text for "enabled"                                                                               |
| content.disableText                      | Text         | Disable                                                  | Text for "disabled"                                                                              |
| content.connectSolutionMessage           | Text         | You have been invited to connect                         | Default message when a user has been invited to configure/connect a solution via a link          |
| content.updateSolutionMessage            | Text         | Please update your connection below                      | Default message when a user has been given a link to modify an existing configuration/connection |
| content.connectCloseErrorMessage         | Text         | The connection wizard was closed before it was completed | The error message when the solution wizard is closed before completing                           |
| content.connectFinishedSuccessMessage    | Text         | Connection was successful                                | The message for when a solution is successfully configured                                       |
| content.updateFinishedSuccessMessage     | Text         | Connection was successfully updated                      | The message for when a solution instance is successfully updated                                 |
| content.disconnectFinishedSuccessMessage | Text         | Connection was successfully remove                       | The message for when a solution instance is deleted                                              |
| images.favicon                           | URL          | /tray-mark.png                                           | A URL to a browser favicon                                                                       |
| images.logo                              | URL          | /tray-mark.png                                           | A URL to a logo                                                                                  |

## Troubleshooting

Here we list common errors that might occur:

### 404: NOT\_FOUND

Once the app is deployed, upon opening the URL you might see **404: NOT\_FOUND** popping up. This is rare but can happen.
![vercel notFound](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/3YKBTvQqN2iPu82au9wjK1_vercel_notFound.png)
Follow the steps below to resolve this:

1. Generate another MASTER\_TOKEN in your embedded org.

> **Info:** At any time, you could have two MASTER\_TOKEN in your embedded account. If you have hit the limit of 2 tokens already, delete the one that you are not using and generate another token.

2. Repeat the '[Deploying to Vercel](https://tray.ai/documentation/platform/embedded/overview/integration-marketplace-app/#deploying-to-vercel)' step ie. Create a new project and configure it to use the new MASTER\_TOKEN.

Please [contact support](https://tray.ai/documentation/help/getting-support/creating-a-support-ticket/) if this doesn't work for you.

### GraphQL Error (Code: 403)

![vercel 403 error](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/5H7q6Ox9Xa949nclpK1MMc_vercel_403_error.png)
This comes up if the MASTER\_TOKEN linked to the project is stale (deleted/no longer exists in your embedded org).
Please verify the MASTER\_TOKEN value in the project settings on vercel is a valid active MASTER\_TOKEN in your embedded account. Updating the MASTER\_TOKEN value with an active value and redeploying will fix this.

### Invalid Token

![vercel invalidToken](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/xH62luiLtB83Fa2MUfNoU_vercel_invalidToken.png)
This comes up when you use an invalid JWT token. You can validate your token at jwt.io
![vercel INVALIDTOKEN jwtio](https://tray.ai/documentation/images/platform/embedded/overview/integration-marketplace-app/5KwhKb26BfhCebKqvzVNHq_vercel_INVALIDTOKEN_jwtio.png)

## Advanced Usage

The application supports a number of advanced usage options. Refer to our [repo docs](https://github.com/trayio/nextjs-marketplace-app#advanced-usage) to unlock the full potential.
