Build a testimonial page with Appwrite Cloud using Nuxt

teri - May 13 '23 - - Dev Community

Most websites have a section dedicated to customer feedback on a product or service, which build trust and encourages others to try. A testimonial page is a statement about the validation and satisfaction of a company tool by happy customer comments on social media platforms like Twitter, LinkedIn, and so on.

Appwrite is an open-source backend platform alternative like Firebase, which provides all the necessary API features like authentication, databases, storage, functions, security and privacy, and so on for developing web, mobile, and flutter applications.

This tutorial will show you how to build a replica with Appwrite and Nuxt.

See the testimonial on the official Appwrite page.

appwrite testimonial

Let’s get started.

GitHub and Demo

You can reference the complete source code in this repo, and to see the testimonial page in action, view the project demo here.

Prerequisites

For this tutorial, you need the following:

  • Have Node >= 16 installed on your machine
  • Knowledge of CSS
  • Understanding of Vue.js
  • Have an Appwrite Cloud account

Request for an Appwrite Cloud, here.

Setting up Appwrite Cloud

Appwrite Cloud is used to create a new project. On your dashboard, click the “+ Create project” button and give it a name.

create a project

Creating a database

Navigate into the newly created “Testimonials” project, and on the left pane of the dashboard window, click Databases and create a database with a name.

Create databases

Creating collections

By clicking on the created database, you can create a collection with the “+ Create collection” button. Give this collection ****a name.

collections

Adding attributes
This section is about creating field parameters to hold all the data necessary to display client-side information. Within the created collections, testimonial-collection, click on the Attributes tab to make the attributes for this app.

Attribute Key Attribute type Format Size Default Value Required
comment String 1500 - Yes
imgUrl String url - Yes
name String 255 - Yes
role String 255 - Yes

PS: The Document ID generates automatically.

attributes

Creating documents
With all the attributes created in the Collections, let’s include some default data by clicking on the Documents tab and the “+ Create document” button. Now fill in data in the input field.

create documents

Next, select the Settings tab within the Collections, and update the permissions to manage user access and rights.

permissions

Also, you need to register your web app. On the left pane of your dashboard, click on Overview and the “+ Add platform” button. Choose the Web App option from the dropdown.

register web app

The asterisk () in the input field of the field **Hostname* ensures the web is accessible during development. If not set, cross-origin resource sharing (CORS) errors prevent access to the web app.

Creating a Nuxt app

Nuxt is an open-source framework built on Vue.js that makes web development powerful. To scaffold a new Nuxt project, run this command in the terminal:

    npx nuxi init testimonials
Enter fullscreen mode Exit fullscreen mode

Follow the on-screen instructions provided with the following commands:

    npm install
Enter fullscreen mode Exit fullscreen mode

The above command is responsible for installing all the required dependencies. Next, navigate to the project directory and start the development server, which should run on localhost:3000:

    cd testimonials && npm run dev
Enter fullscreen mode Exit fullscreen mode

Nuxt app

Adding Tailwind CSS

Tailwind CSS is a utility-first CSS framework that uses classes directly in your markup.

In the terminal, run this command to install the @nuxtjs/tailwindcss package:

    npm install -D @nuxtjs/tailwindcss
Enter fullscreen mode Exit fullscreen mode

Configuring Tailwind CSS
Before you can see the action of Tailwind CSS, open the file nuxt.config.ts in the root directory and include the module option within the defineNuxtConfig object:

    export default defineNuxtConfig({
      modules: ["@nuxtjs/tailwindcss"],
    });
Enter fullscreen mode Exit fullscreen mode

Creating environment variables

Environment variables store the secrets keys credentials from unauthorized access in the .env file. This step is essential to avoid committing and pushing your secrets to GitHub.

Check out this resource on creating environment variables in a Nuxt application.

Building the UI

The user interface for the testimonial page is a single page application (SPA) showing a collection of statements from satisfied customers or users of a product.

Create a directory called components in the root directory, and include this file named Testimonials.vue.

The updated project tree directory should look like this:

    .
    ├── components
    │   ├── Testimonials.vue
    ├── pages
    │   └── index.vue
    ├── public
    ├── package.json
    ├── tsconfig.json
    ├── package-lock.json
    ├── README.md
    ├── nuxt.config.js
    └── app.vue
Enter fullscreen mode Exit fullscreen mode

Copy-paste the following code into their respective files:

components/Testimonials.vue

    <template>
      <section class="mx-auto max-w-6xl w-4/5 mt-10">
        <div>
          <h1 class="text-3xl font-serif mb-3 md:text-5xl lg:text-6xl">
            Testimonials
          </h1>
          <p class="mb-10 text-slate-700">
            Learn from experts what they love about Appwrite Cloud
          </p>
        </div>
        <div class="grid gap-6 md:grid-cols-2 xl:grid-cols-3">
          <div
            class="border-2 rounded-lg p-4 flex flex-col justify-between transition-all ease-out">
            <p class="text-sm md:text-lg">
              Appwrite provides web and mobile developers with a set of easy-to-use
              and integrate REST APIs to manage their core backend needs
            </p>
            <div class="flex items-center mt-7">
              <img
                src="https://res.cloudinary.com/terieyenike/image/upload/v1635347142/ypz0tuyz60hirt1obdba.jpg"
                class="shrink-0 w-12 h-12 rounded-full border-slate-200 shadow mr-4 bg-black object-cover"
                loading="lazy"
                alt="william smiling" />
              <div>
                <p>
                  <span class="font-bold">Willian Imoh</span>
                </p>
                <p class="text-xs md:text-sm font-light text-slate-700">
                  Product Manager
                </p>
              </div>
            </div>
          </div>
        </div>
      </section>
    </template>
Enter fullscreen mode Exit fullscreen mode

The code above will style the page's content using Tailwind CSS, combining classes in each element. After that, import this component into the index.vue file in the pages folder:

pages/index.vue

    <template>
      <testimonials />
    </template>

    <script setup>
    useHead({
      title: "Read customers' feedback",
    });
    </script>
Enter fullscreen mode Exit fullscreen mode

The useHead is a Nuxt built-in component that helps to bind metadata to the head of the page, similar to the <title> in HTML.

Now, let’s ensure that this page appears in the browser by replacing the component NuxtWelcome to NuxtPage in the entry point of this project, app.vue:

app.vue

    <template>
      <NuxtPage />
    </template>
Enter fullscreen mode Exit fullscreen mode

Head over to your browser, and you should have something like this:

Testimonial display in the browser

Displaying all user’s statement

Let’s display all the feedback from customers or users of a product from the server which uses Appwrite databases API, list documents.

Let’s update the component, Testimonials.vue, with this code:

components/Testimonials.vue

    <template>
      <section class="mx-auto max-w-6xl w-4/5 mt-10">
        <div>
          <h1 class="text-3xl font-serif mb-3 md:text-5xl lg:text-6xl">
            Testimonials
          </h1>
          <p class="mb-10 text-slate-700">
            Learn from experts what they love about Appwrite Cloud
          </p>
        </div>
        <div class="grid gap-6 md:grid-cols-2 xl:grid-cols-3">
          <div
            class="border-2 rounded-lg p-4 flex flex-col justify-between transition-all ease-out"
            v-for="item in items"
            :key="item.$id">
            <p class="text-sm md:text-lg">
              {{ item.comment }}
            </p>
            <div class="flex items-center mt-7">
              <img
                :src="item.imgUrl"
                class="shrink-0 w-12 h-12 rounded-full border-slate-200 shadow mr-4 bg-black object-cover"
                loading="lazy"
                :alt="item.role" />
              <div>
                <p>
                  <span class="font-bold">{{ item.name }}</span>
                </p>
                <p class="text-xs md:text-sm font-light text-slate-700">
                  {{ item.role }}
                </p>
              </div>
            </div>
          </div>
        </div>
      </section>
    </template>

    <script setup>
    import { Client, Databases } from "appwrite";

    const runtimeConfig = useRuntimeConfig();

    const client = new Client();
    const databases = new Databases(client);

    client
      .setEndpoint(runtimeConfig.public.API_ENDPOINT)
      .setProject(runtimeConfig.public.PROJECT_ID);

    const getComment = databases.listDocuments(
      runtimeConfig.public.DATABASE_ID,
      runtimeConfig.public.COLLECTION_ID
    );

    const items = ref(null);

    onMounted(() => {
      getComment.then(
        function (response) {
          items.value = response.documents;
        },
        function (error) {
          console.log(error);
        }
      );
    });
    </script>
Enter fullscreen mode Exit fullscreen mode

The code above does this:

  • Import the Appwrite package and initialize the new instance using the web software development kit (SDK)
  • The useRuntimeConfig() function is for accessing the environment variables defined in the nuxt.config.ts file
  • The component mount using the onMounted lifecycle hook and the getComment function gets all the items from the collections in the server
  • Loop through the items using the v-for directive to get the individual testimonial listed in a grid

At this point, the app should look like this:

final demo

Conclusion

Having a testimonial on your website is something every brand should adopt because it makes you look good externally before anyone tries the product.

To extend this application, you can create a form on your website to allow users to submit feedback to the server.

Resources

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .