A SPA using React, Node, Express, and PostgreSQL that includes Google OAuth workflows.
The application: https://ce-expense-calculator.herokuapp.com/
This is a coding challenge application to demonstrate abilities to develope the front and backend. The stack is React, Redux, Node, Express, and PostgreSQL.
Features:
- Custom Redux interface using higher order reducers to simplify interaction within React code.
- Google API interface to provide OAuth authentication logic and retrieve basic user data.
- PostgreSQL for persistent data as well as express sessions for better user experience.
Please see sections Notes and Next Steps sections below for more commentary.
Running the application locally or deploying to Heroku requires pre-requisite steps here.
- Visit Google's developer console.
- Register the application with Google and create web application credentions.
- Visit "Credentials" tab
- Click "+ Create Credentials"
- Select "OAuth client ID" in the dropdown
- Select "Web Application"
- Input any name of your choosing
- Input "http://localhost:3000" under "Authorized JavaScript origins"
- Input "http://localhost:3000/google/redirect" under "Authorized redirect URIs"
- Copy and save your "Client ID" and "Client Secret" for later
To run this locally there are two prerequisites: Node and a local version of PostgreSQL. (This is assuming you already have Git.)
Once PostgreSQL is installed and running you need to create the database.
- Enter the shell with the desired username
$ psql "username"
- Inside the shell, create the
expense_calculator
database
CREATE DATABASE expense_calculator;
- Clone the repository.
- Navigate to the root level of the cloned directory and create a file named ".env" and input the required environment variables (anything starting with "YOUR")
MODE=development
PORT=3000
SESSION_SECRET=YOUR SESSION SECRET
PGUSER=YOUR PG USER
PGHOST=localhost
PGPASSWORD=YOUR PG PASSWORD
PGDATABASE=expense_calculator
PGPORT=YOUR PG PORT
GOOGLE_CLIENT_ID=YOUR GOOGLE CLIENT ID
GOOGLE_SECRET=YOUR GOOGLE SECRET
GOOGLE_REDIRECT=YOUR GOOGLE REDIRECT
- Run npm install
$ npm install
- Run npm start
$ npm start
- Navigate to localhost:3000 or your chosen port.
- Sign up for free with Heroku.
- Install Heroku locally by following these directions here.
- Create the Heroku app and register it by running:
heroku create
-
Navigate to the Heroku console and find the application. Retrieve the public URI that you are able to access the application from under the setting tab.
-
Register the Heroku domain with Google.
- Navigate to "Credentials"
- Select the application
- Click "+ Add URI" under "Authorized JavaScript origins"
- Copy and paste Heroku URI
- Click "+ Add URI" under "Authorized redirect URIs"
- Copy, paste, and add "/google/redirect" to the end if the URI
-
Set up Heroku environment variables. NOTE: Heroku will automatically pass a database connection url to the application.
MODE=development
SESSION_SECRET=YOUR SESSION SECRET
GOOGLE_CLIENT_ID=YOUR GOOGLE CLIENT ID
GOOGLE_SECRET=YOUR GOOGLE SECRET
GOOGLE_REDIRECT=YOUR GOOGLE REDIRECT
-
Spin up a free Heroku PostgreSQL instance by navigating to the resource tab and searching PostgreSQL. Select "Heroku PostgreSQL"
-
Deploy the application
$ git push heroku master
- As changes are made, any updates can be deployed by pushing to heroku master (above command)
While building this application I experimented with implementing a Redux interface I have used before. It makes things quite convenient when adding components and managing many different branches of state. The implementation was new to me and could possibly be refined to be clearer or more performant. Setting this up took the most time out of all other features but made state managment and Redux very easy to use.
I also tried a new interface for the routes to make RESTful practices more straight forward. In the end I am undecided on the approach as in its current state it feels light weight but as the application grows it would likely become more combersome and resource heavy.
Because I experimented a little bit with these interfaces, the styling and css approach to the application is left wanting.
There is some key functionality missing due to time constraints. Here they are in order of priority to resolve.
- The user needs to be able to log out.
- An interface for API calls from the frontend needs to be more robust and standard. For the small amount we have, there is already enough variance to warrant some abstraction. This could include the introduction of Saga or Thunk as Redux middleware or just a small library to standardize the calls.
- There is currently no approach to styling. Everything is dumped into main.css file. I would explore having styling sheets for each "page" of the application or implement the styled-components library.
- Although this is a single page application we already have a few different "pages". It would be ideal to implement React Router so we can have some persistence on refresh and the ability to use browser navigation. It would also cleanup the main App component.