Designing a User-Friendly Course Catalog With Pink Design and Nuxt
Tags: javascript, nuxt, beginners, webdev
Published: 2023-05-08 11:42:17

Creating a course catalogue that is both visually appealing and easy to use can be a challenge. However, with the combination of [Pink Design](https://pink.appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) and Nuxt.js, we can design an excellent and intuitive catalogue for users. 

In this article, we'll learn how to build a course catalogue that allows users to search, filter through the available courses, and view course descriptions & prerequisites.


## Sandbox

We completed this project in a [Code Sandbox](https://codesandbox.io/p/sandbox/jolly-greider-jkxoif?file=%2Fpages%2Findex.vue&selection=%5B%7B%22endColumn%22%3A43%2C%22endLineNumber%22%3A8%2C%22startColumn%22%3A43%2C%22startLineNumber%22%3A8%7D%5D); fork and run it to get started quickly.

<CodeSandbox id="jolly-greider-jkxoif" title="Designing a User-Friendly Course Catalog With Pink Design and Nuxt" />

## GitHub repository
{% embed https://github.com/Olanetsoft/Course-Catalog-With-Pink-Design-Nuxt.js %}


## Getting Started with Nuxt.js

[Nuxt.js](https://nuxtjs.org/) is the bedrock of our Vue.js project, providing structure and flexibility while allowing us to scale confidently.

It is extensible, offering a robust module ecosystem and hooks engine. Integrating our REST or GraphQL endpoints, favourite CMS, CSS frameworks, and other third-party applications is seamless.


## Project Setup and Installation

To create a new project, we will use the command below to scaffold a new project:

```bash
    npx create-nuxt-app <project-name>
```

A series of prompts will appear as a result of the command. Here are the defaults we recommend:


![Designing a User-Friendly Course Catalog With Pink Design and Nuxt.js](https://paper-attachments.dropboxusercontent.com/s_7AC26CC02ABBD4ECF87A28FA94F444D13C603C1D71496E75B9FDC7D0E5DF2094_1679178738732_Screenshot+2023-03-18+at+23.32.00.png)


The command above creates a new Nuxt.js project.

Next, we navigate to the project directory and start the development server using the command below.

```bash
    cd <project name> && yarn dev
```

Nuxt.js will start a hot-reloading development environment accessible by default at http://localhost:3000.

![Nuxt.js default page](https://paper-attachments.dropboxusercontent.com/s_7AC26CC02ABBD4ECF87A28FA94F444D13C603C1D71496E75B9FDC7D0E5DF2094_1679178889890_Screenshot+2023-03-18+at+23.34.36.png)

## Appwrite Pink Design Setup

To set up an [Appwrite](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) pink design in this project, we will configure our project using the [Appwrite pink design CDN](https://pink.appwrite.io/getting-started#cdn). Navigate to the `nuxt.config.js` in the root directory and add the following configuration.

```js
    export default {
      // Global page headers: https://go.nuxtjs.dev/config-head
      head: {
         //...
        link: [
          { rel: "icon", type: "image/x-icon", href: "/favicon.ico" },
          {
            rel: "stylesheet",
            href: "https://unpkg.com/@appwrite.io/pink",
          },
          {
            rel: "stylesheet",
            href: "https://unpkg.com/@appwrite.io/pink-icons",
          },
        ],
      },
    
     //...
    };
```

## Creating a Sample Course Catalogue JSON

In this step, we will create a sample course catalogue which we will utilize in our application as a database for our courses. In the project's root, create a new JSON file called `courses.json` and add the following course sample.

```js
    [
      {
        "id": 1,
        "title": "Introduction to Web Development",
        "description": "Learn the basics of web development with HTML, CSS, and JavaScript.",
        "level": "Beginner",
        "prerequisites": [],
        "category": 1
      },
      {
        "id": 2,
        "title": "Advanced Web Development",
        "description": "Build complex web applications with React, Node.js, and MongoDB.",
        "level": "Intermediate",
        "prerequisites": ["Introduction to Web Development"],
        "category": 1
      },
      {
        "id": 3,
        "title": "Introduction to Mobile Development",
        "description": "Learn the basics of mobile development with React Native and Expo.",
        "level": "Beginner",
        "prerequisites": ["Introduction to Web Development"],
        "category": 2
      },
      {
        "id": 4,
        "title": "Data Analysis with Python",
        "description": "Learn how to analyze and visualize data using Python and Pandas.",
        "level": "Intermediate",
        "prerequisites": ["Introduction to Web Development"],
        "category": 3
      },
      {
        "id": 5,
        "title": "User Interface Design Fundamentals",
        "description": "Learn the basics of user interface design with Sketch.",
        "level": "Beginner",
        "prerequisites": [],
        "category": 4
      },
      {
        "id": 6,
        "title": "Cloud Computing with AWS",
        "description": "Learn how to deploy and scale web applications on Amazon Web Services.",
        "level": "Intermediate",
        "prerequisites": ["Introduction to Web Development"],
        "category": 5
      }
    ]
```

In the sample data above, we have the identifier for each record `id`, a `title`, `category`, `description`, `level`, `prerequisites`, and `category`.


## Designing the layout for the Course Catalogue

Let's design an aesthetically appealing design for the course catalogue in this section by updating the `pages/index.vue` with the following code snippet.

```js
    <template>
      <div>
        <div class="container">
          <div class="sidebar">
            <!-- Sidebar content goes here -->
           </div>
          <div class="content">
             <!-- Search and Course list goes here -->
          </div>
        </div>
        <div class="course-modal" v-if="selectedCourse">
          <div class="modal-content">
            <!-- Modal goes here -->
          </div>
        </div>
      </div>
    </template>
```

Let's add CSS by creating a new file called `styles.css` in the root directory and updating it with the following CSS snippet.


{% embed https://gist.github.com/Olanetsoft/0080a3694d6e1c22bc74e4688cf83334 %}

Import the style by updating the `pages/index.vue` with the following code snippet.

```js
    <template>
      <!--  -->
    </template>
    
    <style>
    @import '@/styles.css';
    </style>
```

## Developing the Functionality to Retrieve All Courses

In the previous step, we successfully designed the application layout; now, we will implement the functionality to retrieve all courses from the JSON file we created earlier.

Inside the `pages/index.vue` file, update it with the following code snippet.

```js
    <template>
      <div>
        <div class="container">
          <div class="sidebar">
          
          </div>
          <div class="content">
            <h1 class="course-catalogue-title">
              Course Catalog With Pink Design and Nuxt.js
            </h1>
             <!-- Search goes here -->
            <div class="courses">
              <div
                class="course-card"
                v-for="course in filteredCourses"
                :key="course.id"
              >
                <div class="card" @click="openCourseModal(course)">
                  <div class="card-content">
                    <h3 class="title">{{ course.title }}</h3>
                    <div class="description">{{ course.description }}</div>
                    <div class="details">
                      <div class="level">{{ course.level }}</div>
                    </div>
                  </div>
                
                </div>
              </div>
            </div>
          </div>
        </div>
        </div>
        <div class="course-modal" v-if="selectedCourse">
          <div class="modal-content">
           <!-- Modal goes here -->
          </div>
        </div>
      </div>
    </template>
    <!--  -->
    
    <!-- Importing data from a JSON file named courses.json -->
    <script>
    import coursesData from '../courses.json'
    
    export default {
      // Defining the data property of the component
      data() {
        // Returning an object with a key of 'courses' and its value set to the imported coursesData
        return {
          courses: coursesData,
        }
      },
    }
    </script>
```

In the code snippet above, 

- We import data from a JSON file named `courses.json`. 
- The `data()` function returns an object with the key of `courses` and its value set to the imported `coursesData` variable.

We should have something similar to what is shown below.

![Developing the functionality to retrieve all courses](https://paper-attachments.dropboxusercontent.com/s_7AC26CC02ABBD4ECF87A28FA94F444D13C603C1D71496E75B9FDC7D0E5DF2094_1680098408918_Screenshot+2023-03-29+at+14.59.42.png)



## Adding a Search and Filter by Category feature to the Course Catalog

In the sources, we have different categories. Let's implement the course filtering search functionality to filter based on the course category by updating the `pages/index.vue` file with the following code snippet.


{% embed https://gist.github.com/Olanetsoft/a54e5e5ef91ab259683c04b594496927 %}

In the code snippet above we:

- Utilized the imported JSON file with course data
- Defined a Vue.js component that uses the imported course data as its initial state
- Created component's data properties, which include search `searchQuery`, `categories`, and the currently selected category
- Defined a `computed` property that filters courses based on the search query and currently selected category
- Returned the filtered courses in the component's computed property

We are almost there! We can retrieve all courses and search and filter courses but we can't view individual courses yet, let's implement that in the following step.


## Implementing the Course View Functionality

To implement course view functionality, we will add a `modal` to view the course content whenever a user clicks on an individual course. Let's update the `pages/index.vue` file with the following code snippet.

```js
    <template>
      <div>
        <div class="container">
          <!-- //... -->
        </div>
        <div class="course-modal" v-if="selectedCourse">
          <div class="modal-content">
            <span class="close-modal" @click="closeCourseModal">&times;</span>
            <h2 class="modal-title">{{ selectedCourse.title }}</h2>
            <div class="modal-description">{{ selectedCourse.description }}</div>
            <div class="details">
              <div class="modal-level">{{ selectedCourse.level }}</div>
            </div>
            <div class="modal-prerequisites">
              <h3>Prerequisites</h3>
              <ul v-if="selectedCourse.prerequisites.length">
                <li
                  v-for="prerequisite in selectedCourse.prerequisites"
                  :key="prerequisite"
                >
                  {{ prerequisite }}
                </li>
              </ul>
              <p v-else>None</p>
            </div>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    // Import courses data from JSON file
    import coursesData from "../courses.json";
    export default {
      data() {
        return {
          //...
          selectedCourse: null,
        };
      },
      methods: {
        //...
        openCourseModal(course) {
          this.selectedCourse = course;
        },
        closeCourseModal() {
          this.selectedCourse = null;
        },
      },
      computed: {
        //...
      },
    };
    </script>
    
    //...
```

In the code snippet above,

- The course list container dynamically generates a course element for each course in the filtered course list using `v-for`
- Each course element has an `on-click` event that triggers the `@click="openCourseModal(course)``"` method
- The `selectedCourse` variable is set to the `course` object to display the modal using the `openCourseModal` method
- The `selectedCourse` becomes `null` when the close modal icon is clicked, which triggers the `closeCourseModal` method

Testing the application, we should have something similar to what is shown below.


![Testing the application](https://paper-attachments.dropboxusercontent.com/s_7AC26CC02ABBD4ECF87A28FA94F444D13C603C1D71496E75B9FDC7D0E5DF2094_1680099876413_Course-Catalog-With-Pink-Design-and-Nuxt.gif)


## Conclusion

This post demonstrated how to design a user-friendly course catalogue with pink design and Nuxt.js. Additionally, you learned how to search, filter through the available courses, and view course descriptions and prerequisites.


## Resources
- [Official Nuxt Documentation](https://nuxtjs.org/)
- [The Intuitive Web Framework](https://nuxt.com/)
- [Appwrite's Pink design system](https://github.com/appwrite/pink/?utm_source=hackmamba&utm_medium=hackmamba-blog)
- [Appwrite Documentation](https://appwrite.io/docs/getting-started-for-web?utm_source=hackmamba&utm_medium=hackmamba-blog)
- [Cover Image - Nick Morrison](https://unsplash.com/photos/FHnnjk1Yj7Y)