
Let me walk you through the final project that we will be building throughout this course.
Here are all of the lesson files that you will need to get this project completed.
Having a strong foundation is always important for every project. In this first step, we will install Laravel and pull in the 1st party package Passport to handle API authentication on our application.
We will need two layers of routing in our application. The backend routing will simply consist of auth routes and a single app entry point. Then, we'll use Vue-Router to handle the rest of our application routing needs. In this lesson, we install Vue and Vue Router and start scaffolding our application's routing layer.
Tailwind CSS is a utility CSS framework. Unlike many of the other pre-built CSS libraries, Tailwind differs in that it gives you the building materials for your application and customizable design guidelines. These design guidelines give your application a polished look without much extra work. Let's bring that in and wire it into our Laravel application.
If you’ve ever argued with your team about the way your JSON responses should be formatted, JSON:API can be your anti-bikeshedding tool.
By following shared conventions, you can increase productivity, take advantage of generalized tooling, and focus on what matters: your application.
For the first stab at introducing posts to our application, let's work together on a 1st draft test and get it to green. You will be able to follow along as we follow each test error until the test starts to pass. TDD is an integral part of modern application development and will be an integral part of this course.
With our test in a green state, let's take it to the next level by introducing the response side of our JSON:API specification. We will be working through all of the test errors until we end up with a passing test. This will represent the basic arrival post state of our application.
Let's make use of Laravel's Resources features to refactor our code into a reusable formatter response. At the same time, we will add information about the user that created the post.
Let's retrieve some posts, though we don't have any idea of friends in our social network, let's at least retrieve all of the user's posts. This will require us to follow the API convention and reuse our resource but in Collection style. Follow along as we reuse all of our resource code.
If you recall, we are simply displaying all posts in the database whenever someone requests all of the posts. Let's write a new test to make sure that the only posts returned, are the ones that belong to the user. Next, let's create a global query scope to make sure that posts always get returned in reverse order as expected by the user.
I've included the final design files from all of the following videos. Download the files and put them in the correct places in your app.
Let's take some time to get the basic structure of our app in place.
The top navigation section of the new Facebook design, entails 3 distinct groupings with svg icons, search bar and special styling for active links.
The content section includes a sidebar on the left and a scrollable content area on the right. Let's make sure we get proper scrolling and sidebar.
Let's work on the NewsFeed content area and the component that will be in charge of posting new things to the user's news feed.
Each post will consist of a user, an optional image, a caption and a like/comment button. Let's create that now.
With our newly designed views, let's start fetching posts from our database. But first, let's make sure that our database has the correct table and posts to show.
Let's add a new field to our resource for showing how long it has been since the post was created using Carbon's diffForHumans() helper. Next, let's add a column to our post table to store an image link.
As we have already learned, Axios performs a request and returns a Promise. A Promise is only resolved once the request has been completed so we need to keep track Promise's state. Let's add a piece of data to our component to keep track of it and then use it to display proper messages to the user.
Introducing the concept of user profiles to our application requires that we have a way of fetching a user's information. Let's add a new route and controller to handle user profiles. As we have done before, let's start with a test.
With our new route under test, let's start fetching it in the front end and spike a quick design for it.
As we always do, let's start with a test. Along the way, we will create the necessary nested route to our api.php file to tackle grabbing a specific user's posts.
With the ability to fetch a specific user's posts, we can now shift our attention to displaying it properly on the user's profile component. Follow along as we style and design the user's profile.
Before we can begin this section, we need a way of retrieving the currently authenticated user's information. Let's write a test that drives us to create the necessary end point and logic to return the currently authenticated user.
Now that we are able to get the user's information, let's use that to finally get the navigation link to route the user to their profile. We will refactor this in the next lesson but for now this simple implementation will do the trick.
Let's cover the basics for setting up a Vuex store that fetches the user's information on page load. This will allow us to have shared information about the authenticated user throughout our application.
Now that we have Vuex working, let's create a new module to handle page titles and then use Vue Router to dictate when it should swap out our document's title.
In this first test, we will tackle the happy path of creating two users and one of them sending a friend request to another. To do this, we will need to properly set the column names to be able to associate a user to another user within the same table.
What happens when a user is not a valid user id? Well, right now, our app crashes! Let's fix that with a proper JSON response to the JSONAPI specification.
An old saying says that "it takes two to Tango" and that is true whenever a user friend requests another user. We need have the ability for the second user to accept that new friend. In this lesson, we implement the endpoint to accept friend requests.
An important thing to consider when writing APIs is to make sure that you think of every possible scenario where a user can make your app act in ways that you didn't intend. We currently have two cases we need to handle, first is the one where a user accepts a friend request that doesn't exist and the second is where a user tries to accept a friend request that doesn't belong to them.
Let's tackle validation without breaking the awesome built-in Laravel validation methods. We'll do 3 rounds of refactors until we arrive at the final solution that involves us taking care of validation for the entire application.
When a user visits another user's profile, we need to attach the friendship status to that user to properly display the friend request button. In this episode, we go through the steps necessary to account for that by using the reusing the resource.
In a previous episode, we installed Vuex and started using it in the navigation component. In this episode, let's move the user fetching code from the UserShow component, into a new Vuex module in preparation for adding the Add Friend button.
The Add Friend button will take several different roles depending on the authenticated user's friendship with the current user. Let's tackle hooking up our button to our Vuex store.
Let's refactor our action to set the text on the button to a computed property so we can take advantage of Vue's reactivity, Then we'll clean some small lose ends and get ready to tackle accepting and ignoring friend requests.
This is the lesson that we have been working towards for a long time. We finally get to accept or ignore friend requests and go through the whole flow through the browser. Settle in, we have arrived.
We have one remaining refactor in the Show component and that is the way that we fetch the user's posts. Let's refactor that code to use Vuex instead. Then, we will take a look at the console errors and get those fixed using the statuses that we have been setting along the way.
We have two bugs in our application right now. The first is that a user can keep hitting the friend request button and adding records to the database. The second, is that we show the friend requests buttons even on our own profile. Let's fix both of those, in this episode.
We need to move the logic for fetching posts from the newsfeed component to a new Vuex store and then start the process of adding a button to submit a new post to our app.
Let's take all of the necessary steps to complete a text post to our app. Then, let's add a nice fade transition to the post button for that extra cool detail and let's also make sure that we don't create a ton of unnecessary updates with Lodash and debouncing.
Up next in our features, we need to add the functionality to "like" a post. As we've been doing, let's start with a feature test to get the backend properly storing and associating likes to posts and users. This will take the shape of a many-to-many relationship and a couple of resources. Let's dive in.
With our functionality to toggle likes in place, let's shift our focus to returning these new likes with each post. The approach here is to not have to fetch the likes separately from our posts but rather, have a unified post and likes resource to achieve this.
Now that posts can be liked, let's shift the attention to the front end code. Vue is a data-driven JS framework and this episode fully illustrates that. Being able to change our data and have the views re-render automatically is very powerful. In this lesson, we implement the ability to like a post.
For a first test, let's create the endpoint, controller and model necessary to have the concept of comments in our application. Once we get that to green, an authenticated user will be able to submit their comments for a particular post.
Let's secure our endpoint with some validation as well as making sure that all posts now return with comments.
Let's start off easy and display the proper count of comments on each post. Then, let's dial it up and start to iterate through any comments a post may have.
In this lesson, we are hooking up Vuex to our post comment submit sequence.
Refactoring needs to be a normal part of any project. In this lesson, we refactor two of our modules to eliminate any cross and duplication with the newsfeed and profile logic.
Our application will have a concept of User Images. This will represent any content that the user uploads. Our implementation will need to keep record of all of the images a user has uploaded into our application but it all start with the basic "a user can upload an image" test.
When fetching the user, we should expect to get the profile image resource as well as the cover image resource. Let's cover that with a test in this lesson.
Dropzone is a great library we can pull it to facilitate uploading a single image into our application using the backend code that we already wrote in the previous two episodes. Let's pull that in and get it setup in our UploadableImage component.
After an user updates their images, we need a way of updating that on our component. For a first stab at this, let's use a computed property that will check if there's an uploaded image and if there isn't, it defaults to the user image that was passed through to us from the Show.vue component.
When a user first creates their account, our application has no images for their profile and this can break our UI. Instead, let's use Laravel's model defaults to set a sensible default image that a user can then just update when they are ready.
Let's make sure that all of the images are properly displayed and reloaded when they are updated. Then, let's add the finishing touches to our UploadableImage component and make sure that it only displays for the authenticated user.
Using the Intervention Image package, we can easily resize the images on upload and make sure that we don't save huge images onto our server. Let's take care of that, in this episode.
Building modern applications requires a specialized toolbox of skills and tools. We are going to be using Facebook as an example to build a social network platform from scratch. We will be using modern development techniques that mimic real-world team flow along with some added tooling to help aid with that.
Why did we choose this as the sample project?
Most students that take this course will know or at least have an understanding of Facebook. Instead of spending time trying to explain what our project needs to do and what the expected functionality needs to be, we can jump straight into writing code. This helps facilitate the comprehension of the new concepts we are introducing.
What if I am not sure that I have the skills necessary?
This course is what would be considered an intermediate level course but with basic knowledge of PHP & Javascript even the most beginner will be able to acquire new skills and level up their skills. Working knowledge of Laravel & Vue will increase your chances of grasping every concept. But all and all, every lesson goes into great detail about the "why" we are doing what we are doing.
Will there be boring slides?
Absolutely not! Every video will be engaging, throughly explained and straight to the point. Showing you every nook and cranny of Test-Driven Development using Laravel, Vue, Vue Router & Tailwind CSS.