How We Planned a Full Rewrite of GraduateNU’s Frontend
This semester, the GraduateNU team at Sandbox decided to rewrite the frontend of our project. GraduateNU “aims to empower Northeastern students to customize their plan of study through an intuitive and flexible interface shaped by student feedback” (our mission statement). My name is Justine Luo, and I became the project lead of GraduateNU in September 2021. In this article, I would like to share how my technical lead and I came up with the rewrite planning process, lessons we learned, and the team’s progress so far.
Setting the Stage
GraduateNU has been at Sandbox since June 2019, and since then, many developers have contributed to its growth. Projects with many contributors are capable of implementing a lot of innovative features quickly, and GraduateNU has been no exception. These features shaped our product’s fundamental purpose and identity. But, working quickly also sometimes meant a lack of standards and quality. As a result, there were many places in our codebase where design decisions were made ad-hoc, which snowballed into hard-to-maintain implementations.
Due to a UX Competitive Analysis we had during the semester, the team realized that we needed to develop unique and useful features quickly in order to still provide value to Northeastern’s students in the long term. This goal was difficult with our current code. Accomplishing even a small task, which should in theory require minimal changes, posed a big challenge due to our inflexible codebase. Additionally, as the project and the team matured, we standardized technical processes, learned about industry practices, and saw many places we wanted to improve. The deep-seated tech debt hindered fast development, and our growing dissatisfaction with the buggy codebase culminated with us deciding to rewrite the frontend. There were many reasons for choosing to rewrite, but this article will focus on how we approached the rewrite rather than why.
Introducing industry best practices into the project and revisiting design decisions were some of the main goals we had. We hoped the new codebase would improve developer experience by enabling team members to ship faster and impact users quickly. We also envisioned this rewrite as a way to bring GraduateNU closer to our mission statement and deliver value to students quickly.
These aspirations are what became the motivations and priorities of the rewrite:
- Well-researched technical designs. We will produce designs we are confident in. These designs should lay a strong technical foundation for our project and should be guided by best industry practices.
- Communication. We don’t want to repeat previous mistakes by having ad-hoc decisions. Instead we will communicate these decisions to each other and iterate on them with peer feedback.
- Knowledge transfer. Given the project will undergo a big change, we don’t want the next project team to be lost. We also don’t want to lose the design work and knowledge we accumulated this semester. We will establish standards and write documentation that will be transferred down into future teams.
- Keep it simple. We are not adding new features during the rewrite. Instead, we will simplify and improve the current product. We will value reliability over having many features.
Our priorities stayed the same throughout the process, and all our efforts in the past two months stemmed from the shared vision and priorities.
Creating the Plans
In order to meet our first priority, I needed a way to break down work so that people could start designing. To avoid the same mistake of making ad-hoc design decisions, I decided that there needed to be separation between design and implementation phases, with design informing the implementation. I met with my technical lead, Aryan Shah, to ask about technical areas we needed to design. Aryan quickly listed a couple of main areas to think about off the bat, including state management and component styling.
Given these areas, the first idea I had was to break down the work by React components and fix these areas for each component one at a time. However, I quickly identified that having each developer work on different components would introduce more discrepancy to the codebase. I feared that approaching it one component at a time would create too much variance, and spread developers too thin — they would need to learn about each area but couldn’t spend much time on any. What I wanted were common conventions and design decisions that were well-researched and backed by experience. There was also the issue of code conflicts when multiple developers make overlapping changes to a common resource. I realized that starting with designing components was too close to the code and rejected this idea. There needed to be more discussion about how to deal with these main ideas.
My second idea was to break down tasks by workflow, which are groups of components. This solution reduced code conflicts and facilitated common convention, at least within the workflow. However, I feared that I would still be spreading developers too thin and asking them to do too much at once. It also did not completely solve the issue of code discrepancies. Aryan and I both envisioned a codebase where people learn from examples of good industry practice. It would be ideal if we already had sample code in place before people worked on components. That way, less experienced developers would have a good example to build off of. Because of these concerns, I ended up rejecting this idea too.
Back to the Drawing Board
Aryan and I were still thinking about this issue when one of our developers, Cindy Luo, volunteered to make an overview of our React components in their current states. At first, I thought it would just be a helpful way to view a snapshot of the project’s state at the time. But after Cindy presented the components and their implementations, it became apparent to me that some of the issues were not going to be solved by simply rewriting at the component level — we had deeper issues. Namely, there were problems with conventions and tools that we should be using, but didn’t because of tech debt, or simply hadn’t thought about.
I spoke with Cindy about my difficulties with splitting up the design work and my reasons for rejecting the original ideas. Having been a project lead herself, Cindy had a lot of insights to share, and she suggested separating the design process into two steps. In the first step, we should have someone who has experience with a specific technical topic (such as styling and theming) make a guide on the topic for the team to follow when they’re coding. Then, the second step should focus on designing code-specific implementation details. Initially, I was concerned about knowledge transfer — should just a few people be making those guides? We discussed this and decided to aid with knowledge transfer by documenting the design proposals and holding synchronous design review presentations to collect feedback and address questions. Having figured out a general plan, the next step was to boil it down into a concrete process and decide which design areas were worth spending time to research.
Creating the Platform Design Process
When I talked to Aryan about Cindy’s idea, he also agreed that it was a clean way to separate the design stages. He took this idea and created the concept of “platform design”, where platform means a group of technologies that serves as the foundation upon which code is developed. The goal of platform design is to re-evaluate our frontend’s foundation (i.e technical stack and code organization). This was our way of laying stable foundations upon which we can build the rest of our code. After re-examining all the features of our product, we ultimately decided that these would be our platform design areas:
- State management
- API interactions
- Types of page rendering
- Styling and theming
- Error handling
- Drag and drop (a core functionality of our frontend)
- Sidebar structure and auto-validation (validation refers to validating the student’s plan of study based on graduation requirements)
From here, I broke each topic up into a task with the following requirements:
- Look into what the topic is
- Figure out why things are the way they are right now in the codebase (so that we may avoid the same mistakes)
- Propose new solution(s) and justify it/them
- Explain the the implications of the solution(s)
- Provide a proof of concept (show a code snippet)
Creating the Component Design Process
While thinking about the platform design phase, Aryan and I were also simultaneously planning component design, which is a level higher than platform design. These tasks were easier to arrange because we had already drawn a line between platform and component work. For this, Aryan and I grouped the components by workflow and how much work it would take. For each component design, the task requirements were:
- List what dependencies the component should have
- List the global and local states and justify why they are necessary
- Describe what logic lives inside the component and justify why
Design Review Process
In order to facilitate communication and knowledge transfer, the team had many design review meetings to discuss both platform and component designs. Prior to the meetings, each developer would research their topics and document the problems along with potential solution(s). To guide people’s research and specify proposal requirements, I created templates for developers to document their findings and proposals. Then, during each design review, the person who researched the topic would present their documents, collect feedback, and answer questions from team members. This was an iterative process that involved multiple design reviews to talk about the improvements made after each feedback session. While we preferred real-time feedback, due to the lack of time and to avoid overwhelming the team with too many meetings, team members also often collected asynchronous feedback. Lastly, after several iterations, developers presented their finalized designs at the last design review.
In terms of how things actually played out, the design phase is going as planned. Because we split the team in half for platform and component designs, the team was able to work on both phases simultaneously, helping us make fast progress. Getting iterative feedback from peers was also a key part in making our rewrite go smoothly. The only part that didn’t go according to plan so far was a last minute switch to use ChakraUI for styling. With the frontend rewrite, we also created new UI wireframe designs. When Aryan and I started to write tickets for implementing the new UI, we realized that our originally proposed styling library, MaterialUI, may be difficult to style to the way we want. After a discussion with the team, we decided to switch over to ChakraUI, a more flexible UI library, to enable us to have more control on the component styles. This switch went very quickly and smoothly because we all already had a common understanding of the original proposals.
At this point, we have wrapped up platform design presentations and most of the platform implementation. Component designs are also close to being done. It’s taking longer than expected because I did not account for two groups of components in the timeline, but we can wrap it up quickly given we now have experience with component designs. Since we’re still in the design phases, it’s hard to know what issues we may run into later during implementation.
The team is continuing to work during the summer with the goal of making our alpha release on August 31, 2022. Our alpha version will entail launching our finished frontend to a small audience. It will be stable, available, reliable, and show off our core features and redesign.
A few of our summer goals include finishing frontend implementation, e2e testing for the backend, and setting up new infrastructure. To help us transition into new leadership and welcome new team members in the fall semester, we put an emphasis on documentation so that the new team can understand our work from this semester and contribute to it. We already have documentation for why we chose to rewrite and all the technical design documentations. This summer, our goal is to create onboarding documentation of our new code and cover every feature we develop.
We also want to be able to collect user feedback through our new UI and have a process for turning user requests into production features. Therefore, before the alpha release, the next project lead will also create mechanisms and internal guidelines to make user feedback collection easier.
When Aryan and I first started this semester, we had planned to focus on feature development and user research/interviews. A month into the semester, we recognized a need for a clean up, but it wasn’t until the middle of the semester that we decided on rewriting the entire frontend. Changing the project direction was a major decision to make, and resulted in a lot more planning and road-mapping than Aryan or I had ever thought we’d do. There was stress about how to move the team forward while we took a break to figure out redesign plans, and how this change will impact new developers joining the team next semester. However, because we were thinking about those concerns, we were able to work together to create a thorough roadmap as well as a contingency plan for roll-over work into the summer.
This rewrite ended up as one of the most valuable decisions we could have made for the team. Through this experience, we learned about how to work efficiently as a team and we learned a lot from one another. Since we had only two months to finish the design phase, it was a unique challenge for me to learn how to fit that much work into that small of a time period, while helping the team stay on track.
It’s hard to measure the quantifiable impact of our rewrite since we’re still in the initial stages of the process. We’ll have to see if the decision to overhaul pays off later, but we are confident that our efforts now will lay strong foundations for our future work and solve many of the issues we are facing now.
This rewrite really challenged me as a project lead and taught me how to adapt to changing requirements. It has been such a fulfilling and fun experience, and I’m so grateful for my team for being here with me for this exciting journey. I appreciate my team so much for their amazing work and constant support.
Special thanks to Aryan Shah for being so dedicated to the team, our mission, and our product. He’s been so kind and supportive, and I can’t express how thankful I am for him always listening to and talking through my ideas, and taking them to the next level. I appreciate how thorough he is about technical details and his genuine passion for tech. This rewrite process definitely would not have been the same nor gone nearly as smoothly without Aryan.
To our developers, Alex Takayama, Brandon Lim, Cindy Luo, Duy Tran, and Jia Mu for always being down for a challenge, being curious, and genuinely caring about the product. Their passion for our mission and tech was so inspiring and motivated me to become a better project lead for them. It’s been so fulfilling to watch them all grow and contribute to the project, and I could not ask for a better team to take with me through this rewrite journey. I am so grateful for you all.
To Linda Zeng, our talented designer, for her amazing work on frontend wireframes and always pushing to improve GraduateNU. I’m so grateful for her dedication to user experience and always helping the team see from the user perspective.
A very special thank you to my Sandbox friends who took the time to read and edit my many drafts of this article: Alex Takayama, Aryan Shah, Cindy Luo, Daniel Wang, Duy Tran, Jia Mu, and Shash Jarmale. It was intimidating for me to write an article like this, but thanks to them, this article has improved so much from the first draft and became something I can be proud of. I truly appreciate how thoroughly they read each of my drafts and all their insightful feedback. Thank you all so much!