Let’s build a FullStack App with JavaScript! ~ Episode 5: Part 1

Matt Basile
10 min readApr 4, 2019

--

This is a multipart series about building a Puppy Adoption Site with JavaScript. If you haven’t read all the articles please find them here: Episode 1| Episode 2 | Episode 3 | Episode 4 | Episode 5-Part 1 | Episode 5-Part 2 | Episode 6

Let’s Build our API — Part 1: The Plan

Have you ever heard the phrase “you can rest when your dead”? We’ll those folks clearly have never implemented a RESTful API before!

In this article, we are going to dive into what it takes to build our very own API. As I began writing this article I thought we could plan and build in one big swoop but I realized that would be a veryyy long article. That said I didn’t want to lose you guys over a 20-minute article so I decided to break it down into two episodes:

Part 1: Planning our API- Introduction to APIs and a discussion about what routes we need for our users and admins to access our data.

Part 2.A: Visitor Side Routes and Models- this will cover building the part of the API that will be accessible to everyone.

Part 2.B: Admin Side Routes and Models- this will cover our admins API. They will need to have the ability to edit, create and delete items in our database. We’ll talk about that in specifics during this section.

Sorry to not get you coding right away, but understanding why we’re building our API and what we need is going to set us up to succeed on this project and others in future. So let’s dive into the theory so that we can get coding soon!

What’s an API?

API stands for application programming interface and honestly, it’s a term that can seem pretty intimidating at first. I know when I started coding just hearing those three letters made me nervous.

Well, I’m telling you today there’s nothing to be afraid. The day APIs started to make sense for me was when I finally dissected them. APIs are just javascript functions that define the ways we can read, add to, update or delete something in our database. They are how our backend communicates with our database, and later how our frontend communicates with our database, via our handy backend.

When we begin chatting with our database there are specified actions or requests we can use. If you’ve ever heard of “CRUD operations” that’s exactly what I’m referring to. CRUD stands for create, read, update and delete. And when we communicate with our database these are the actions we implement.

With each of our CRUD operations, there are specified HTTP and SQL methods that allow us to request data and then act on it. In most cases, the HTTP requests will define our action and then the SQL methods will execute that action. This table from Wikipedia does a fantastic job of mapping out each CRUD operation and the corresponding HTTP and SQL methods:

Visualizing the connection between the CRUD, SQL and HTTP will allow us to start thinking that if we want to Create, Read, Update or Delete anything in our database we’re going to need to PUT, POST, GET or DELETE and INSERT, SELECT, UPDATE or DELETE.

Let’s start planning!

Getting started with an API is exciting, but we need to define where and when we’ll need access to our data. Knowing this will allow us to maximize our time building instead of focusing on building routes we should’ve completed earlier. I’ve started too many projects only to realize I needed an extra route here or there and I don’t want this to happen to you!

With that said, the way I approach planning my APIs is mapping out the flow of each user accessing our site. This might sound odd at first, but the user is who we’re building the site for and knowing what data they’ll need at each step of their journey will help build practical routes in our API.

In our site, we’re going to have two types of users: visitors and admins. Let’s start by mapping our a visitor’s journey and then take a stab at admins.

Site Visitors Journey:

  1. Our visitor wants to adopt a puppy! Or at least look at some cute doggies who are adoptable… let’s check out Doggoland.com!
  2. The visitor arrives at our home page and immediately wants to see dogs and the kennels they belong to.
  3. After perusing through many photos they see a dog they absolutely adore. They want to learn more about that specific dog and the kennel it lives at.
  4. After seeing the info they realize, this dog neeeeeeds to be theirs. So they submit a request to the kennel to meet and potentially adopt the puppy.

It’s not the most complicated user journey ever, but it certainly serves our purpose. Let’s go ahead and pair these actions with some CRUD operations to our database.

  • View Dogs and Kennels: When a visitor arrives, they are interested in gathering as much information about cute dogs as possible. This would fall under the READ action in the CRUD operates. Can you remember what HTTP request and SQL method we’ll need for reading? (if not go take a peek at the table above). That’s right! We’ll need to use our GET request to return all our dogs and kennels. Additionally, our dogs and breeds tables are separated. However, when we return a dog’s data it’d be nice to know all the breeds associated with it. We’ll need to make another request in our backend to return all a dog’s breeds as well!
Routes well need:
GET - /api/kennels Expected Return - A list of all our Kennels and their dogs.
GET - /api/dogs (returns breeds as well). Expected Return - A list of all our Dogs and their breeds.
  • Filtering by a specified Breed, Dog or Kennel: This is similar to our first action except we’re going to need one dog or kennel or, in the specific breeds cases, all the dogs with associated with that. Again we’re still using our GET request but this time we can pass a corresponding ID as a parameter in the URL to help identify that specific item in our database.
  • There’s a real possibility that when we build out our frontend we might not actually need these routes and can simply parse over the prior we received above. But when planning it’s nice to over prepared rather than under prepared.
Routes well add:
GET - /api/kennels/:id (id === kennel's id) Expected Return - A specified Kennel and all their dogs.
GET - /api/dogs/:id (id === dog's id) Expected Return - A specified dog and all their breeds.
GET - /api/breeds/:id (id === breed's id) Expected Return - A specified breed and all the dogs of that breed.
  • Create Notification: Lastly, we need to allow visitors to submit a request without logging in. This can be done by creating a notification and assigning it to a specified kennel and dog. To do that we’ll need a form on the frontend that collects data so we can POST it to the backend. This form must include a kennel’s id and dog’s id so we know who to send the notification to and then what dog the notification is about.
Routes well add: 
POST - /api/notifications Required parameters: Kennel's Id, Dog's Id and an email address from the submitter.

Only 6 routes! That’s not so bad, but see how complicated some of these returns can get when we want to add data that are not all store in one data table? Planning this out beforehand is super helpful to understand what we’ll need to do.

Now that we have a visitors journey mapped out let’s talk about our Admin users. Their journey is going to look like this:

  1. Admins will arrive at work with a long list of to-dos and one of them is to check if anyone is interested in adopting a pup. They’ll log in to their dashboard to check if anyone has tried to contact them.
  2. On their dashboard, they’ll have access to a handful of data. A list of their dogs in the kennel, notifications waiting for their response.
  3. They click on a notification they received and proceed to email that person. The notification actually came from a good friend and they know they’re adopting this dog, so they decide to delete the dog from the kennel.
  4. While looking at this dashboard the admin is reminded they have two new dogs coming to them today. They upload their information and add those new dogs to their kennel’s list.
  5. Lastly, they notice the kennel’s profile is slightly out of date. They update the profile and continue on their day!
  • Login/Registration: When an admin comes to our site we’ll need to implement a login route to make sure they’re a registered user. And in that same vein, we’ll need a registration route as well. These will both be POST requests because we need to send their login credentials or add information to the backend. Also, when an admin registers we’ll need to create a kennel that we can link to their account.
Routes well add 
POST - api/login Required Parameters: email and password. This will return the admin's kennel information to be stored on state as well.
POST - api/register Required Parameters: username and password. A kennels POST will occur on the backend as well.
  • Dashboard View: On their dashboard, they’ll have access to a handful of data. A list of their dogs in the kennel, notifications waiting for their response. We’ll just need to GET all their specific data by the kennel’s ID. While this will return kennels and dogs we’ll need notifications baked into this call as well.
Routes well add 
GET - api/kennels/:admin_id Expected Return: all the information regarding that kennels. That includes Kennels, Dogs, and Notifications
  • Notifications: Since we’re getting all the notifications above we don’t need to be too specific about getting it by ID. However, we might want to update our Notifications every 10 minutes or so? Let’s add a route to return our notifications.
Route well add
GET - api/notifications/:kennel_id Expected Return: all the notifications associated with the kennel.
  • Dog CRUD: In our last two steps our admin has deleted and created new dogs. Sounds pretty CRUDDY to me 😂. To delete a dog, we just need a route to pass our specified deletion dog’s id to and to add a dog or two we’ll need to allow a POST request to occur. This will also include posting to our dog_breeds table and potentially breeds table if we’re adding a new breed. (This will be something we adjust when we implement our frontend so just be patient for now.) While we’re here an admin could input the wrong information and need to update it later in the week. Therefore we’ll need to add a PUT request as well so they can go back and make changes.
Route well add
DELETE - api/dogs/:dog_id Expected Return: a 0 confirming the dog is no longer in our db.
POST - api/dogs Required Paramaters: Kennel_ID. Expected Return: The new dog.
POST - api/breeds Expected Return: New breed returned
POST - api/dog_breeds Required Parameters: Dog_ID and Breed_ID. This will allow us to connect our new dog to previous breeds or brand new ones.
PUT - api/dogs/:dog_id Expected Return: The updated dog and all their old and new information.
  • Kennel CRUD: Like above this will just require a PUT route to update their information. I’d also like to add a delete route that will allow a user to remove their account. This will require that we cascade down and delete everything associated with that kennel. For now, we’ll represent that with the DELETE route but we may need to tweak other tables later.
Routes well add 
PUT - api/kennels/:kennel_id Expected Return: Updated kennel with all it's previous and new information.
DELETE - api/kennels/:kennel_id Expected Return: A 0 that confirms the kennels been removed.

Soooo that’s a bit more complex than our site visitors but when we break it down like this it becomes much more manageable. This list is an awesome launching point for us, but like every plan, we may need to make adjustments on the way. The good thing about that is, as the frontend and backend developer, we can control it all! So if we need to alter a route or add a new one we’ll be easily able to.

To review here’s a list of all the routes and HTTP requests we’ll need:

Routes for Site Visitors:
GET - /api/kennels
Expected Return - A list of all our Kennels and their dogs.
GET - /api/dogs (returns breeds as well). Expected Return - A list of all our Dogs and their breeds.
GET - /api/kennels/:id (id === kennel's id) Expected Return - A specified Kennel and all their dogs.
GET - /api/dogs/:id (id === dog's id) Expected Return - A specified dog and all their breeds.
GET - /api/breeds/:id (id === breed's id) Expected Return - A specified breed and all the dogs of that breed.
POST - /api/notifications Required parameters: Kennel's Id, Dog's Id and an email address from the submitter.Routes for Admins:
POST - api/login Required Parameters: email and password. This will return the admin's kennel information to be stored on state as well.
POST - api/register Required Parameters: username and password. A kennels POST will occur on the backend as well.
GET - api/kennels/:admin_id Expected Return: all the information regarding that kennels. That includes Kennels, Dogs, and Notifications
GET - api/notifications/:kennel_id Expected Return: all the notifications associated with the kennel.
DELETE - api/dogs/:dog_id Expected Return: a 0 confirming the dog is no longer in our db.
POST - api/dogs Required Paramaters: Kennel_ID. Expected Return: The new dog.
POST - api/breeds Expected Return: New breed returned
POST - api/dog_breeds Required Parameters: Dog_ID and Breed_ID. This will allow us to connect our new dog to previous breeds or brand new ones.
PUT - api/dogs/:dog_id Expected Return: The updated dog and all their old and new information.
PUT - api/kennels/:kennel_id Expected Return: Updated kennel with all it's previous and new information.
DELETE - api/kennels/:kennel_id Expected Return: A 0 that confirms the kennels been removed.

Wrap up

This is awesome you guys! We’ve got our plan and we are ready to execute. Next time I swear we’ll be doing nothing but coding… well maybe a little theory, but for the most part, it will be us, HTTP requests, SQL methods, and our database.

--

--

Matt Basile

Full Stack Developer sharing updates of his journey through Lambda School’s course. Check-in for a recap of core concepts and how-to guides.