Back

Bookmoeum

August 2024
Bookmoeum
MyRole
I did everything.
Team
Euichan Lee
Timeline
3 Weeks, starts August 2024
Tech Keywords
Next.js, TypeScript, Figma, Tailwindcss, Redux, React-query, OPEN APIs, Firebase, middleware, useInfinityScroll, Framer, Phase
Overview
Book Collection is a book search service where users can find where to read books in one place, eliminating the need to search multiple sites.
I implemented a design system including typography, colors, spacing, and UI components using Figma before proceeding with the design work. The design was created with responsiveness in mind.
It's a web page based on Next.js, with TypeScript used for type specifications. For book information, I used the Naver API for searches to provide as much book information as possible, and the Aladin API for more detailed information on the book detail page.
Login ans DB was implemented using Firebase, and book information checks and displays book availability from Kyobo Book Centre, Yes24, Aladin, Ridibooks, and the user's selected library. I used APIs for Aladin and libraries, and web crawling for the other bookstores.
HIGHLIGHTS
Provides information on where to read books in one place using OPEN APIs from bookstores and libraries, as well as web crawling.
Project highlight
Project highlight
Project highlight
DESIGN SYSTEM
How should we create the design?
Building a Design System
We introduced a design system to ensure consistent design application and to prevent confusion or mismatched specifications during development.
In the Foundation, we set and stored colors, typography, and specifications, which were then used in UI components.
From the design stage, we considered componentization, designed components divided by UI, and then used them in the final design.
Foundation Design
UI Component Design
Design
OPEN API
Which APIs should we use and how?
Bookstore API
For domestic book information, there are bookstore APIs from Naver and Aladin, each with its own characteristics.
Therefore, we used Naver for searches as it provides more book information, and Aladin API for the book detail pages as it offers more detailed information for each book.
Library API
For libraries, we used public APIs and stored a list of libraries separately. When a desired library is selected, we check the availability of books using each library's ID.
React-query and API folder
Values fetched from APIs are cached using staletime to avoid unnecessary repeated API calls.
Instead of fetching APIs directly on the client-side, we divided each API into folders and set up a uniform format for calling APIs in server components.
  const fetchSearchResults = async ({
    pageParam = 1,
  }: {
    pageParam?: number;
  }) => {
    const response = await fetch(
      `/api/search/naver?query=${encodeURIComponent(query)}&start=${pageParam}`
    );
    if (!response.ok) {
      throw new Error("API 요청 실패");
    }
    return response.json() as Promise<SearchResponse>;
  };
Search results use the Naver API.
SearchPage.tsx
InfiniteQuery.tsx
Bookfind.tsx
STATE
How can we pass information when navigating between pages?
API Recall Problem
The book search page and book detail page have different routes, requiring the page to be reloaded. However, this causes a delay problem as the API needs to be called again each time.
To solve this, we thought of passing the already fetched search results to the book detail page, allowing values to be displayed immediately.
Using Redux
While it was possible to pass values from the search page to the detail page using query parameters, this would make the URL messy. Instead, we chose to store the values in Redux and retrieve them from there.
export default function BookList({ searchResults }: BookListProps) {
  const dispatch = useDispatch();

  return (
   //...
      onClick={() => dispatch(setSelectedBook(result))}
	//...
}
When listing book information, clicking on each book manages the values through Redux.
BookDetail.tsx
bookDeatil.tsx
LOGIN
Methods to check logged-in users based on user type
Firebase
For login, we implemented methods using Firebase, including email and password login, and Google login.
Middleware
Since users have their own database and need to check their library, we need to verify whether they are logged in or not.
This verification is done through middleware, which intercepts the signal, checks if it's a designated link, and shows the appropriate page accordingly.
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  const authToken = request.cookies.get('authToken')?.value;

  if (request.nextUrl.pathname.startsWith('/mylibrary')) {
    if (!authToken) {
      return NextResponse.redirect(new URL('/login', request.url));
    }
  } else if (request.nextUrl.pathname === '/login' && authToken) {
    return NextResponse.redirect(new URL('/', request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ['/mylibrary/:path*', '/login'],
};
The middleware is located at the page root and intercepts requests to check specified paths.
If it determines that login is required for a path, it redirects to the login page.
BookDetail.tsx
DB
How to manage information that needs to be stored?
Firestore
Initially, we only stored the ISBN of books saved by each user in the user data. However, this required API calls even for the book list, so we decided to include the already fetched API data when saving on the page.
  const handleButtonClick = async () => {
	  //...
	  
    const bookRef = doc(db, `users/${user.uid}/books/${bookData.isbn}`);

    try {
      if (isBookAdd) {
        await deleteDoc(bookRef);
      } else {
        await setDoc(bookRef, {
          title: bookData.processedTitle,
          author: bookData.processedAuthor,
          image: bookData.image,
          isbn: bookData.isbn,
          publisher: bookData.publisher,
          description: bookData.description,
          pubdate: bookData.pubdate,
          timestamp: new Date(),
        });
      }
      setIsBookAdd(!isBookAdd);
    } catch (error) {
      console.error("Error updating book status:", error);
    }
  };
Since books selected by users need to be managed in order, we also included the time of saving.
BookDetail.tsx
ANIMATION
Considering more user-friendly UI/UX.
Phase
To make it more interesting when fetching values from the API, instead of just showing 'Loading', we created characters in Figma, then used an animation tool called Phase to create an mp4, which is displayed during loading.
CSS && Framer
The book list display on the homepage and the bookstore list display were implemented using CSS and Framer respectively.
RESPONSIVE DESIGN
Which devices do users use more frequently?
Responsive Design
While I personally use a laptop more often, a survey of book-loving people around me showed that the frequency of mobile phone use is higher. We considered responsive design during both the design and development phases.
We considered user experience for each device through design changes such as the footer disappearing or the header dropping down depending on the screen size.
responsive mobile
responsive mobile book detail