# Bundled app

So you decided to host your entire codebase on Zendesk's servers and go through each update verification, fine by me :eyes:. Here is how this boilerplate can accommodate your needs.

## Create a webapp project

1. Creating a React + Vite project

```bash
cd packages/ && yarn create vite
```

2. Let's give our project a name - this name does not affect much, but keep it simple and do not include special characters in there, as this name will be referenced in `manifest.json` file later automatically.\
   I will call it `super-cool-app`
3. Choose whatever Vite setup options you would like to use, those do not affect the boilerplate at all.\
   I chose:\
   \- React as framework\
   \- Use TypeScript
4. Install the packages required by Vite app to run

```bash
cd super-cool-app && yarn
```

{% hint style="info" %}
Remember, these options selected in step 3 do not affect any boilerplate setup. Each project is a separate project and can have any technology it requires.
{% endhint %}

## Alias scripts to manage React + Vite project

You don't want to every time go inside `/packages/super-cool-app` to start the dev server. It is more convenient to do so from the root of your entire boilerplate, like 2 demo applications are showcasing. Let's do the same!

In the root folder of the boilerplate (*attention, not our new Vite + React project, but 2 levels up*), open `package.json` file and add following to the `scripts` property:

```
"super-cool-app:start": "node scripts/run.mjs super-cool-app"
```

Here, the parameters of `scripts/run.mjs` receives a name of the package to be launched, which is a name of our newly created React + Vite package.

While we are at it, let's also add a build script.&#x20;

Modify the `build` script to add the following:

```
"build": "node scripts/build.mjs prod super-cool-app"
```

Here, `scripts/build.mjs` receives an environment to build the app for (production a.k.a prod) and a name of the package. If you have multiple apps / packages, just list them here without commas.

Let's verify that everything works as expected! In the root directory, where we modified the `package.json` file, let's start up our React + VIte package:

```bash
yarn super-cool-app:start
```

If everything was done correctly, you can see the following log:

<figure><img src="/files/7gPHqnQ8Q3nRtM0zTUpn" alt=""><figcaption><p>Successful launch of Vite + React application</p></figcaption></figure>

## Create a zaf.config.json file

Now, let's make this project recognisable by boilerplate, so that we can see it in our Zendesk instance.

In the root of your newly created project (I will refer to it as `super-cool-app` in my case), create `zaf.config.json` file.

```bash
cd packages/super-cool-app && touch zaf.config.json
```

Open it (or your entire boilerplate project) in your code editor (~~I use vim btw~~) and add the following content:

```json
{
  "location": "nav_bar",
  "server_side": false, // Careful, this parameter is different to what you see in Server side app page
  "dev_url": "http://localhost",
  "production_url": "index.html",
  "dev_port": 5173,
  "size": {
    "height": 400
  }
}
```

You can learn more about what this file is in the [section zaf.config.json of Configuration page](https://pineapps.gitbook.io/zendesk-applications-framework-boilerplate/create-your-own/pages/b0U9Ka0lBD0ev198QHu2#zaf.config.json).

Unlike server side app, our `production_url` property here should always point to a `.html` file. This will be handled by boilerplate's build scripts to turn this into a URL that Zendesk expects:

`assets/${project package name}/index.html`

Last command to run, is to create a `zcli` server that will establish connection between our application and Zendesk:

```bash
yarn zcli:start
```

That's all it takes get a basic version of our bundled app running in your Zendesk instance. Now, you can verify that everything works by visting your Zendesk ticketing instance, and do not forget to append `?zcli_apps=true` to the end of the url.

Example: <https://d3v5878-he.zendesk.com/agent/dashboard?zcli_apps=true>

On the left side you will notice a small icon that is our application entry point:

<figure><img src="/files/WePvaYzV24lJxVz2DWij" alt=""><figcaption></figcaption></figure>

Once opened, you should be greeted with default React + Vite page.

<figure><img src="/files/HmawtWXXUSKjVG0JYX7I" alt=""><figcaption><p>Successful application running inside the Navbar in Zendesk</p></figcaption></figure>

## Add zafClient

We have our basic application, you are free to do whatever you want, but you will probably want to interact with Zendesk ZAF SDK (Zendesk Applications Framework).

To do so, this boilerplate has a small special Vite plugin, that will insert `<script>` tag with Zendesk's SDK into your `index.html` file at dev and build times.

Navigate to the `vite.config.ts` file (or `vite.config.js` if you chose pure JS madness) and add the plugin to it:

```typescript
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

import injectZafHtmlPluginModule from "@app/zendesk/vite-plugin-inject-zaf-html";
const { injectZafHtmlPlugin } = injectZafHtmlPluginModule

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react(), injectZafHtmlPlugin()],
});

```

Now, you can start using `zafClient` SDK in your application. Here is one example to get started:

Go to `src/App.tsx` file and add the following lines to your `App` component:

```tsx
  const [zafClient, setZafClient] = useState(null);

    useEffect(() => {
    if (window.ZAFClient) {
      setZafClient(window.ZAFClient.init());
    }
  }, [window.ZAFClient]);

  useEffect(() => {
    if (zafClient) {
      zafClient.on("app.registered", function (data) {
        console.log("app.registered", data);
      });
    }
  }, [zafClient]);
```

{% hint style="info" %}
Treat this as illustration of how SDK works, not React best practices, which is outside of the scope of this article. You probably want to put more care into instantiating the SDK and reusing it in the application.
{% endhint %}

### zafClient types for additional typesafety

To get types autocomplte for `zafClient` (which will allow you to fetch data in a type-safe manner), adjust your `tsconfig.json` file with following properties:

```
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    ".next/types/**/*.ts",
    "../../node_modules/zendesk-types/**/*.d.ts" // Add type reference to existing zendesk package
  ]
```

And change `moduleResolution` to `node:`

```
"moduleResolution": "node"
```

{% hint style="info" %}
Types for zafClient are under a long construction, so some types maybe incorrect / not exhaustive.
{% endhint %}

## Build and publishing your app

Now, when you are happy with application changes, you can simply run

```
yarn build
```

And you can observe that your application is being built into root directory `/dist` folder.

```
.
├── assets
│   ├── logo-small.png
│   ├── logo.png
│   ├── logo.svg
│   └── super-cool-app
│       ├── assets
│       │   ├── index-DiwrgTda.css
│       │   ├── index-DmyYh-Yb.js
│       │   └── react-CHdo91hT.svg
│       ├── index.html
│       └── vite.svg
├── manifest.json
└── translations
    └── en.json
```

Where `super-cool-app` name is being picked up by build script automatically, assets importing is also adjusted by boilerplate (to set base url) and you can see the resulting `manifest.json` file:

```json
"location": {
  "support": {
    "nav_bar": {
      "url": "assets/super-cool-app/index.html",
      "size": {
        "height": 400
      }
    }
  }
}
```

You are now ready to package the application with a helper utility:

```
yarn zcli:package
```

And entirely ready application will appear in `/dist/tmp` folder.

#### Get in touch

If you have any questions or troubles, feel free to jump into [Discord server](https://discord.gg/CGBW27FK7U) where I am always reachable and other like-minded developers can help you out.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://pineapps.gitbook.io/zendesk-applications-framework-boilerplate/create-your-own/bundled-app.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
