Myreads, a digital bookshelf using Golang, React with Typescript, HarperDB, JWT based auth, and Docker
A complete web-based application using the RESTful API architecture consisting of frontend, backend, and database.
Hello everyone, to participate in HarperDB+Hashnode Hackathon I'm submitting this complete web-based application called Myreads which lets us maintain our offline bookshelf digitally. This is a full-stack application having backend, frontend, database service deployed using docker-compose.
Little bit about me
My name is Pratik. I'm a system-level software developer and tester who works mainly with Linux and containers. I'm a Linux enthusiast and love open-source technologies. I don't have any professional experience in developing web-based applications. This project can be considered my first web-based project.
Inspiration behind this project
For a long time, I was thinking to get started in the web development field as I already work on system-level programming with containers, adding web development to my portfolio could make it a full-stack developer. I also like to read books. Everyone who loves reading books keeps count of their books or maintains the status of books present on their shelf. So I thought why not build something in this area and I built the Myreads. Inspired from Goodreads
What is Myreads
Myreads is a simple but utilitarian web-based application that helps you to maintain your book status in three categories:
1. Wish List: Books which you want to read.
2. Reading List: Books you're currently reading.
3. Finished List: Books you finished reading.
How I build it?
Tech stack
Main tech stack:
- HarperDB as database service
- Golang for backend server
- React with Typescript for UI
- Docker compose to deploy the application
Underlined tech stack:
- git, git-submodules
- go-fiber
- harperdb-sdk-go
- containers
- react-bootstrap, react-query, etc...
- HarperDB docker instance
Challenges
As I'm new neophyte in web development, I faced lots of challenges.
- Learning frontend technologies
I come from more of a back-end technology background, so learning front-end and creating a project using it in a small period of time was a bit challenging. But after many sleepless nights and countless hours of going through tutorials, I got hang of it.
- HarperDB's support for Golang
When I started researching HarperDB, I found almost no tutorial about Golang+HarperDB
. This was one of my motivations to write backend using Golang so I could create some content of Golag+HarperDB
. I found one small library harperdb-sdk-go
, which supported the basic CRUD functionality but does not provide all the functionalities needed to write the webserver which deals with the database. But I still managed somehow and wrote my own wrapper whenever it was needed.
- Model migration
Almost all the MVC based library supports the migrating model to the database table which was not yet supported by the harperdb-sdk-go. So I had to find another way to initialize the database using curl commands in a shell script.
Myreads System Design
System design is simple and elegant.
We've three services running: frontend, backend, and database. Frontend makes the API call to the backend then backend verifies the authenticity of the API call and takes the required action accordingly.
Myreads backend service
Myreads backend is written in Golang
using Fiber
and harperdb-sdk-go
. Backend exposes a list of API which are then consumed by the frontend.
1. /api/register: For user registration.
2. /api/login: For use login.
3. /api/user: To fetch the logged-in user information.
4. /api/logout: To log out the user.
5. /api/books/add: To add book the database.
6. /api/books/all: To fetch all the books.
7. /api/books/reading: To fetch books from the reading list.
8. /api/books/wishlist: To fetch books from wishlist.
9. /api/books/finished: To fetch books from the finished list.
10. /api/books/deletebook: To delete book
11. /api/books/updatestatus: To update the status of the books such as reading->finished.
12. /api/static: To fetch the static content such as the image.
This is a standalone service so it can be spun up using docker and could be tested using POSTMAN or CURL.
Myreads frontend service
Myreads frontend is written using React with Typescript
.
It consumes the APIs exposed by the backend.
This service is also standalone it can be used with any other backend service which will expose the same set of APIs as the Myreads backend service.
Myreads database service
Myreads backend service is hardcoded to use the HarperDB. The schema has two tables users and books. Users table is to store the user-related information such as name, email, and password. Books table is to store books related data such as name, author, description, imageLoc, userid of the book's owner.
Application walkthrough
- Every new user will have to register themself at the registration page.
- After successful registration user will be redirected to the login page.
- After login, the user will be redirected to the home page where he can see all the books from his bookshelf.
The new user will see the warning in the Red saying empty bookshelf
.
- User will need to fill a form to add books to the bookshelf.
- Then a user can visit the home page or the category page to see their book.
Below is a screenshot of the
reading
category of the book.
Each book on the bookshelf has a
green colored more
button. On clicking it will prompt with the book description and two operation choices to perform on the book.Update the status of the book(wishlist, reading, finished)
Remove the book from the bookshelf.
Deploying the Myreads
This is a multiple service-based application so it makes sense to use containerization to deploy it.
I've containerized frontend and backend services whereas the database service is handle by the HarperDB cloud instance.
Follow the following steps to deploy the application.
Get the powerful free HarperDB instance by visiting this link
Create New HarperDB Cloud Instance (one instance is free) and remember the
username
andpassword
of the instance.Once the instance is up and running click on the instance card and go to the
config
section.- In the config section, you'll see the
Instance URL
andInstance API Auth Header (this user)
copy them. They're needed to interact with DB.
- In the config section, you'll see the
Make sure you've docker and docker-compose installed and running successfully.
Clone the project repository from Github. This repo contains sub-modules of frontend and backend services so we'll need to clone it with
--recurse-submodules
flag. Project source code: https://github.com/pratikjagrut/myreads-harperdbgit clone --recurse-submodules https://github.com/pratikjagrut/myreads-harperdb.git cd myreads-harperdb
Update the
.env
file with your harperDB database credentials. In the root of themyreads-harperdb
directory, it has a.env
file that contains the database and API connection-related environment variables.DB_HOST= BASIC_AUTH_TOKEN= HDB_ADMIN= PASSWORD= PORT=8000 API_URL=http://localhost:8000
DB_HOST, BASIC_AUTH_TOKEN, HDB_ADMIN and PASSWORD
we've already obtained this information in the 2nd and 3rd steps.DB_HOST=Instance URL from 3rd step BASIC_AUTH_TOKEN=Instance API Auth Header (this user) from 3rd step HDB_ADMIN=username from 2nd step PASSWORD=password from 2nd step
If all the above steps were successfully followed then hit the docker-compose
docker-compose up
Once all the services are running perfectly fine you can visit the http://locahost:3000/ and see the application is up and running.
NOTE: If something goes wrong and you wish to check the logs of individual services run the following command.
docker-compose logs server # To check the backed service logs
docker-compose logs web-ui # To check the frontend service logs