Introduction: Why Track Reading Progress?

Welcome back! In the last lessons, you learned how to create and manage resources like users and books in your API using NestJS. Now, let’s take the next step and add a feature that makes our application more useful: tracking reading progress.

Imagine you are using a reading tracker app. You want to know how far you’ve read in each book and maybe even pick up right where you left off. This is a common feature in many reading and learning apps. When you stop at page 52, you want the app to remember that exact page, so next time you resume reading — boom, you're right there. That’s exactly what our ReadingSession is doing in this lesson. You will learn how to build this feature by connecting users, books, and their reading sessions together.

By the end of this lesson, you will know how to update and track a user’s reading progress for a specific book using modules and DTOs in NestJS.

Quick Recap: Project Structure and Data

Before we dive in, let’s quickly remind ourselves of the project setup. You already have modules for users and books, and a simple mock database to store data. Here’s a summary of the main app module and the mock data structure:

This setup allows us to keep track of users, books, and reading sessions. The ReadingSession ties a user to a book and records their current page.

How the Reading Module Connects Everything

To track reading progress, we need a way to connect users and books through their reading sessions. This is where the ReadingModule comes in.

The ReadingModule imports both the UsersModule and the BooksModule. This allows it to use their services to check if a user or book exists before updating progress. Here’s how the module is set up:

By importing the other modules, the ReadingModule can access user and book data, making it possible to validate and update reading progress for any user and book combination.

This gives the ReadingService access to methods like usersService.findOne() and booksService.findOne(). Otherwise, NestJS will throw a runtime error because the provider (service) was not visible in the current module’s context.

Using DTOs to Update Progress

When updating reading progress, we want to make sure the data sent to our API is correct. This is where a DTO (Data Transfer Object) comes in. A DTO helps us define and validate the shape of the data.

Here’s the DTO used for updating reading progress:

This DTO ensures that:

  • userId and bookId must be valid UUIDs (not integers).
  • currentPage must be a positive integer.

For example, when a user wants to update their progress, they might send a request like this:

If the data doesn’t match the DTO rules (for example, if currentPage is negative), the request will be rejected. This helps keep your data clean and reliable.

Updating Reading Progress: Controller and Service in Action

When working with APIs, it’s important to know what endpoints exist, what kind of request they expect, and where the code for them should be written. In NestJS:

  • Controllers define the API routes (POST, PATCH, GET, etc.) and shape the response.
  • Services hold the actual logic (validation, updates, database operations).

In our case, tracking reading progress involves two main routes:

  • PATCH /reading/progress → update or create a reading session for a user and book
  • GET /reading/progress/:bookId → fetch all progress records for a specific book

Now, let’s see how the reading progress is actually updated. This happens in two main parts: the controller and the service.

1. The Controller Receives the Request

The controller listens for PATCH requests to the /reading/progress endpoint and passes the data to the service. Tracking progress is one part of the equation — but what if we want to retrieve progress data? Maybe we want to show how many users are currently reading Dune and how far each of them has progressed. That’s where the new GET route in our controller comes in handy.

Summary And Practice Preview

In this lesson, you learned how to track and update reading progress by connecting users and books through reading sessions. You saw how the ReadingModule brings everything together, how DTOs help validate incoming data, and how the controller and service work to update or create reading sessions.

Next, you’ll get to practice these concepts by updating and managing reading progress yourself. Try sending different requests, updating progress for different users and books, and seeing how the system responds. This hands-on practice will help you solidify your understanding and prepare you for building even more features in the future.

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