Build a Waitlisting Application in Vue using Xata and Cloudinary
Tags: vue, xata, cloudinary, javascript
Published: 2022-11-24 15:55:37

For many reasons, businesses start their introduction to the market by launching a waitlist. Universities and medical institutions are known for having waitlists for admissions and surgeries, respectively.

This article will discuss building a waitlisting application in Vue using Cloudinary and Xata.

[Cloudinary](https://cloudinary.com/signup?utm_source=hackmamba&utm_campaign=hackmamba-hackathon&utm_medium=hackmamba-blog) is a cloud-based video and image management platform that offers services for managing and transforming uploaded assets for usage on the web.

Xata is a [Serverless Data platform](https://xata.io/docs/intro/serverless-data-platform?utm_source=hackmamba&utm_campaign=hackmamba-hackathon&utm_medium=hackmamba-blog) that simplifies how developers work with data by providing the power of a traditional database with the usability of a SaaS spreadsheet app.


## GitHub

Check out the complete source code [here](https://github.com/MoeRayo/xata-cloudinary-waitlist).


## Netlify

We can access the live demo [here](https://phenomenal-sunburst-10b96a.netlify.app).

## Prerequisite

Understanding this article requires the following:

- Installation of Node.js
- Basic knowledge of JavaScript
- A Cloudinary account (sign up [here](https://cloudinary.com/signup?utm_source=hackmamba&utm_campaign=hackmamba-hackathon&utm_medium=hackmamba-blog))
- Creating a free account with [Xata](https://xata.io?utm_source=hackmamba&utm_campaign=hackmamba-hackathon&utm_medium=hackmamba-blog)


## Creating a Vue app

Using the `vue create <project-name>` command, we will create a new Vue app.
The process of scaffolding the project would provide a list of options, which could look like this:


![Vue application scaffolding options](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mqjtxnnsmq5otc37ffkx.png)

We can start our Vue application by running the following command:

```javascript
cd <project name>
npm run serve
```
Vue will, in turn, start a hot-reloading development environment accessible by default at `http://localhost:8080`.


## Styling

The CSS framework to be used in this project is [Tachyons CSS](https://tachyons.io/). Install it by running the command below in the terminal.

```javascript
npm i tachyons
```

Afterward, make it globally available for usage in the project by adding the line below in our `src/main.js`:

```javascript
import 'tachyons/css/tachyons.css';
```

## Creating a Xata Database

To create a database on Xata, we must either log into our account or create a new [account](https://xata.io?utm_source=hackmamba&utm_campaign=hackmamba-hackathon&utm_medium=hackmamba-blog). Next, we will go to the user dashboard's database tab to create an appropriate database.

![Database creation on Xata](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a078jummhysarbjqq9r7.png)

We will create a new table within the database and add the appropriate records/fields that we want the table to have. In the case of the solution we are building, we will create a `signups` table with three fields: `firstname`, `lastname`, and `email`.
These fields signify the data we will track in our application before saving it to the database.


![The newly created table with the records](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3xm7veecwbzm4tn4ubks.png)

## Setting up Xata in our Vue application

### Installing Xata CLI
We will first need to install Xata CLI on our machine. To do this, we will open the command line terminal as an administrator and run the command below.

```javascript
npm install -g @xata.io/cli@latest
```
### Installing Xata in our project
To use Xata in our project, we will install the Xata software development kit (SDK) from the command line like so:

```javascript
npx xata
```
After this, we can then initialize Xata for use in our application by running the command below:

```javascript
xata init
```
Xata will present us varieties of options from which we can choose. In the end, Xata will generate some files for usage, among which we will have the `.xatrc` and `.env` files.
We will need to edit the name of the Xata API key in our Vue app to the one below to allow the Vue application to pick up the environment variable.

```javascript
VUE_APP_XATA_API_KEY="add your api key"
```
## Cloudinary Setup

For our application's asset management, if you haven't already, you need to create an account with Cloudinary by clicking [**here**](https://cloudinary.com?utm_source=hackmamba&utm_campaign=hackmamba-hackathon&utm_medium=hackmamba-blog). Creating an account is entirely free.
We will need to install the [Cloudinary Vue.js SDK](https://cloudinary.com/documentation/vue_integration?utm_source=hackmamba&utm_campaign=hackmamba-hackathon&utm_medium=hackmamba-blog) with the command below before configuring it in your Vue app.

```javascript
npm install cloudinary-vue
```
We will need to configure the installed SDK in our Vue app by navigating to the `main.js` and adding the following to the file.

```javascript
import Cloudinary from "cloudinary-vue";

Vue.use(Cloudinary, {
  configuration: { 
    cloudName: "XXX," //add the cloudinary cloudname here,
    secure: true }
});
```
Our waitlist will have an image, which we will upload to Cloudinary. In this case, we used this image by [Hannah Busing](https://unsplash.com/photos/4J16oO4MmXs?utm_source=unsplash&utm_medium=referral&utm_content=creditShareLink).

## Adding the landing page image

We want our waitlist application to have the image we uploaded to Cloudinary. To do this, we will create a file named `components/TheCloudinaryBackground.vue` and add the code below:

```javascript
<template>
  <cld-image publicId="hannah-busing-unsplash" dpr="auto" class="dn db-l w-50-ns vh-100" quality= "auto">
    <cld-transformation flags="rasterize" />
  </cld-image>
</template>
<script>
export default {
  name: "TheCloudinaryBackground",
}
</script>
```
From the above, we achieved the following:

- Cloudinary provides us with several templates to use in our Vue app. One of which is the `<cld-image />`  and the `<cld-transformation />` components we will use to generate our invoice
- Passed in the `publicId` of the Cloudinary file we will be using, which is named `hannah-busing-unsplash`
- Cloudinary components support asset transformations, which we leveraged by adding attributes like the `dpr` attribute, which we set to a value of `auto`. The `dpr` attribute ensures that users receive images at their devices' pixel ratio(dpr) and size.

To render this template, we will need to import it into the `views/HomeView.vue` file like so:

```javascript
<template>
  <div class="flex-l flex-row-l justify-center justify-between-l">
    <TheCloudinaryBackground />
  </div>
</template>
<script>
import TheCloudinaryBackground from "@/components/TheCloudinaryBackground.vue";
export default {
  components: {
    TheCloudinaryBackground,
  }
}
</script>
```

## Creating the waitlisting form

The waitlisting application is incomplete without the form where interested candidates can register.
To create this form, we will create a `components/TheWaitlistForm.vue` file and add the code below.

```javascript
<template>
  <div class="bg-waitlist vh-100 w-50-ns w-100-m">
    <div class="w-70 center pv6">
      <h3 class="f2 f1-m f-headline-l measure-narrow lh-title mv0">
        <span class="lh-copy brown pa1 tracked-tight">
          Joinr.
        </span>
      </h3>
      <h4 class="f5 fw1 lh-copy georgia i mt0">
        Be one of the first to access our service!
      </h4>
      <p></p>
      <form @submit.prevent="submitForm">
        <label for="firstname" class="db mb2 brown b georgia">First Name</label>
        <input type="text" class="db w-80 w-60-m pa2 br2 mb3 ba bw1 b--brown" name="firstname" id="firstname" v-model="firstname" placeholder="First name">
        <label for="lastname" class="db mb2 brown b georgia">Last Name</label>
        <input type="text" class="db w-80 w-60-m pa2 br2 mb3 ba bw1 b--brown" name="lastname" id="lastname" v-model="lastname" placeholder="Last name">
        <label for="email" class="db mb2 brown b georgia">Email</label>
        <input type="email" class="db w-80 w-60-m pa2 br2 mb4 ba bw1 b--brown" name="email" id="email" v-model="email" placeholder="Email">
        <div class="w-100">
          <button type="submit" class="f6 ttu tracked black-80 bg-brown pa3 br3 white bb link b--brown hover-white dim bg-animate pointer">Join waitlist</button>
        </div>
      </form>
    </div>
  </div>
</template>
<script>
export default {
  data: () => ({
    firstname: "",
    lastname: "",
    email: ""
  })
}
</script>
```
From the code block above, we achieved the following:

- Created a functional form to handle interested candidates' input for the waitlist
- Added the `data` in the Vue script to manage the names and email of the people who will fill out the form

To render this template, we will need to import it into the `views/HomeView.vue` file. Together with the imported Cloudinary background, our `views/HomeView.vue` file should be like the below:

```javascript
<template>
  <div class="flex-l flex-row-l justify-center justify-between-l">
    <TheCloudinaryBackground />
    <TheWaitlistForm />
  </div>
</template>
<script>
import TheCloudinaryBackground from "@/components/TheCloudinaryBackground.vue";
import TheWaitlistForm from "@/components/TheWaitlistForm.vue";
export default {
  components: {
    TheCloudinaryBackground,
    TheWaitlistForm
  }
}
</script>
```
At this stage, our page should look like the below:

![The landing page view](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/juawd2yac42h65mlg8to.png)

## Creating the success page

We want to ensure that on successfully adding the user's details to the waitlist, the user gets directed to a confirmation page. For this, we will create a file called `views/SuccessView.vue` and add the code below:

```javascript
<template>
  <div class="bg-waitlist vh-100">
    <div class="w-60-l w-80-m w-100 center tc pv6 ph3">
      <h3 class="f1 measure-narrow lh-title mv0">
        <span class="lh-copy brown pa1 tracked-tight">
          You are now on the waitlist
        </span>
      </h3>
      <h4 class="f5 fw1 lh-copy georgia i mt0">
        We will reach out to you soon with juicy updates!
      </h4>
      <a href="/" class="db link f6 ttu tracked black-80 bg-brown pv3 br3 white bb link b--brown hover-white dim bg-animate pointer mt5 w-70 w-30-ns center">
        Go To Home
      </a>
    </div>
  </div>
</template>
```
From the code block above, we were able to achieve the following:

- Created a success page which the user gets directed to
- Added a button that takes the user back to the home page

Our waitlist confirmation page should look like the following:

![Waitlist confirmation page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jgcces5z0d6ezygdts7c.png)

## Submitting waitlist 

We must submit the form data from interested people into the **"Signups"** table in our previously created Xata database. To do this, we will add the code below to the script tag of the `components/TheWaitlistForm.vue` file.

```javascript
<script>
import { getXataClient } from '@/xata'
export default {
  data: () => ({
    // data goes here
  }),
  methods: {
    async submitForm() {
      const xata = getXataClient()
      await xata.db.signups.create({
        firstname: this.firstname,
        lastname: this.lastname,
        email: this.email
      }).then(() => {
        this.$router.push({path:`/success`})
      })
    }
  }
}
</script>
```
From the code block above, we achieved the following:

- Imported the Xata client 
- Created a new record for the user on the Xata database
- At successful record creation, the user's view gets changed to the waitlist confirmation page

At this point, our waitlist application should look like the below:


![Complete waitlist application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f5nbssi9zme1cvy2ovou.gif)

## Conclusion

This article discusses how to build a waitlisting application using Cloudinary and Xata. Cloudinary was used for asset management and image transformation, while we used Xata for storing user details.

## Resources
- [Xata.io documentation](https://xata.io/docs/overview?utm_source=hackmamba&utm_campaign=hackmamba-hackathon&utm_medium=hackmamba-blog)
- [Cloudinary transformation reference](https://cloudinary.com/documentation/transformation_reference?utm_source=hackmamba&utm_campaign=hackmamba-hackathon&utm_medium=hackmamba-blog)