The Journey to Creating Wanderful
Building smaller projects helps to reinforce learning and be able to freely experiment with things. Larger projects require significantly more forethought on the app and data architecture, technologies used, and overall direction of the project.
This past Tuesday evening, the team project that has enveloped all of my free time has launched. Wanderful is a random travel destination site built utilizing the MERN stack. Users are able to visit the site and click a button on the landing page to discover details about a randomized destination stored in our database. Here they can get a quick blurb about the location, and information about various points of interest including: hotels, restaurants, entertainment, and the ability to check flights to get to the location. If a user creates an account with the site they are able to save their favorite destinations and POIs where they can easily view them on their favorites dashboard. If a user desires to get any more information about a give POI, they can click on the given item to have the Yelp details for that location open in a new window.
Prior to this application, I had never built a large scale application other than this website, which in comparison is basic. I had never built a full-stack application, only frontend applications. Lastly, I also had never been part of a team to build out a project. All of these are areas that I knew I needed to gain more experience in for my pressing web developer job search. Enter Chingu. Chingu is a worldwide group with the focus on connecting developers to build a project together and advance their learning track. It is completely free, ticked off all the boxes that I was looking for, and I decided to jump into it headfirst. I was paired with a team of two other developers with a similar skillset, and after our first meeting we had solidified the conceptual idea which evolved into Wanderful. Over the next 6 weeks we worked on building out the concept from scratch.
Working on a larger scale project as part of a team, was a valuable experience both in terms of what we were able to accomplish together and the logistics of working on the same project at the same time. Consistent communication was essential to make sure that we were working synchronously, and also to reduce the number of merge conflicts. It also encouraged better code commenting and making the logical flow clear and understandable to others who may rely on the code for another feature. One of the really rewarding experiences for me personally was to spend a substantial amount of time on a given feature and then be able to walk through and explain the branch to my teammates. This helped to solidify my understanding of the concepts and find the best way to explain why I used the methods that I did.
We decided to build our project on the MERN (MongoDB, Express, React, and Node) stack with each of us having varying levels of experience throughout the stack. We also knew that there would be some significant data management within the application and planned to use Redux early on in the project. For the visual design we landed on using Material UI components. Now that we had the tech stack determined, it was time to start actually building the thing.
Making a Courageous Leap
As we were discussing the tasks that needed to be implemented to begin building out the project, I kept on being drawn to the concept of local user authentication over using OAuth. I pushed for working on that and some of the other backend portions of the project, recognizing that I had never implemented any features like this, or built anything beyond a frontend application. Then again, stretching myself and learning new things through building was exactly why I joined the cohort in the first place. Previously I had done some tutorials on working in the backend and built some microservices, but that was were my experience stopped.
As I poured over the documentation for Passport.js and started installing packages left and right, it became readily apparent that there was going to be a lot of trial and error involved in setting this up. Each package had multiple dependencies that required specific configuration in order for each to work before I even reached the authentication logic. To make matters more interesting, I found that the out of the box setup for Passport wasn't working the way I wanted with the frontend, using React and React Router. In order to resolve this issue, I dove further into the documentation and implemented my own custom callback solution which resolved that matter. After a week or so of working on it during the commute and evenings, I finally had it all sorted out. Creating and merging in that Pull Request was exhilarating. Before I would become so excited and proud of completing a simple project that was about 300 lines of code. The final authentication feature PR was over 400 lines of code.
After completing the authentication features, I moved on to creating the functionality of a user being able to store their favorite hotels and points of interest. Building out the backend logic for this went fairly smoothly. We utilized the Yelp API to fetch data for all of the places in each location. The Yelp API already provided a unique ID field in their response, which I was able to capitalize on by storing it in an array on the user model. When the backend API endpoint was hit, all it would need to do is check if the Yelp ID was already in the array and add or pull it as needed. We went with storing just the Yelp ID of each location in the user model to maintain fresh data each time the user visits the site. Thankfully, the Yelp API provides a generous number of requests. However, clearly we needed an efficient means of storing the populated data for ready access by the front end; it was time to conquer my hesitation with Redux.
I don't know what it was about Redux that perplexed me so much, but I couldn't quite wrap my head around the concept before the project. I didn't understand why it would be necessary and what good it would do if the data was lost when the app refreshed. Of course, previously my React applications had only gone one or two levels deep in nested components and rarely consisted of more than 5 components. Even before I started trying to hook up Redux for this project, it was clear why it would be necessary. There was substantially more complexity and deeper nesting of components that would have been a nightmare to pass state down to and also create functions to modify the state of the parent components. Additionally the data would be shared across entirely different routes and component structures. I began working on setting up the Redux actions and connecting different parts of the UI to the Redux store. There were several points of revelation of the power of Redux in increasing complexity along the way.
- I created an auth state which stored whether the user was logged in or not. Initially this selectively rendered the header component to show Register/Login or Logout buttons.
- I created a favorites state which stored all of the details retrieved from the Yelp API for each of the locations a user favorited. This state was kept in sync with the backend when locations were added or removed from the User model instance. Additionally, I structured a concise and reusable means for the frontend to update this state.
- On each details page there is a heart for the respective location that we wanted to fill in or have outlined to represent if it was currently a favorite. I was able to utilize the existing auth state which held the raw arrays of Yelp IDs to utilize more performant logic.
- I implemented isFetching boolean flags in various pieces of state to allow rendering of progress loaders while the data is being fetched.
I am really proud of the project that our team built. It was an incredibly valuable learning experience building a larger scale application. Building smaller projects helps to reinforce learning and be able to freely experiment with things. Larger projects require significantly more forethought on the app and data architecture, technologies used, and overall direction of the project. It becomes increasingly more difficult to make significant changes in course as the application grows in size. For me, it was invigorating to engage in these types of conversations and to play a role in guiding the direction of the decisions made. Solving these more detailed and complex problems as well as connecting more moving pieces together was amazing. Each piece needed to not only be thought out in its implementation, but also how it was going to integrate into the rest of the project that oftentimes another team member was coding.
There were also many benefits in building the project with a team of other developers. We were able to play to each other's strengths in the tasks that we were working on. As we all contributed to the codebase and reviewed each other's pull requests, we were able to bounce ideas off of each other or identify ways that code could become more streamlined or efficient. Lastly, discussing and explaining why things were completed in a certain way was important to the team dynamic. This is also an important skill to have in presenting a particular course of action to a potential external party on the job.
For those looking to further advance their web development skills, I can highly recommend joining a Chingu cohort, or other means of working with a team to create a larger scale project. There is much to learn in this medium, and I know that I am better prepared for a job in the industry having completed it.