Building an App for the Furry Family Member
Clean Your Pet with Dignity
Have you ever considered how truly humiliating the typical grooming experience is for your pet? Your beloved furry friend is jammed into the back of your car and shivers the whole ride there because she knows what’s about to happen. When you arrive, she’ll be taken to a “back room” with clear glass windows and shackled to a cold metal table in full view of other pet owners who stare and point while someone with rubber gloves scours every inch of her defenseless body.
There has to be a better way!
I give you Pet-XPress! Pet-XPress recognizes what an uncomfortable experience a trip to the groomer’s can be for your pet, and also what an inconvenience this literal guilt trip can be for pet owners. This is why our team is helping Pet-XPress to build an application that will allow pet owners to connect with groomers who can come to you and make your pet look beautiful in the privacy and comfort of her home.
In this blog, I will walk you through the step-by-step process our team is taking to make this streamlined home-grooming experience a reality. Our goal is make your next grooming appointment an event you and your pet will look forward to!
The Product Roadmap
As with any attempt to disrupt the status quo, the main challenge we face is to convince enough customers (in this case pet owners and groomers) that they deserve better than the options currently available to them.
Pet owners will need plenty of grooming options so they can hold their groomers accountable. They will also demand an easy and efficient experience that will far surpass the monthly ordeal of hauling your pet to the “shop.” To accommodate this, our application will allow owners to:
- Create a profile page for their pets that will serve as a hub for accessing the app’s most popular features
- Locate groomers in their area using an open sourced mapping platform
- Schedule, cancel and confirm appointments through an interactive calendar API
- Rate groomers based on how satisfied the owner and pet were with the in-home grooming experience.
- Pay for services through an integrated payment processing API
Groomers, for their part, will require easy access to customers so they can quickly build a customer base seeking the services they provide, and a way to streamline business operations so that the need for a brick and mortar is rendered obsolete. With this app, a groomer will be able to:
- Create a profile page that list the services the groomer provides, highlights favorable customer reviews, and provides links for customers to schedule appointments
- Set appointment availability through an interactive calendar API
- Accept payments through an integrated payment processing API
- Rate their customers
This, of course, is just our jumping off point. As with any product development process, we expect the feature list to expand as we dive in. But let’s begin with setting tasks for the features we outlined above.
Assigning tasks
Our team’s mission is to ensure that users can perform each of the functions described in the Product Roadmap above with the click of a few buttons. This means that we, as developers, will need to click many more buttons to take the stress off of the users.
We will need to complete a number of tasks to ensure that each feature provides all the functionality envisioned. When you add all the tasks from every feature together, the quest of building this application, or any user-friendly application for that matter, can seem quite daunting. So where do we start?
Organization is paramount!
Thankfully, there are applications to help those of us who may be organizationally-challenged. Our team uses Trello, an interactive application that allows teams to organize product features into cards, create a task list to realize each feature, and assign those task to specified team members. Teams can also set a series of stages that will need to be completed before all tasks are completed and the feature is ready to deploy.
Trello Cards
Our first step was to create a Trello card for every user story in our product roadmap. The title of these cards simply describes the feature we will provide to our users. Trello lists these features for us so we can break them down one by one. Here’s a sample of what that looks like:
Next, we can open each card and create a checklist of tasks that will need to be completed to generate the desired feature. One of my first assignments was to tackle the customer profile page feature. Here is the task list our team created for this feature:
Note that the task items are not technical in nature. They do not delineate the tech stack or how the needed components will be structured. These points should be laid out in an engineering rubric
Once each task list is created, our team assigns each card to specific team members. In the example above, the team assigned the Customer Profile page to myself (“TL”) and my teammate Virginia (“VW”).
Stages
To ensure a consistent process for the implementation of every feature, our team created a series of stages that each card will need to complete before the feature can be deployed. The general idea is that the initial code generated serves as a first draft that needs multiple levels of review before being merged into the main version of the application.
Here are some of the levels of review that we implemented to guarantee that each feature is fully functional before being deployed:
- A stage to list and consider blockers we have encountered or are encountering in implementing the feature
- A stage for peer review
- A stage for stakeholder review
- A “completed” stage
In Trello, the stages are arranged as tab on the top of the Trello Board. They look like this:
This multi-stage review system ensures that 1) multiple team members are accountable for the successful implementation of each feature and 2) the finished product has survived extensive scrutiny and emerged more polished and succinct.
Seems simple enough, right? While the process certainly helps with organization, almost every feature we’ve taken on has come with its own technical blockers that have caused the feature to stall out in one or more of the review stages. In the next section, I will discuss the technical blockers I encountered when trying to pull data from our backend to create a dynamic Profile Page component.
The Fateful Connection
Early in the development process of every dynamic application comes the point where the front end must first connect to the backend so that the application can provide user-specific information from the database. Despite extensive planning before any code is written, there are almost always glitches that the team needs to work through before this fateful connection is seamless. Sometimes those glitches can be as simple as typos in the endpoints, or synchronizing the data keys. Other times, however, the issues are more complicated and require collaboration with the team to resolve.
In our application for Pet-XPress, we first attempted to connect to the backend to pull user data that could be entered into the Profile Page component. We encountered two significant issues when trying to make this initial connect. The first issue we encountered was collecting a bearer token and an id from our secure identity management API that could be used in our backend call. The second issue was determining a way to access our backend on our local server so we could tweak it as needed without deploying unnecessary changes.
The Okta Problem
Those of us with a rudimentary knowledge in NodeJS or other backend frameworks can generally implement a simple system for authentication and authorizations involving either Bearer Tokens or Authentication Cookies. The problem is that, unless we have an extensive background in cryptography and/or other data security fields, these simple systems are not secure enough for widespread dissemination of a scalable app.
For this reason, third party secure identity management systems are often the preferred method to ensure that applications are secure. To use these systems, developers are required to read the documentation and get at least a basic understanding of how the system operates. For Pet-XPress, our project leaders selected Okta as the secure identity management system we use to better secure our data.
Fortunately for us, the authentication/authorization middleware needed for Okta was already setup when we started working on our app. That said, we still needed to know how to pull the bearer token and id from Okta in order to make backend requests. This is where we hit our first blocker.
To determine where this information was stored I first had to determine what information Okta provided. By reading through the documentation, I discovered that Okta gives us access to two objects, “authService” and “authState” using a “useOktaAuth” hook. We stored these objects in variables with this code:
The bearer token is stored directly in the authState object. Our project leaders provided us with the following helper function to access this token so, for me, it was just a matter of recognizing the function and its purpose:
The function first checks to see if the user is authenticated by accessing the boolean value for “isAuthenticated” in the authState object. If the user is not authenticated it throws the authentication error. Otherwise, the function returns the entire header with the bearer token value pulled from authState.
Accessing the user id is a little trickier as it is not stored directly in either authState or authService. Rather authService includes a “getUser” method which returns a promise when called. If resolved, the response provides user data including the user id under a “sub” key. Here is the code I implemented to retrieve this data:
The retrieved id and header could then be plugged into an Axios call I created, to retrieve the desired user data:
Working through this blocker didn’t require any specific expertise. All I needed to do was to take some time to read Okta’s documentation to gain a better understanding of the syntax and naming conventions it uses. The lesson being that if you’re using a third party secure identity management system, set aside some time to go through the documentation (even if most of the functionality is already provided for you).
Local Servers, Postgres and a Hard-Learned Lesson
The next blocker is a little embarrassing, not because I was stumped on a piece of code or because I had to ask for help to get the answer, but rather because I failed to do something that I learned in grade school — follow instructions.
The issue concerned Postgres, the database system our project leaders selected for this application. Postgres is an effective database system because it is highly scalable and easy to learn, but one of its disadvantages is that it will not run on local servers without additional software.
For a couple of days, the front end of our application was not receiving responses from the backend and we could not figure out why. We went through code numerous times and everything seemed fine. We also dove into the backend to see if there were any CORs issues or other problems. (There actually was a CORs issue but it’s not what was preventing us from receiving responses).
Finally, our Technical Project Lead discovered that I had not installed additional software so I could run Postgres on my local server. He and another teammate walked me through installing ElephantSQL and running Postgres through that software. Issue solved!
The reason this whole thing was embarrassing is because our project leads had instructed us to install a software to run Postgres on at the beginning of our project. I neglected to do this because I was working on the front end and figured I wouldn’t need the software until I started working with the back end. Of course, I forgot about this step when I went to work with the backend and we were stuck for days.
So, at the risk of sounding like your third grade teacher, always follow instructions!
Where We Stand and Where We’re Going
We are at the turning point in our app when we wrap up the features we’re working on and turn it over to another team. Like many developers leaving a project, I wish we had accomplished more, but I’m also proud of the work that we did.
We created a home page that renders upon user login:
From the home page you can link to the user profile page, which contains some basic user data:
You can also link to an edit profile page which allows user to edit some of their information:
Finally, with our app, customers can view groomer profiles on cards that include rating averages and a cool flip feature:
It is our hope that future teams will expand on what we’ve done by adding some or all of the following features:
- Mapping functionality so customers can see where groomers are located
- Scheduling functionality so customers can schedule with groomers directly on the application
- A payment processing method so customers can make payments and groomers can receive payments through the app.
- Additional data points for both customers and groomers
The biggest challenge in implementing these features will be working with new APIs such as Stripe API, Mapbox API and Calendar API. As noted above, I strongly recommend that incoming developers devote significant time to reading the documentation for the APIs before diving into the code.
I’ve learned so much working on this project and am very grateful to have worked with such a productive team. My biggest takeaways from this project have not been learning more code, but rather have been learning all the organizational steps that go into building a successful application before a single line of code is even written. Things like creating user stories, engineering rubrics, wireframes and Trello boards were fairly new to me before working on this app. Now, I’ll feel much more comfortable using these tools in my career.
I also learned how to productively work with a team and to receive constructive feedback. The most important feedback I received was to slow down, take time to learn what I need to, and use the resources available to me. The process has been incredibly rewarding and I feel I am a better developer and person because of it. I can’t wait to get started on the next project!