A Full-Stack Application
Tags: react, rails, showdev, redux
Published: 2021-09-16 18:33:16

{% github aj-rom/hike-it-up-v2 no-readme %}

I recently have completed a *full-stack* (backend and frontend) application, [hike-it-up](https://aj-rom.github.io/hike-it-up-v2/), and wanted to share how I went about creating this application and hosting it for **completely free**. 

## Some Background
I am finishing my time at [The Flatiron School](https://flatironschool.com/) and wanted to showcase my new learnings by re-creating a very simple [Sinatra](http://sinatrarb.com/) application that I made earlier this year. Now that I had all this great knowledge of [React](https://reactjs.org/) I could combine it with my knowledge of [Ruby on Rails](https://rubyonrails.org/) to create a full-stack application.

## Getting Things Started
Right off the bat, with experience from previous projects, I wanted my backend and frontend within the same GitHub repository. Both for ease of local deployment and because at the end we want to have **3** branches. One for our backend, one for our frontend, and one to house everything.

I initially started and used the `create-react-app` toolchain to generate my GitHub repository and frontend services. 

After moving into the newly generated folder, I created a new rails API application named `backend`. 

Now I had a folder for my backend, a `public` folder for my entry point, and a `src` folder for React related files. 

### Choosing Frameworks
I went with [Pico.CSS](https://picocss.com/) for the framework, as it is a very lightweight CSS pack and has useful 'classless' styling properties.

> [Read more on Pico.CSS](https://picocss.com/docs/)

I also wanted to have application state as well as client side routing. To achieve this I had to install some [npm](https://www.npmjs.com/) packages.
For application state I used [redux](https://github.com/reduxjs/redux) with [redux-thunk](https://github.com/reduxjs/redux-thunk) middleware. 

For client side routing, I decided to go with [react-router](https://reactrouter.com/). This allowed me to mimick route browsing of the backend on the frontend. For example, going to `/trails/1`, should bring up the first trail. React Router passes the declarative **id** of the route, in this case `/trails/:id`, to the props of the route. 

This allows us to make backend server calls **ONLY** when necessary, and doesn't break if someone were to link to it like [this](https://aj-rom.github.io/hike-it-up-v2/#/trails/1).

## Building Out the Backend
I created resources for `trails`, `users`, and a model for `addresses`. Full CRUD operations should be able to be performed on trails, but only limited functionality should be able to be used for users. 

To ensure malformed or malicious attempts would not be able to work, I built out a simple token authentication system that would verify the user for ever session. If they have the incorrect token, requests to the backend server will not be implemented.

Also, because I was separating where the frontend and backend servers are hosted, I needed to configure [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). This would ensure requests where only valid if they came from my frontend's location.

After creating all pertinent relations and migrations I had my backend system up and running.

## Frontend Challenges
When I was building out the frontend there were a couple of issues that I ran into, mostly because I was hosting this on [gh-pages](https://www.npmjs.com/package/gh-pages).

### Switching To Hash Router
React Router has a nifty component called [<HashRouter>](https://reactrouter.com/web/api/HashRouter), which allows our UI to rely on the hash portion of the URL (www.example.com/#/I/Am/The-Hash-Portion).

This was necessary because I was hosting this application on a subdirectory of my GitHub domain. For example this application is hosted at `https://aj-rom.github.io/hike-it-up-v2/` not `https://aj-rom.github.io/`. As normal routing would break this.

### Persisting Application State
I had everything working as I wanted it except one thing, my state wouldn't persist on refresh. This made sense as there was nothing keeping application state stored in the users browser.

There were a couple of ways to implement this:
1. Use [redux-persist](https://www.npmjs.com/package/redux-persist) & [redux-storage](https://www.npmjs.com/package/redux-storage)
2. Persist application using raw JavaScript (build it myself)

After doing some research I learned that implementing this really wouldn't be difficult at all and this will save me two packages and maybe even more.

JavaScript has a nifty object accessible on every window, [`window.localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), that allows us to store data within the users page. This even persists when the page session ends, perfect for handling refreshes.

I went ahead and modified my [application store](https://github.com/aj-rom/hike-it-up-v2/blob/master/src/store.js), to continuously save to storage when it updated and then clear when the user logs out, clears their history, or deletes their account. 

## Hosting
Hosting the application is a whole different process, but luckily I have had some experience doing this in the past and have got a decent understanding on how to do this.

### The Backend
For my backend I wanted to host it on [Heroku](https://heroku.com) which allows for simple deployment from GitHub repositories and is completely free. 

Their deployment process is quite simple, all you have to do is link to a GitHub repository and choose a branch, then deploy the application.

To make my Heroku server as least crowded as possible, I created a new branch named [heroku](https://github.com/aj-rom/hike-it-up-v2/tree/heroku) that would only contain the contents from the `backend` folder.

Now that I had this branch only containing Rails related files, I headed over to Heroku and deployed the application.

### The Frontend
This is probably the easiest way to host a react application for completely free, especially if it lives in a GitHub repository.

The [gh-pages](https://github.com/tschaub/gh-pages) npm package, makes for quick and easy deployment of fully compiled react applications.

After running two simple commands `npm run predeploy && npm run deploy`, the frontend was up and running!

## Conclusion
I am very happy with the final outcome for this project as it pushed the limits of my understanding of JavaScript, Rails, HTTP protocol, and full-stack development.

All in all there are really only slight optimizations to be made using code splitting, and maybe implementing search functionality (which is pretty much done). 

I hope this can be a resource for others to learn from or get inspiration for their next project!

Thanks for reading, if you would like to check out the application you can do so at [this link](https://aj-rom.github.io/hike-it-up-v2/), or if you would like to see the GitHub repository you can do so [here](https://github.com/aj-rom/hike-it-up-v2/).