Skip to content

Latest commit

 

History

History
129 lines (105 loc) · 4.56 KB

README.md

File metadata and controls

129 lines (105 loc) · 4.56 KB

GoodReads Reviews

Book Reviews Web App

"Create an account, log in, search for, and leave reviews for your favorite books!"

Live | GitHub

Project Brief:

Harvard CS50W Capstone Project

Role / Skills:

Lead Developer

Technologies Used:

    PERN Stack:
  • PostgreSQL
  • Express.js
  • React
  • Node.js
  • JavaScript
  • Local Storage, Session Storage
  • GoodReads API
  • Deployed to Heroku
  • Redux
  • React Router
  • React Bootstrap
  • SCSS
  • Axios
  • Converted from originally Python, Flask, Jinja2 project
  • CRUD capabilities - users can GET, POST, PUT, DELETE their own comment reviews of individual books

Summary:

  • Users can log in to search for books, leave reviews, edit and delete their reviews, and see average reviews and review counts per book from Goodreads API data.
  • Express.js server-side fetch of Goodreads API endpoints as well as database queries using PostgreSQL for books, user reviews, and user login information.
  • Books imported from a CSV file of 5000 books
  • Environment variables stored via Heroku

Challenges Faced:

Pre-rendering the "Details" HTML page first to display external fetched data

After deploying the production version to Heroku, when refreshing or GET requesting the 'details' page of any book (/details/9958 route for example), I was stuck with a plain, white screen with only a JSON object of the API response data for that book. My Express.js routes were catching all of the GET requests before React could load the index.html page, therefore the application had no webpage to display the API data onto.

I wanted my HTML to be pre-rendered in order for the fetched GoodReads API and database data to successfully "hydrate" and display on the page.

To remedy this, I found a work-around on my server-side using the Express.js res.sendFile(path, options) method to pre-render the template index.html file as the path argument, along with the API response data object in the options argument.

  
  // detailsRouter.js
    let options = {
      headers: {
        'result': (results from GoodReads API fetch),
        'comment_list': (comments from the database fetch),
        'bookinfo': (book info from the database fetch)
      }
    }

  res.sendFile(path.join(__dirname, "../client/build/index.html"), options);
  
  

Deploying to Heroku with the Heroku Postgres database add-on

Heroku Postgres

Before finally deploying the application on Heroku for production, I installed the Heroku Postgres add-on to host the PostgreSQL database for my users, books, and reviews. I made sure to include the DATABASE_URL environment variable provided by Heroku to link to the app's process.env and used conditional boolean logic to select either "deployment" or "production" mode configuration.

This ensured the application was using either the "development mode" local database, or the "production mode" heroku hosted database.

  
    {`// db.js
      const devConfig = {
        user: process.env.PG_USER,
        host: process.env.PG_HOST,
        database: process.env.PG_DATABASE,
        password: process.env.PG_PASSWORD,
        port: process.env.PG_PORT
      }

      const prodConfig = {
       connectionString: process.env.DATABASE_URL // <-- heroku add-on Postgres database URL
      }

      const pool = new Pool(process.env.NODE_ENV === "production" ? prodConfig : devConfig)
    `}