Introduction: Why Catalogs Matter

Welcome to the first lesson of our course on building a Reading Tracker API with NestJS. In this lesson, we will focus on the foundation of any reading tracker: the book catalog. A well-organized catalog makes it easy for users to find, browse, and manage books. By the end of this lesson, you will know how to store book information, search for books, sort results, and paginate through large lists. These are essential features for any modern API that deals with collections of data.

In this unit we lay the catalog groundwork your API will build on later: richer book metadata, a validated CreateBookDto, a FindAllBooksDto for query parameters, and a controller/service pipeline that supports public search, sorting, and pagination on GET /books. Here we will implement these pieces end-to-end so lists are UI-ready and scalable.

Book Metadata: Storing Book Information

Book metadata is the information we store about each book. This includes details like the title, author, total number of pages, and important dates. Here’s what each field means:

FieldDescriptionExample Value
idUnique identifier for the book39dd8d1a-94b4-401d-8236-b16c5e9f235a
titleThe name of the book"The Hobbit"
authorThe person who wrote the book"J.R.R. Tolkien"
totalPagesTotal number of pages in the book310
publishDateWhen the book was published (optional)"1937-09-21"
uploadedAtWhen the book was added to our system"2024-06-01T12:00:00Z"

Here’s how a book is represented in our code:

By storing this metadata, we make it possible to search, sort, and display books in a meaningful way.

Enrich the Book model and seed data

Here we will update the Book interface and seed array so each book carries analytics-friendly fields used throughout the course.

What changed

  • Added totalPages, optional publishDate, and uploadedAt to Book.
  • Seeded two books with those fields populated in ISO formats.

Why

  • These fields power sorting and (later) progress/analytics.
  • uploadedAt makes new items visible in lists without extra queries.

This change standardizes how books are represented and ensures any list, sort, or later aggregation has the minimal metadata it needs. Using ISO strings keeps comparisons deterministic and display-ready. Seeding a couple of books guarantees your /books endpoint always has something to return. This foundation will be used by your search/sort logic in the next steps.

Validate creation input with CreateBookDto

Here we will update the DTO used by the admin-only POST so creation is validated at the edge.

What changed

  • Required title, author, and totalPages (≥ 1).
  • Optional, strictly formatted publishDate (ISO 8601). Why
  • Prevents invalid records from entering the catalog.
  • Keeps later list/sort behavior predictable.

With this DTO, invalid payloads are rejected early with helpful errors. That reduces downstream null/edge handling and makes client behavior clearer. The constraints mirror the fields you just added to the model, keeping the contract between controller and service simple.

Add FindAllBooksDto for search, sorting, and pagination

Here we introduce a single, typed DTO for all list query params on GET /books.

This DTO decouples transport concerns from your service logic and guarantees sanitized inputs reach the core. It also ensures pagination has sensible bounds, protecting performance and response sizes. The same pattern will support more advanced sorts later without changing controller signatures.

Searching the Catalog

A catalog is only useful if users can find what they are looking for. In our API, we allow users to search for books by title or author using the q query parameter. This search is case-insensitive and matches any part of the title or author’s name.

We'll need the service searchsortpaginate functionality. Here’s how the search works in the service:

Sorting and Pagination

When a catalog grows, it’s important to help users organize and navigate the results. Our API supports sorting and pagination through query parameters.

Sorting:
Users can sort books by title, author, publishDate, or uploadedAt. They can also choose the order: ascending (asc) or descending (desc).

Here’s how sorting is handled:

Pagination:
To avoid overwhelming users with too many results at once, we use pagination. The page and pageSize parameters control which results are returned.

Example:
Suppose there are 30 books in the catalog. If a user requests /books?page=2&pageSize=10&sortBy=title&order=asc, the API will return books 11 – 20, sorted by title in ascending order.

Sample Output:

This approach keeps the catalog easy to browse, even as it grows.

Test it with curl (Unit-1 scope only)

For tests, use the seed credentials admin/admin. Only the catalog features are tested here: public list/search/sort/pagination and the admin-only create.

1. Public: list existing books

2. Admin login and create a couple of books

3. Public search + sorting + pagination

4. Negative tests (expect errors)

What to look for

  • The public GET returns { items, page, pageSize, total } and respects your query params.
  • Admin-created books appear in subsequent GETs and can be sorted by publishDate/.
Summary & What’s Next

In this lesson, you learned how to build the foundation of a book catalog in a reading tracker API. We covered how to store book metadata, search for books by title or author, sort results, and paginate through large lists. These features make your API much more user-friendly and efficient. You now have a robust, public catalog endpoint with validated creation and UI-ready listing behavior. This structure will carry forward as we add more fields and sorts. In the next unit, we’ll build on this by introducing per-user shelf/progress features and advanced sorting that reuses the same query DTO.

Now, you are ready to practice these concepts with hands-on exercises. Try searching, sorting, and paginating the book catalog yourself to reinforce what you’ve learned.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal