This tutorial demonstrates how to use the Wix CLI to build an app named Business Buddy. The app creates a chatbot connected to an AI that appears on a site owner’s dashboard. The AI answers questions about products in the site's store.
We'll use the following steps to build the Business Buddy app:
The end result will look like this:
You can see the finished app code in this GitHub repo.
If you want to run the app code from the repo you'll need to do some setup first.
appId
property in the wix.config.json file with the App ID from your new app.wix.run
URL in the server.ts whitelist to use the App ID from your new app.OPENAI_API_KEY
and set its value to your API key.WIX_APP_SECRET
and set its value to your app secret.PORT
and set its value to your desired port number.Before getting started, make sure that:
We use the Wix CLI to initialize our app. In the process of initializing our app, the Wix CLI automatically:
src
folder containing initial boilerplate code for an app with a dashboard page.package.json
file containing your app dependencies.To initialize the app:
Open a terminal and navigate to the folder where you want to create your app.
Run the following command:
If prompted, press y to install the package.
Select A new Wix App.
Enter a name for your app. Let’s name our app Business Buddy.
The CLI prompts you to choose a development site (test site), which you’ll use throughout this tutorial to run and test your app. You can choose an existing Wix site as your development site, or create a new one. Let’s Create a new Development Site. The newly created development site is automatically named something like Dev Site 5x2043, and can be found in your Wix account’s list of sites.
Follow the prompt to open the development site on your default browser. If the browser doesn’t open, install your app on your test site manually and skip the next step.
Click Agree & Add to install your app on your development site.
Back in the terminal, press Enter to select the default folder name (business-buddy
) for your app in your local file system.
You now have a new app, a new folder in your local file system, and a local git repository for developing and testing your app.
In the app, we want the dashboard pages to appear in the dashboard like this:
To create this structure, we use the CLI's generate
command to generate dashboard page extensions. This places dashboard page files in subfolders of the dashboard/pages folder.
Run the following command and follow the prompts to create a dashboard page extension:
When prompted for a page route, type product. The route is the path that is appended to the dashboard base URL to access the dashboard page. Learn more about page routes.
When prompted for a page name, enter Products.
Upon completion, the extension files will be created in your local app files under the chosen route with the following structure:
For more information about these files, see Dashboard Page Extension Files and Code.
Each dashboard page is defined by a page.json file and a page.tsx file. The page.json file defines the page metadata and the page.tsx file defines the page UI and functionality.
Each file pair exists in a folder that determines the route to a page.
Repeat the above steps but create a page with route settings, and page name Settings.
Now that you’ve initialized the app, you can run a local development server to see the app in action, and view local changes as you develop it. The local development environment runs the app and its initial boilerplate code on the development site that you chose during app creation.
To run a local development server:
Run the following command:
Press 1 to open the local environment in your browser. Your development site’s dashboard opens, and you can see your newly created app’s dashboard pages in the left sidebar. We add the content of our app’s dashboard pages in step 5.
Your app is now running on your development site. As you develop your app, any changes made to your app’s code are reflected in real time on your development site.
If your changes don’t show up, try refreshing the page, or closing and reopening the development site.
Before we start coding our app, we need to install some npm packages. In your terminal, run the following commands:
The purpose of each of these packages will become clear as we progress.
In our app, we want the Products page to look like this:
This design is consistent with the rest of the pages in the dashboard. To create it, we’ll use the React components provided by the Wix Design System.
The Products page is built from:
The Products page UI is defined in several files in the dashboard folder as follows:
QueryClientProvider
and WixStyleReactProvider
wrapper. QueryClientProvider
allows fetching, caching, synchronizing, and updating server state. WixStyleReactProvider
provides styling according to Wix's design system.Let's take a look at the code used to build the page's UI. We'll take a look at the code for the page's functionality a bit later.
Notice how the code uses components from the Wix Design System to build the page. Other than that, it's a standard React component. For more information about each component, see AutoComplete, Card, TableActionCell, Divider, Layout, and Page.
Note: At this point, we're showing the code with a hardcoded, dummy product object just to demonstrate how the page will look once a product is selected. We'll add real products to the page later in the tutorial.
Here again, the code uses Wix Design System components to build the component UI. For more information about each component, see Text, Box, Card, Input, and Loader.
We’ll use the following CSS to define the width of the input element for the ProducChat component:
Finally, here is the code for the QueryClientProvider
wrapper. We use the withDashboard()
higher-order component from the Wix Dashboard React SDK to wrap this component. This will allow us to make Wix SDK calls from inside the component's code.
In our app, on the Products page, users can choose a product from the site's Store.
To work with the Stores app on a user's site, we use the Wix Dashboard React SDK and the Wix React SDK. We already showed how to set up your dashboard page extensions with the Dashboard React SDK in the previous section. In this section, we'll use the React SDK to retrieve site data to display in the app.
Before getting started making calls with the SDK, you need to request the proper permissions.
You can find out which permissions your app needs by checking the API reference for the functions you call. Our app queries store products, so it needs the Read Products permission.
You can add permissions in your app's dashboard by selecting Permissions from the sidebar.
After setting up permissions, our app can retrieve a list of products from the site's store.
In your Products page code add the following imports:
These imports give us access to the Wix SDK overall and the particular functionality we need for retrieving products.
Once we import everything, we'll add the following hooks to our ProductsPage component:
We’ll use the useWixModules()
hook to create an initialized copy of the products
module that we can use directly in our page extension code. We retrieve the products
module's queryProducts()
function that we can use to access store products.
Next, we use the React useQuery()
hook to query for products whose names start with a query string. This string will be set based on the product selected in our AutoComplete
component. We also make sure to handle any errors.
Finally, let’s replace our dummy current product with the proper type now that we have it.
Now that we have access to a list of the site’s products, we can use them to populate the AutoComplete
component and define what happens when a user selects a product.
First, we set the AutoComplete
component's status
.
Then, we set the AutoComplete
component's options
to the products we got from the query by mapping them to a list of options objects with id
and value
properties.
Next, we set up the AutoComplete
component's onSelect
function to set the component's current product.
While we're at it, we also set the AutoComplete
component's onChange
function to set the search query and clear the current product.
Finally, we set the AutoComplete
component's value
to the current product if there is one.
In our app, the Products and Settings dashboard pages will need to communicate with an app backend to work with the OpenAI API and to store user settings.
In general, you communicate with a backend server from a Wix App the same way you would in any other type of app.
You do, however, need to pay special attention to:
Later, we'll see how to do all that on the server. For now, let's focus on what we need to do on the front end.
Each time an app is installed on a site a unique instance ID is assigned. You can use the instance ID to authenticate requests sent from an app and to know which instance of the app is sending the request. The instance ID is added as a query param to your app’s dashboard pages.
Let's see how we add code to send requests to the server using the instance ID. In our app, we've placed this code in a file named utils.ts in the dashboard folder.
First, we create a function to get the instance ID from the page's URL.
Next, we create a function to fetch data from the server using the instance ID to authorize the request. Notice how we call the getAppInstance()
function described above to create the authorization header.
import.meta.env.VITE_API_BASE_URL
accesses the environment variable VITE_API_BASE_URL
provided by Vite.
So, ${import.meta.env.VITE_API_BASE_URL}/${relativePath}
dynamically constructs a full URL by combining the base URL defined in VITE_API_BASE_URL
with the relativePath
passed to the function.
Now that we've set up the infrastructure to make secure requests to the server, we can use the ProductChat
component to send and receive chat messages.
To add backend requests to ProductChat, we do the following:
First, in ProductChat.tsx we import the utility function described above.
Then, we add a function to submit messages, send them to the server, and update the state with the response. Notice how this function calls fetchWithWixInstance()
to post a new message to the server.
Finally, we call submitMessage()
when the send icon is clicked.
And we call submitMessage()
again when enter is pressed in the Input
component.
You can see the complete code for the Products page in our GitHub repo.
In our app, the Settings page is defined in the dashboard/pages/settings/page.tsx as follows:
As usual, the code uses Wix Design System components to build the component UI. For more information about each component, see Button, Card, FormField, InputArea, Loader, and Page.
In this code, we import useMutation
and useQuery
from react-query
:
useQuery
is used to fetch data from the server and handle caching. In the code below, useQuery
fetches the current behaviorDirective
from the server and stores it in data.
useMutation
is used to update data on the server. In the code below, useMutation
sends a new behaviorDirective
to the server via a POST request:
This component renders a page where we can configure a behavior directive. It includes the following elements:
useMutation
sends the new directive to the server by calling mutation.mutate
. It shows a loader instead while the mutation is in progress.behaviorDirective
state.When a user changes the behavior setting on the Settings page, we want to show a toast at the top of the dashboard page.
To show toasts, update dashboard components based on state changes, and open and close dashboard modals, we use the Wix Dashboard React SDK.
First, we need to import the useDashboard()
hook from the Dashboard React SDK.
Then, we need to call the useDashboard()
hook in the code for the React component where we want to display the toast. We need to add the following to our Settings page component code:
Finally, we call the showToast()
function and provide a message and type. In our app, we want to show the toast when a behavior setting has been successfully changed, so we call showToast()
in the onSuccess
of the mutation used by the Save button.
In our app, the backend server must receive requests for chat messages, and for storing and retrieving settings values. Each of these operations must be performed by calling an endpoint exposed on the server.
In this implementation, we use a simple Express server. You're free to use any type of server for your app's backend.
When an app server receives a request to an endpoint, it needs to:
You'll also need to set up CORS to make sure your server allows the requests from your app.
To set up CORS properly, we need to add headers that allow access from certain origins and with certain HTTP methods.
In our case, we whitelist localhost for testing purposes and the URL for our app frontend on the Wix App CDN.
The URL of an app on the CDN is in the following format:
You can find your app's App ID on your app's dashboard.
This is how we whitelist the URLs on our server using Express:
Now that we've dealt with CORS issues, the next thing to do is to authenticate the requests coming into our server.
To authenticate requests, we first need our app's secret key from your app's dashboard. We get the key from the OAuth page in our app's dashboard. Then we add the key to an environment variable named WIX_APP_SECRET
.
Now that we have the key, we can write code to authorize the request. In our case, we write this code in a file on our server named utils.ts.
To add authentication logic, we do the following:
First, we create the authorizeWixRequest()
function. This function reads the authorization header sent from our app frontend and checks it using the parseInstance()
function described below.
Next, we create the parseInstance()
function to parse the received app instance and check it against our app's secret key using the validateInstance()
function described below.
Then we create the validateInstance()
function to authenticate the instance against our app secret.
To use this authentication code, we call the authorizeWixRequest()
function and pass it an incoming request. For example, when we receive a request for a product chat we authorize the request before continuing.
In our app, the backend server must store settings data for each app instance. We use the instance ID to associate a particular setting value with a particular instance of our app. We can do this by storing the instance ID alongside each setting value in a simple key-value store.
The authorizeWixRequest()
function we created in the previous section returns the parsed instance information, including an instanceId
. We can pass that information to the key-value store when we process a request, such as a /settings
POST, as you can see here.
Then, in the key-value store, we can store the value of the instanceId
as the key and the setting text as the value.
After testing your app and seeing that it works as expected, you can create a public preview of your app, build your app, create and manage app versions, and deploy your app. For more information on these tasks, see Build and Deploy an App with the CLI
After completing this tutorial, you have created a dashboard AI chatbot that integrates with a custom backend and Wix site data. At this point, you have all you need to know to develop an app. Feel free to play around with the example app some more, or get started on writing your own app.