Chat Site - Reddit Clone

Turbo 360

This series is a great introduction to Node JS with a full stack web development focus. We will create a basic chat website similar to Reddit where users can enter various chat room ("subs" in Reddit lingo) and post comments and replies. We will begin with a backend REST API for delivering data as well as creating/updating data. Then we will move on to user registration & authentication, creating rooms ("subs"), posting comments, and replies to existing posts.
- DOWNLOAD THEME - Gulpfile GIST - Slugify GIST
Key technical areas will include: - Node JS & Express - REST API - Templating with Mustache - Bootstrap - jQuery and AJAX - User Registration & Authentication - Image Uploading
WHO This workshop is well suited for those who have basic HTML/CSS experience but are not completely comfortable in a full stack environment. The course is part of the Intro to Development track on Turbo 360 which is focused on beginners with little to no experience. This track is a great intro to Node JS and full stack web development in general. To register, complete the form on the left sidebar.


REST API

Getting Started - 1:14
We start by installing the Turbo CLI and creating a new project. Then, we install dependencies and demonstrate how to connect the project to a Turbo account. We also test on both the local and staging environments.

Description of the Application - 5:05
We explain the structure of Reddit’s platform and how we will emulate it in our project. Rooms relate to subs, topics relate to original posts, and replies relate to comments. We will also create users. During this portion, we also go over the structure of our Node/Express project.

Registration Form - 10:50
We start by removing unnecessary code and cleaning up what we have. We modify our Mustache template file to add a form that will allow users to sign up on our application.

Adding an Auth Route - 14:46
We create an auth route which will handle user authentication including registration, login, logout, and session management. We also demonstrate how to connect this file to the rest of the app, and show how to properly test the new route.

Creating a User - 19:07
We use the Turbo Datastore to easily create users for our project. We also explain how to work with Promise chains and ensure that our authentication code is working.

User Login - 24:58
Now we modify our front end code to display one form for registration and another form for login. We create another handler for login, and demonstrate how to use the Turbo SDK to handle login. We test our login function by submitting a user that doesn’t exist, a user that does exist with an incorrect password, and a user that does exist with the correct password.

Session Management - 31:14
We want to maintain session state when a user logs in, so we create a new route that will return the current user. We use Turbo’s built in Vertex Sessions to keep track of our current user as soon as they log in. Then, we demonstrate how to fetch a user from our Turbo project to return the full data associated with the user.

Logging Out - 40:23
We create one more GET route for logging out. This is done by resetting the Vertex Session. We test by logging out and checking the current user to ensure it is null.

Template for Rooms - 45:58
We create a new Mustache template which will be used for showing our rooms on the front end. We create another route that connects our new template. Finally, we add a form to our template which will allow a user to create a new room.

Adding Rooms to the Datastore - 50:01
We use our API route to handle the creation of new rooms. We point our form to the new POST route we created, and demonstrate how to persist data to the Turbo Datastore. We also check the Turbo Datastore directly to ensure that our data is being persisted correctly. Finally, we add a check to ensure that the user is posting a valid resource.

Getting Rooms from the Datastore - 59:46
We create a generic GET handler in our API route which fetches data from the Datastore depending on the specified resource. In this case our resource is rooms. Then, we add a handler to get data based on a given ID, which is part of the request parameters.

Template for a Single Room - 1:06:53
Since we already have a template to show all of our rooms, we need to create a template that will show a single room and allow users to create topics for that room. This template will render a list of topics for that specific room. We also create a new route which allows us to render this template on the front end of our application. Finally, we show how to apply this to a specific room by using the ID of the room.

Deploying the Project - 1:16:24
We finish this part of the series by deploying our project to the Turbo staging environment and doing some testing. We ensure that all of our functions and API endpoints are working.

Theme Integration and Asset Optimization

Recap - 0:00
We start by recapping everything we created in the previous part of the series. We implemented user authentication as well as rooms and topics. We also test all of these aspects of the project to ensure they are working properly and demonstrate functionality.

Using a Theme - 2:39
We download the theme for this tutorial from Turbo’s website and explore the theme’s files. We also see what the theme looks like and decide how to best utilize it for our project. Then, we move all of the assets from the theme into the public directory for our own project.

Integrating the Theme - 7:18
We remove the code from our index Mustache template and copy over the code from our theme’s index HTML file. Then, we make sure to include the assets in our Mustache templates.

Separating Into Partials - 12:02
First, we create two partials for our assets - one for the head which contains stylesheets, and one for our JavaScript imports. Then, we separate a few different elements from our HTML code into other partials. This helps to declutter our code and prevent repetition across multiple pages.

Optimizing with Gulp - 17:26
Now, we show how to optimize our static assets using Gulp. We start by downloading and installing Gulp modules. Then, we create a gulpfile. This file will allow us to concat and minify our CSS and JS files for optimized delivery. After running our gulp tasks, we are left with a single CSS file and a single JS file. We make sure to import these two files in our head and imports partials instead of the many files we started with. Finally, we create a single gulp task that will run all of our previous tasks for us and create an NPM build script that will clean the project and run our gulp tasks.

Testing - 47:48
After running our build script, we run Turbo’s devserver and check our local project to make sure everything is working as expected. Then, we deploy to our staging environment and make sure it works there as well.

Using the Turbo CDN - 49:30
We want to deliver our static assets using Turbo’s CDN. On the staging environment, Turbo does this automatically. However, on the local environment and on other hosting services, this is not done automatically. We copy the link for the project-specific CDN and change all of our imports to reference the CDN directly. Finally, we add the link to the CDN as an environment variable. This is good practice because it avoids the need to hardcode the CDN link all over our project.

Finishing up - 56:39
To finish up this part of the series, we test on both the local and staging environments again. Now, our project has a new theme integrated and is optimized for delivering assets efficiently.

User Login and Main UI

Introduction - 0:00
We begin by reviewing everything we’ve done so far, as well as running the devserver to ensure everything works as expected. Then, we decide which theme page we want to use to show the posts on our application.

Checking Imports - 1:33
We must ensure that all of our imports for this page match up with the imports used in the theme. Since we are missing a few, we create a new gulp task to fix this and run our build script once again. Then, we paste the HTML code from the theme page into our index.mustache file, and make sure all of the imports are working correctly.

Partials - 17:20
We remove the code for our sidebar and include the partial instead. Then, we do the same for our topbar.

Cleaning Up - 19:19
At this point, we need to change the code we copied over from our theme to dynamically render our application’s data, so we begin by removing unnecessary and repetitive code in our Mustache files.

Posts Table - 23:02
We simplify our posts data table by removing extra entries. We also change the headers to reflect the data used by our application. Then, we simplify the table by preventing the theme’s jQuery datatable file from running.

Rendering Posts - 35:28
To start rendering our post data dynamically, we first create some sample data directly in our route file. Then, we demonstrate how to use Mustache templating to iterate over data and display it on the front end.

More Cleaning Up - 41:05
We remove unnecessary items from our sidebar in an effort to make it cleaner and more manageable. Then, we get rid of the breadcrumbs in our topbar.

Logging In - 43:06
Now, we add a login form to our topbar and add a bit of styling. We point this form to the login post route with front end JavaScript and an AJAX post request. We also include some error checking and alert the user if they enter incorrect credentials.

Rendering the User - 58:28
Since we want our page to look different if someone is logged in, we must check the current user in our index route. If someone is logged in, we pass the current user’s data to our Mustache template. If no one is logged in, we just pass our post data to the template. Then, we demonstrate how to check if someone is logged in within our mustache files. Finally, we connect the logout button to the appropriate route.

Finishing Up 1:04:16
To end this part of the series, we deploy our project and test everything that we’ve added on both the local and staging environments.

Creating Chat Rooms

In part 4 of our Node JS Intro - Reddit Clone, we add the ability to create chat rooms by topic then show those rooms on the sidebar when logged in. We also reorganize the architecture to use controllers for all CRUD operations in order to make custom operations easier and maintain modularity in the overall backend code structure.

Creating a New Page - 1:05
We create a link to add a room in the topbar. Then, we use the login page from our theme to create our template for adding rooms. We copy over the code from the theme file into our own project, then fix the imports. Next, we create a route to render this page and add a hyperlink to this route on the front end.

Add Rooms Page - 6:30
We start by changing the content and styling of our new page. Then, we add a jQuery function to handle the submission of our form. This form checks the user input and uses an AJAX request to hit our backend route for adding a room. We also ensure that a user is logged in before reaching this page, and pass the data of this user to our template. This allows us to associate the creator with a new room being created.

Rendering Rooms - 23:14
We add a dropdown menu to display rooms in our sidebar, and then we pass our room data to the front end populate this menu with our rooms. This will allow us to navigate to a specific room.

Creating Controllers - 31:53
In order to separate the logic for different resources, we create a controller for each one. These controllers handle all the CRUD operations for each resource. We use a promise library called Bluebird to handle these operations. Then, we move the database functions over from the API route into the controllers. Finally, we connect the controllers to our API route.

Adding Subscribers - 44:44
Now that our logic is separated into controllers, we can use the Room Controller to add subscribers to a room. The first subscriber is the creator of the room, and we ensure that this is done automatically.

Using the Full User - 47:33
Instead of associating the creator of a room just by the ID, we append the entire user object to the room entry. We take advantage of our Room Controller to add this custom logic.

Fetching Rooms by Subscription - 50:24
When we display a list of rooms, we only want to show the rooms that the current user is described to, so we add this logic to our index route. Finally, we deploy our project and make sure all of our new features are working.

Submitting Posts

In part 5 of our Node JS Intro - Reddit Clone, we set up a dedicated route and template for individual rooms. We then connect the ability to post topics in a room and make sure the data accurately reflects the user who posted the topic as well as the room itself.

Using Slugs - 1:46
We don’t want to expose the database ID to the user, so we create a slug for our rooms. A slug is a human-readable identifier. We use a slugify function to create a slug from a room’s category. We also append a random string of characters to the end of the slug.

Displaying a Single Room - 10:38
We want our room links to show a page containing only the topics for that room. We add a route to render a room page based on the room’s slug. We fetch the specified room and pass the data to our template file. We also fetch the current user and pass the data to our page like we did in Part 3 of this series. Finally, we change the sidebar hyperlinks to point to each individual room based on its slug.

Posting to a Room - 24:06
On our room page, we want to be able to post a new topic. We start by adding input fields for a title and a description and a button to submit the new topic. We use front end JavaScript and an AJAX function to error check and post the new room once the submit button is clicked. We also bind the current user to the topic by ID.

Binding the Topic to a Room - 33:12
In this part of the tutorial, we demonstrate another technique for binding data to a newly created object. Inside our route, we pass in the room data. Then, we create a new front end script that binds the current room to the window. Then, in our click handler, we use this data to bind the topic to the room. Finally, we parse the room data in our Topic Controller to ensure it is valid before persisting to the datastore.

Binding the User as JSON - 41:16
Just like we did earlier in this workshop with projects, we want to bind the entire user object to the newly created topic. We do this by simply copying over some code from the Room Controller into our Topic Controller.

Rendering and Posting Topics

In part 6 of our Node JS Intro - Reddit Clone, we render the topics posted in each room. We then update the page when the user posts another topic by setting up client-side requests for fetching and posting data. We use the Mustache templating engine on the client side to render data dynamically.

Displaying Topics in Rooms - 1:25
When we display a room, we want to show all of the topics that were posted to that room. In our index route, we make a request to get topics based on the ID of the current room. Then, we pass this data to our Mustache template to dynamically render the topics on our room page.

Client Side Mustache - 9:43
In its current state, our project does not show new topics after they are created without first refreshing the page. To fix this, we move our topics query on the client side of the application. We perform an AJAX request the fetch topics based on the current room’s ID. Next, we use the Mustache templating engine on the client side as well. We import mustache from a CDN and change the delimiter to avoid conflicts between client and server. This allows us to create a table row for each topic with the same templating we used originally. Finally, we render the new HTML we created on the client side.

Bypassing Page Refresh - 24:51
Now, we extract the code used to create the rows into its own function. Whenever a new topic is submitted, we push the new topic into the array of topics we already have, and it automatically gets pushed into our data table.

Modifying the UI - 28:44
We switch the positions of our title and topic, and add some inline styling.

Adding in Missing Keys - 30:46
In our Topic Controller, we add a key to keep track of the number of replies to a topic, and set it equal to 0. This ensures that the number of replies will be displayed by default when a new topic is created. We also make sure to render the timestamp so our date field is not empty.

More Client Side Mustache - 34:33
We copy the Mustache CDN import from our room page and paste it into our home page. We also change the delimiters again and reuse the same template from the room page. The only difference for our homepage is that we do not fetch topics based on a specific room - we fetch all topics.

Rooms Sidebar Issue - 38:12
We want the rooms to display in the sidebar dropdown menu on every page, so we fetch all the rooms when rendering a single room page in order to populate this menu.

Finishing up : 40:51
We finish this part of the series by cleaning up some of our code and discussing what’s to come in the next iteration.

Rendering and Posting Replies

Recap & Introduction - 0:00
We begin by discussing what we accomplished in the previous part of this workshop, and set our goals for this part of the workshop. Then, we ensure everything is working as expected.

Minor Fixes - 0:50
We switched Topic and Room in the last video, so we switch the two titles in our table. We also fix the links to individual rooms in our table. We also change the logo so it links to the homepage, and remove the Email dropdown from our sidebar.

Topic Pages - 5:19
We take a look at the Reddit website to get an idea of what we are trying to create next. Then, we create a new view for Topics and decide which page we are going to use from our theme. As we did in earlier parts of this workshop, we ensure that all of our imports match up. Then, we paste the content from our theme into our new view file.

Setting up our Route - 13:17
We create a new route in our index file to render the topic page. We fetch an individual from the Turbo datastore, and perform some error checking. Then, we render the topics page and pass our topic data to the templating engine.

Topic Slugs - 16:04
When we create a new topic, we want to automatically create a slug for it. We copy over our slugify code from our rooms controller and use it in the topics controller. Then, we link to topics based on slugs on both our index page and room page.

Showing the User - 21:57
We start by utilizing our partials and removing unnecessary code. Then, we fetch the user in our route so we can display user information at the top of the Topic page the same way we did in the homepage and Room page.

Rendering Topic Data - 23:56
We start by removing unnecessary code in our Topic view. Then, we display the title and description of the topic. We also add a textarea to allow users to reply to a topic.

Submitting Replies - 35:36
Now, we add front end JavaScript code to allow users to submit a reply to a topic. We add the user’s ID as a hidden field, and use jQuery to handle submission of the reply. We create the reply object and send it to the backend. Then, we move to our Reply controller and parse our data before persisting it.

Membership Options