COLAB13 - Web App

Dragonfly

A web app to help you stay organized while job hunting. Dragonfly enables users to keep track of critical information to help them land their dream job.

Problem Background  

According to Zippia, in 2021, it took an average of 21 to 80 job applications to land one job offer. Job hunting can be a number’s game – the more applications you submit, the higher your chances of landing your dream job. However, keeping track of every application you’ve submitted can be cumbersome as over 94% of users use multiple platforms to find prospective jobs. 

With over 78% of users using some form of organization tool to help them keep track of the positions they’ve applied to, an opportunity exists to congregate key attributes that are helpful for users to keep them organized during this process.

Research Insights & User Pain Points

Using our network, we identified a few different categories of prospective users and conducted over 60 survey respondents and heard the job hunting process would be easier if… 

  • There was a way to keep all of their job applications organized
  • They could keep job descriptions on hand without worrying about them being removed
  • There was some type of automated process to keep my applications updated
  • There was a way to keep track of what jobs need to be followed up on or when I last reached out to or spoke to someone at the company

Our preliminary user research with job seekers found that users were currently frustrated with the process of job hunting. Many found the process to be overwhelming and tiresome. The majority of our users are currently either Google Sheets/Microsoft Docs or Google Words/Microsoft Docs to keep track of their job applications. However, this process is typically abandoned due to the effort required to upkeep the data.

Solution Explanation

“Based on our target users’ pain points and the capabilities of our team, we leveraged the RICE framework to prioritize the following features: 

Our learnings: RICE allowed us to easily see what was a priority and wasn’t based off distilling our user research and the capabilities of our team. 

In our MVP, we decided to prioritize our Dashboard. One deep exploration we made was on ‘extensions’. While it seemed extremely high-value for our users, it was initially high-risk for our technical team as none of the members on our team has ever built a feature like this before.

Once our SWEs conducted their research, we were able to conclude this was something attainable and something we pursue.

Lo-fi Mockup

Hi-fi Mockups

Iterative Design Learnings

We conducted a total of 10 usability studies:

  • Low Fidelity - 4 participants were tasked with managing the Card View and List View of our product as well as a possible chrome extension.
  • High Fidelity - 4 participants walked through our polished designed product with prompts tasked at them using the Card View, Sort, Filter, and Board View.
  • High Fidelity v.2 – 2 participants provided feedback on the newly updated version of the Board View

We learned the following: 

Low Fidelity: Users were able to navigate the Card View and List View easily. They bought into the idea of the product and really valued what the extension had to offer, that being a way to auto-populate new cards from job applications on the web. Additionally, they would like different ways to view the cards.

“It was very user-friendly! It’s nice to have options for the different views. I like that it  has the options for both auto and manual inputs which is nice.

High Fidelity: Users were excited about the potential of the product and liked the UI design overall. The tasks they found the most intuitive were creating cards, changing the grid layout, sorting, and filtering. Editing and adding cards to the Board View was far from intuitive and users felt lost and confused when it came to this process.

“I liked the Board View and would likely customize it as much as possible.”

High Fidelity v.2: The participants were able to navigate the website without any issues overall. The newly updated Board View was intuitive to use and users navigated the process seamlessly.

"I like it. It's a good way to have it all organized. It was straightforward and easy to use"

Implementation Details

Where is it hosted? 

Dragonfly’s frontend is currently hosted on Netlify at this link and the backend is currently hosted on Heroku. The backend deployment may be subject to change due to Heroku Postgres going behind a paywall starting November 28th, 2022.

Dragonfly is built as a Web application using the JavaScript library of React. The idea was to create a database to host all information from users and display on the page all the info the user had pushed to the database.

What is your tech stack?

On the frontend we used the React library to build out the UX/UI while adhering to an Atomic design pattern. On the backend we used Knex.js to build out our backend schema, Node.js to build out an internal API for our app, and Postgres to store all the data we were collecting and utilizing throughout Dragonfly.

Some other technologies we used were JSON Web Tokens to authenticate and authorize users to access certain pages of Dragonfly, Bcrypt to hash users passwords in our Postgres Database, and Puppeteer to support webscraping from a LinkedIn job posting so users can automatically create cards in their dashboards.

High level journey of a request

Dragonfly's backend was developed using a Model, View, Controller architectural pattern.

What this means is that instead of having all the logic of a request inside of one large file, the request’s lifecycle is split between the model and controller, and then once the request is complete, the response from the request updates our view which is what our a users sees.

An example of this pattern in action can be demonstrated when a user attempts to automatically create a card using a URL from a LinkedIn job posting.

To start the request lifecycle a user would fill out a form including the link to the posting, the current status of the application, the date applied, the recruiter contract, and any notes they would want to attach to this card. Once all the information is filled in and the form is submitted, this submit event triggers a POST request to one of our API routes. All routes that handle CRUD operations specific to applications live inside of the applications controller. Inside of the applications controller there is an asynchronous function that gets called and pulls all the information from the body of the request.

Once the information is pulled, we can now pass in the parsed LinkedIn URL to our webscrapper which utilizes Puppeteer to run a headless browser and navigate to the URL provided by the user and scraps all relevant information from the posting (such as position, company, location, and job description). Once we have successfully scraped the information from the job posting we pass both the information from the body of the request and the scraped information to our applications model. Inside of the applications model is where the query is made to our database.

Once the query is completed we send a response back to the user with the information from the newly created row in our database, and with this response we can update the frontend to reflect the changes made to the database. 

What was the hardest part of development?

One of our technical challenges was the user authorization and how to keep the same user credential constant while navigating through different pages of our website.

Does your app have any scaling issues?

The scaling issues with Dragonfly can be broken down into two sections. One being the hard cap that Heroku sets on the free version of Heroku Postgres which is a limit of 10,000 rows for our database. If we need to store any more information than that, well we can't, not without paying a premium.

The other part would be the monolithic architecture of Dragonfly’s backend. Any small change to the schema, the controllers, or models requires an entire redeployment of the backend. This is a major bottleneck for our application as it is cumbersome to redeploy every time you make a change to the repo.

A monolithic architecture also makes it difficult to adopt any new technologies that might be well suited to address a particular function of our application.

Switching to a distributed system such a microservice based architecture can address some of these issues. With a microservice based architecture each microservice has a single responsibility. Whether it be signing up users and authenticating log in requests, or handling all the requests for users boards, these tasks are split up into their own microservice.

If we need to make changes to a microservice, instead of redeploying our entire backend, we only have to redeploy that single microservice. The technologies that the microservices utilizes can differ from one to another. This allows us to use technologies that are best suited for the responsibility of that microservice. 

What are some key takeaways?

Mark - I would say that a key takeaway is to spend a healthy amount of time to really think about and plan out the backend schema. By taking time in the beginning to plan out what the backend looks like, it can save you time later on because you won’t have to make lots of changes to it because all the support for the features you want to build out are all there and can be created using what you planned out.

Jairo - Building this product, I realized how the same result can be achieved using different paths and techniques. While developing the code, I would share my thoughts with my fellow developer on how to process the issue and he would solve the same issue with a different approach. This gave me the feeling that there is not right or wrong answer but maybe just concise and clean code, so at the end of the day both would have the same outcome

Future Steps

We will continue advancing our project moving forward. We’d love to work towards other features we discovered were important to users but did not have the capacity to build over the course of this program (8-weeks). We look forward to sharing this with you!

Learnings

Product Manager Learnings:

Amy Du

Co.Lab was a unique experience for me for several reasons:

  • I had an opportunity to guide a team of three – 1 Product Designer & 2 SWEs
  • As a team, we were able to formulate a common problem space we were all invested in. This investment is needed to drive engagement on the team. 
  • You need to ruthlessly prioritize as a PM and consistently think in advance so you can prepare your team

Designer Learnings:

Stephen Oey

Co.Lab delivered on its promise of real world experiences and working in a fast paced product-development cycle.

From the program I learned to think from various perspectives and lean on my team to find the best solution in the room rather than working in my own silo. Having a dedicated PM and collaborative SWEs was extremely valuable. I was able to build confidence in my design thinking as well as learn to scope down our product to features that were truly top priority in order to deliver an MVP.

Additionally, learning to run a proper design handoff and run quality assurance with the developers was a new challenge for me. However, due to great feedback from my mentors and peers, this process ran smoothly.

Developer Learnings:

Mark Rodriguez

Co.Lab was only the second time that I had worked on a project while utilizing the agile workflow and the first time that I had worked on a cross functional team with a dedicated Product Manager and Designer.

I can confidently say that I have grown from this experience as a developer and gained insight into how cross-functional teams run in the industry.

As a developer we can often get stuck in our own little bubbles behind our computers writing code, but working closely with a designer allowed me to be closer to the customer than I have ever been before. Joining user testing sessions allowed me to see how the code I wrote was being used and allowed me to think of edge cases and see them play out in front of me.

Developers Learnings:

Jairo Calderon

&

From the standpoint of developer to developer I learned that working independently but alongside another programmer gave a real glimpse of what I can expect from others’ code.

As a fresh bootcamp graduate I have been comfortable understanding my own lines of code but when it comes to understanding other’s code it was a bit confusing and the reason is because you get exposed to different syntax or methodology that sometimes it makes you believe that it may be a totally different programming language and this can take a while to fully comprehend what is going on.

Regarding my learnings towards the other two professionals (Product Designer and Product Manager) this experience made me realize how a real company environment works.

Having people delegating tasks to you and depending on your work completion to make their work flow puts lots of pressure on yourself, thankfully my experience in this Co.Lab couldn’t be better, I had the opportunity to share a group with exceptional professionals that not only were there to make their best work but also to cheer me up whenever I needed.

Full Team Learning

As a team, some of the key learnings we discovered were the following: 

  • Communication is key, especially understanding the technical requirements for SWEs that Designer/PM may have missed in the initial process
  • Ownership is important so everyone feels invested in the problem space and idea
  • Always be flexible with timing and the solution: expectations vs reality: when it comes to timing, things will always take longer than we anticipate. It was critical to ruthlessly prioritize and de-scope to develop our MVP. It was also important to be flexible with our solution and empathetic to what might be feasible for the team to build.
  • Consistent iterations can be challenging but rewarding – Our SWEs enjoyed prototyping and building; however, felt it was challenging to have constant iterations that reflected updated user research 
  • WoW and Goal Transparency is critical to maximizing return: When everyone is open to what they want to achieve, as a team, we can maximize everyone’s experiences