DEV Community

Cover image for How I built CupBook

Posted on • Updated on

How I built CupBook

I have decided to document my projects on online platforms. Mainly to write down my progress, but also for anyone curious who is starting out with Vue and Tailwind.

One of my favorite development projects is Cupbook. When one day my friend showed me her favorite design project, where she had revealed all her love for animals and books, I asked if I could build it as a developer. While her creativity and vision brought the design to life, I was able to focus on my passion which is web development.

The first step was to install Vue. Pretty easy and straightforward.
The process started with the creation of the navbar. The bookshelves and cats, brilliantly designed, create a sense of peace for book and cat lovers. The positioning of the SVG-s has been a bit challenging, because I wanted to make sure that the final product matched the designer's vision. But I learned how to edit SVG-s in my editor and I call that a small victory for me. The positioning of the cat was my favorite part because I thought I couldn't pull it off that well. But the result was awesome. A little cat crawling over the search input. How cute is that?

Search is functional. Just type something and the result will appear. Below is the code written with Vue 3:

<script setup>
import {computed, ref} from "vue";
import photo03 from '@/images/photo03.jpeg';

const searchQuery = ref('');
const books = [
        title: 'To kill a mockingbird',
        cover: photo03,
        author: 'Harper Lee',
        isBestseller: true,

const filteredBooks = computed(() => {
    if (! searchQuery.value) return [];

    return books.filter(function (book) {
        return book.title.toLowerCase().includes(searchQuery.value.toLowerCase()) ||

            <img alt="logo" src="@/images/mace.svg"/>
            <input v-model="searchQuery"

        <div v-if="filteredBooks.length" id="books">
            <div v-for="book in filteredBooks">
                <img alt="logo" :src="book.cover"/>
                <div>{{ book.title }}</div>
                <div>{{ }}</div>


Enter fullscreen mode Exit fullscreen mode

Listing books and events on the home page was a piece of cake, especially when you have the design ready. I used CSS grid and flex utilities to position the books in different screen sizes.

Then I continued with the creation of the About Page. Here too, I used mainly grid and flex.

The last section was the Contact Page. It was created with forms and here I made validation errors with Vue.

After I finished the Desktop version, I switched to the mobile version of the site. The basic change was the part of the navbar, from which I removed the book SVG-s and put a simple hamburger menu which, when clicked, opens the menu of the page which consists of Home, Books, Events, About us, Contact.

The last step is to Lazy Load the images so that the page is performant and fast.

<img loading="lazy" src="@/images/photo24.jpeg">
Enter fullscreen mode Exit fullscreen mode

It defers loading the image until it is needed.

Where did I encounter difficulty during the project?

The first difficulty was to make Search functional. The second was well-positioning the SVG-s.

What did I learn during the realization of the project?

  • I learned how to make a functional Search. I used the filter() function of arrays in Javascript. I also used Vue model binding to link the search input with the search variable.

  • I learned how to edit SVG-s in IDE (PhpStorm).

Here is a link to the CupBook Website and here is a link to the GitHub Repository

I hope you like it 😄.

Top comments (3)

genijaho profile image
Geni Jaho

Cool website :D

zacharyzac profile image

Cool site! I did find a little bug. If you navigate to /about and then try to navigate to another link from the nav it will not work correctly. Looks like it is looking for an id field to navigate within the page.
ex. #books in the URL

envitab profile image
Ekemini Samuel

Great work, thanks for sharing.

Also, designer friends are cool😎!