# Using a Front-End Framework with Twilio Serverless

Additionally to using Twilio Assets to host audio files for your phone calls or files for shared logic between your Twilio Functions you can also use it to serve front-end web assets such as HTML, JS and CSS files.

In this guide we'll talk about how you can use the Serverless Toolkit to use front-end frameworks to build you web assets. As an example we'll be using [React](https://reactjs.org/) as a front-end framework but you can use any common framework including [Vue](https://vuejs.org/) and [Angular](https://angular.io/).

## Setup

### Setup your Twilio Serverless project

If you don't already have an existing project using the Serverless Toolkit, go ahead and [create one by following the instructions in our Getting Started guide](/docs/labs/serverless-toolkit/getting-started). Otherwise, keep reading.

### Pick your build tool

In this guide we'll be using [Parcel](https://parceljs.org/) as our build tool of choice but you can apply similar steps to [Webpack](https://webpack.js.org) or other bundlers.

Make sure to install your bundler tool in the `devDependencies` section of your `package.json`.

To install Parcel run:

```bash
npm install parcel-bundler --save-dev
```

### Define your project structure

By default a project created with the Serverless Toolkit will contain a `functions/` and an `assets/` directory. In our case we'll want to keep the two directories but we'll also add two new directories:

* **`src/`** will contain our front-end code that we'll end up passing through the Parcel Bundler
* **`dist/`** will serve as the source of truth for the assets that we'll deploy. In our case this will be a combination of the bundled assets from `src/` and the static files from the `assets/` directory.

Create the `src/` directory and add an `index.html` file to it as this will serve as the entry point for our bundler.

This is where you'll reference other files that should be bundled such as stylesheets or JavaScript files. For more information, make sure to check out the [Parcel documentation](https://parceljs.org/getting-started/webapp/).

### Update your gitignore

Since the `dist/` directory contains bundled files it does not make sense to version control this directory. Instead make sure to add it to your `.gitignore` file at the root of your project.

```text
dist/
```

### Install other helpful tools

We'll be using two other tools:

* [`concurrently`](https://npm.im/concurrently) to run the Parcel build process at the same time as `twilio-run` to serve our project.
* [`ncp`](https://npm.im/ncp) to copy files from `assets/` to `dist/`
* [`rimraf`](https://npm.im/rimraf) to delete the `dist/` directory before building the Assets

Install the two dependencies by running:

```bash
npm install concurrently ncp --save-dev
```

### Configure the Serverless Toolkit

By default the Serverless Toolkit will use the `assets/` directory to serve and deploy Twilio Assets.

You can modify this behavior by using the `--assets-folder` flag but the easier way is by creating/modifying your `.twilioserverlessrc` file at the root of your project the following way:

```jsonc
{
  "commands": {},
  "environments": {},
  "projects": {},
  // !mark(1)
  // "assets": true     /* Upload assets. Can be turned off with --no-assets */,
  "assetsFolder": "dist"     /* Specific folder name to be used for static assets */,
  // ..
}
```

### Set up your build steps

Next we need to define a couple of `"scripts"` inside our `package.json` to make executing the right steps easier.

Modify the `scripts` section of your `package.json` the following way:

```jsonc
// !mark(2:5,7:10)
"scripts": {
  "prebuild": "rimraf dist",
  "build": "parcel build src/index.html -d dist",
  "postbuild": "ncp assets dist",
  "predeploy": "npm run build",
  "deploy": "twilio-run deploy",
  "start:web": "parcel watch src/index.html -d dist",
  "start:twilio": "twilio-run",
  "prestart": "ncp assets dist",
  "start": "concurrently npm:start:web npm:start:twilio"
},
```

This way you'll have three distinct commands:

* `npm start` will start the build server for Parcel and serve all Assets and Functions locally using `twilio-run`
* `npm run build` to build all front-end assets and copy over all static files from `assets/`
* `npm run deploy` will run `npm run build` and take all files in `dist/` and deploy them together with all Functions from `functions/` to Twilio Functions.

> \[!NOTE]
>
> If you are using `twilio serverless:deploy` to deploy your application instead of `twilio-run` you have to manually run `npm run build` first and then can normally deploy using `twilio serverless:deploy`.

## Start building your front-end

Now that we set up our build chain you can start developing your project.

Most things should work as you are used to but there are a few things to keep in mind.

### Installing Dependencies

All dependencies for your UI should be installed as `devDependencies` unless they are also used from within your Functions. For example, let's say we want to use React with [Twilio's Paste Design System](https://paste.twilio.design). We'd install the dependencies the following way:

```bash
npm install react react-dom prop-types @twilio-paste/core @twilio-paste/icons --save-dev
```

Note the `--save-dev` at the end. If you are using `yarn` or `pnpm` both of them support equivalent flags to store dependencies as `devDependencies`.

If you do not install them as `devDependencies` but as `dependencies` instead, they'll be installed in your Twilio Functions deployment which increased deployment times and might cause other unintended side effects including failed builds.

### Multiple file versions

When you run `npm run deploy` or `twilio serverless:deploy` the tool will automatically deploy everything in the `dist/` folder but nothing else. Meaning if you are building your output files with file hashes in the name (e.g. `main.a124bfc.js`) and the build changes that hash to a different one (e.g. `main.a12222f.js`) and you deleted the `dist/` folder prior to building (default in the scripts above) this will result in `main.a124bfc.js` to not be served anymore post deployment. *The Serverless Toolkit currently does not support additive deployments that would support both versions to be available.*

On the flip-side keeping your `dist/` folder as lean as possible will reduce the deployment time.

### Calling Functions

With the setup described above you should be able to call any of your Functions that exist in the `functions/` directory by specifying the relative path of them. For example for a Function with the file `functions/token.js` you can make an HTTP request from within your front-end to `/token`.

For example:

```js
fetch('/token')
  .then(response => response.json())
  .then(data => {
    console.log(data);
  });
```

### Static Assets

We talked about "static" assets above? What are those and why are we keeping those separately in a `assets/`. With static assets in this case we mean any file we don't want to have processed by our build tooling. Common types of such assets could be media files — for example an mp3 file that you are referencing in the TwiML for your Twilio Voice call — or a private JavaScript module that you are referencing for from one of your Twilio Functions to store shared logic. In general private assets are likely going to be static assets that you might want to store in the `assets/` directory.

### Limitations

At the current moment Twilio Assets does not support the following two features that you might have to consider when building your front-end on Twilio Serverless:

1. **No URL fallbacks/redirects** meaning you cannot use tools such as `react-router` unless you are operating them in a hash-based routing mechanism. You'll always have to serve to specify the full URL. The only current exception is if you have a file with the path `/assets/index.html` you can use `/` to reference the same file. In our case this means that you'd have to have Parcel output a file in the directory `dist/assets/index.html` which then, once deployed, will be available both at `https://<service_name>-<number>-<environment_suffix>.twil.io/` and `https://<service_name>-<number>-<environment_suffix>.twil.io/assets/index.html`.
2. **No built-in build system** you have to build all the respective files and trigger your deployment either locally or using your own CI/CD system of choice. Check out the [following guide on using Twilio Serverless from CI/CD for more guidance](/docs/labs/serverless-toolkit/guides/continous-deployment).
