Real Estate Listing Site

Turbo 360

In this series, we create an actual real estate listing website for a property management company who has agreed to let us share the process in a tutorial series. We use Node / Express / Turbo 360 / to build a mostly static website with some additional dynamic components such as a contact form and a basic data model so that we are not hard-coding all of our data and our client can update the site when needed (i.e. add a listing; change a rent price).


Setting Up

Theme & Front-End Setup 4:20
We review the theme Ryan has chosen and mocked up. We briefly discuss use of themes and how they improve turn-around time while providing a nice, clean basic design that matches client specification.

Setup Codebase - 7:30
We then create the project locally and execute the install command, reviewing CLI tools and NPM packages required to begin the project, including “best practice” use of build tools required to optimize professional projects, like the one we build here. We test the project locally by running the dev server and loading the site on localhost:3000.

Setup Project Overview - 14:40
When a project is created with the Turbo CLI, certain pieces and tools are already in place. We briefly review the project scaffolding in order to familiarize ourselves with the project architecture. Also included are Mustache templating for rendering dynamic data, handling routes within a conventional Node/Express application, and an example of dynamic data rendering.

Home Page Layout - 19:36
We begin coding by setting up the home page layout, briefly reviewing the use of templating concepts like partials and page organization. Then, we begin integrating the theme into Turbo’s out-of-the-box scaffolding, set up a .gitignore file and go over the important decisions developers must make regarding which elements of the theme stay and which will go.

Setup Assets & Style Homepage & Partials - 28:45
Breaking code up into partials is an important and necessary step in modern web development. Here, we explain how and why we’re taking the first step toward a modular code base that’s easy to read, update and develop. With the HTML now set up, we set about integrating the theme’s styles with a basic import of assets which will facilitate later optimization.

Setup Scripts, Test Page/Deploy to Staging & Recap - 41:11
With all our assets imported, we set up scripts which will link our templates and the assets we will serve at the designated routes. Our step-by-step setup verifies the presence of our code base and we know we’re ready for optimization. We then create a Turbo app, then deploy our code to the staging environment and verify that we see exactly what we expect (which should match our local environment!). We then walk through a brief recap of concepts and steps covered in this video so we’re ready to proceed to the next one.

Home Page Layout

Setup Nav Partial 2:40
We look at the theme’s stock HTML with an eye toward reducing >1000 lines into a codebase that is more manageable and focused on client specifications. In this section, we walk through the actual trial-and-error process used in real-world front-end development. We also have another quick look at the list of client specifications from the first video.

Create Homepage Content - 8:59
With our Nav partial ready and reusable on every page, it’s time to focus on some of the site’s content. We discuss potential ideas for the landing page, including a quick pros and cons over different design and technical directions we can go before elaborating on what is best for this specific client, beginning with the background image.

Front-end Troubleshooting - 14:40
An important part of the front-end development process is troubleshooting problems as they arise. Here, a change in the index.mustache template doesn’t appear as expected, so we need to dig in and figure out a solution in real-time. Once that issue is resolved, we can push ahead and get our landing page image implemented. We continue our troubleshooting steps to include use of the Chrome debugger and some inline styles, essential tools in a front-end developer’s toolkit.

Landing Page Style - 21:36
We continue styling out the front page, looking at some of the ways we can efficiently manipulate the landing page to best meet the client’s specifications. We add dynamic marketing text before continuing on to add apartment listings to the bottom of of the page.

Create Partials for Listings - 26:50
From our theme, we again select an HTML page which we will import into our project, then setup and style as before, this time adding a content on current listings per the client’s request. We add images to make it look professional, look at background colors and make other choices, all while keeping the client’s desires and specifications in mind. As with the Nav partial, we clean up unnecessary code to make it clean and modular.

Create Array for Listings - 32:12
Modular front-end code should be follow the D.R.Y (Don’t Repeat Yourself) principle. To this end, we will turn our listings partial into an array by adding an array iterator in our index route file. This is the step that allowed us to eliminate thousands of lines of code in previous sections. Our array will receive data from the server on the back-end, then iterate each into our front-end templates. We then review how we can render key/value pairs in the Mustache templating language. We close by briefly touching on next steps.

Node JS Routing & Persistent Data

Setup Back-end Routing 1:39
The Turbo platform provides an array of out-of-the-box solutions, including the ability to use Express routing and a Mongo-based datastore on the back-end. In the last video, we hard-coded some data into the front-end, this time, we will use the aforementioned Turbo framework solutions to connect the front and back-ends. We demonstrate by creating an “apartments” data object from the ‘/’ route, then review the data management GUI that Turbo provides out-of-the-box.

Asynchronous Routing in TurboExpress - 9:31
We build our first asynchronous route on the back-end of our application using Express routing layered into Turbo’s framework, which provides the datastore. We use an ES6 promise chain, a common, essential pattern for javascript developers to learn and understand to build modern web applications which follow “best-practices” and take advantages of all the capabilities of the Javascript language. Ryan checks the Turbo documentation to confirm the pattern and shows us how to build and troubleshoot this essential architecture by using server logs.

Filtering Data Using Express Request Objects - 16:20
An important part of efficient front-end development is knowing how to render exactly the data you want to show. Here, Ryan shows us how to filter data from our datastore so only the exact listing he wants to show appears. This is how we further customize our applications. We demonstrate how to use the URL to query data utilizing the Express req.params object, another essential concept. We then demonstrate req.query.

Layering in Our Data Model - 27:36
Having developed an understanding of basic routing, we look at the client data we will need to represent. For this, we need to structure the data. This includes touching on foundational database concepts, like ‘Belongs To’ and ‘Has Many’ relationships. We bring it all together by capturing request objects from variables we set in the URL, and then pass it into our back-end data model.

Building Data Object - 34:03
We bring it all together by passing a building address from the URL into a promise chain in the route. Once our data model is fully set up with client data, it will render that building from the datastore, per client request. This, conceptually, is how we will retrieve data from the back-end. We then briefly discuss next steps for the project.

Fetching & Creating Data with One-to-Many Relationships

Create Building Partial - 3:11
Just like we did with the Nav and Listings partials, we’re practicing modularity by creating a reusable partial template that will render with dynamic data, thereby making the same code reusable throughout the application. Once the back-end data is rendering on the front-end, we’re able to look at different styling options. Small adjustments to the HTML make our code clickable to improve user experience.

Hyperlinking Text to Create Workflow - 9:31
At this point, we’re really ready to bring everything together. We can build hyperlinks into our templates by taking advantage of routes we built on the Express framework, pull, or get, dynamic data from our Turbo back-end, and navigate between templates to create a user experience. We briefly discuss best practices for creating URL’s which optimize SEO (Search Engine Optimization), including slug creation.

Create & Use Building Slugs - 16:45
Slugs are names in URL’s. Use of words and names, as opposed to symbols or randomized strings, in URL’s improves SEO and improve user experience since they provide an additional source of human readable information, so should be used whenever possible and appropriate. We build a route in line, and which fits with, our data model.

Creating an HTML Form - 28:21
To this point, we’ve been creating workflow which gets data from the back-end. Now we’re ready to set up a new partial, but this time it will be an HTML form which will allow us to post in data into the database. We build a simple form, using input fields for data entry and action/method properties of the form element. This tells our form to post the data from the template/front-end, as entered by the user which will pass data from the front-end to the back-end via the route which we will construct.

Create Building Route - 38:56
We build a route which will post the data a user enters into the Turbo back-end, using the same Express routing framework we used to pull data from the datastore in previous sections. Again, we’re using Javascript ES6 promise chains to build out the route.

Create Apartments - 47:44
Putting together what we’ve learned about database object relationships, routing and templating, we’re going to add apartments, which belong to an individual building. We add an apartment object that belongs to the building into the get/fetch building promise. We then add some templating to render apartments as an attribute of a particular building using Javascript object dot notation. We then recap quickly, going over how we’ll advance the project in the next video.

Editing Our Data

Project Recap - 0:00
We recap the first four videos of the series and pick up where we’d left off, which was setting up dynamic data rendering from the Turbo back-end, and touching on the ‘belongs-to/has-many’ relationships between data objects. As an example, we trace a building from the slug, then look at the route which takes the slug from the URL and onto a webpage where the building (stored in the Turbo back-end) matching the slug is found.

HTTP Requests - 1:50
There are 4 basic HTTP Methods in a RESTful application (GET, POST, PUT, DELETE). GET performs a simple fetch, POST creates a new data object, PUT updates an object and DELETE will completely remove a data object. Though we touch on the fact that DELETE isn’t always the best practice for removing an object, as updating an object to an empty, or null, value will preserve metadata and auditability in an application.


Styling the Front-End - 3:25
We revisit our theme. We begin by replacing a few data fields we’d put on a form with an apartmentEdit partial, which will allow users to enter data which will flow into our Turbo back-end. We check our datastore to make sure we’re including each of the fields we’ve persisted to our back-end into the form we are creating. Because we’re using the Bootstrap library, we review some basic styling commands in the form. We add a textarea element, then weigh decisions like prepopulating data, and whether that should be a placeholder or prepopulated dynamic data.


Date Available - 14:45
Among the important considerations you’ll have to make in developing a professional app is choosing what ‘Type’ of data you’re storing/rendering within a particular field. Here, we’d like to show the date an apartment becomes available. Currently, it’s just a boolean-like ‘yes/no’ string, where we’d like actually render the true date it becomes available, as that adds the most value for our client. The HTML form only allows either a GET or POST request, so we choose POST knowing that the TurboExpress back-end is actually handling the routing.

Building Post Route - 22:45
We then build the route to match our new form. To do this, we revisit the Turbo docs, which define which objects need to be passed between the back-end to the front-end. We create variables to store the Express req (request) objects, which will take parameters from the query string and request body and make them available for the functions we’ll define within our route promise function, the pattern for which we’ve picked up from the Turbo docs. We test by looking at the Turbo dashboard for our app to verify data persisted as expected.

Working With Static Assets in the Turbo CDN - 29:15
We then begin working with some pictures the client has provided. We demonstrate how to serve those assets using the Turbo CDN, rather than out of our public directory as an optimization. We then take a look at some areas of our theme we can use to go the extra mile for client satisfaction.

Styling the Front-End - 39:39
Again, we’re using a Bootstrap theme, so we’re manipulating the user experience using Bootstrap regular Bootstrap commands. We then take a look at different design options, here manipulating column size. We finish off the CDN workflow by uploading the image and verifying that it’s in the Datastore container by checking the 16 digit string matches. We then do a bit of data cleaning, clearing out some of the incomplete test data we’d entered initially.

Normalizing Data - 50:15
We continue by modifying our route to include a template for future picture uploads. This is an important part of normalizing our data structure so that, in the future, we can allow clients to upload their own images without having to contact you as the contractor. This is an important feature that offers users a lot of extra value. We also see Ryan make a mistake, realize/acknowledge it and correct it in real time, which is an important part of every good developer’s learning curve.

Image Uploading & Retrieval with Turbo

Client Dashboard - 0:00
We begin with a brief recap, before quickly discussing the work we’ll be doing on the client’s dashboard. From https://www.turbo360.co/docs/storage, copy the data callback function, as per the video, into a file called app.js, which you will then link in the scripts partial (created in earlier videos).

Bug from last video - 2:11
Bugs happen, we had one from last video and Ryan shows us how to correct it.

Setting up Scripts - 2:45
An important piece of a modern web project is the configuration of your scriptfiles. These are modularized javascript files linked in your front end which your app loads in sequence (top-to-bottom in a vanilla configuration, like we currently have). Ryan looks through his list and, in real time, realizes he might have a missing dependency, so we troubleshoot it with him. Pay attention to the steps he takes, and particularly, to how he creates a new Turbo project to compare that scaffolded configuration with his project’s as this is a common step. It’s also something to always keep an eye on. The important take-away is that script files listed below others are often dependent on functions and variables which exist or are exported from those modularized javascript files, meaning they will break your app if they are missing from the list (or out of order!). Every beginning developer trips over this, so watch out.

Building Photo Upload button - 7:33
We’re creating a submit button that’ll let us upload our photo. Again, we’re testing and troubleshooting in real time. Ryan demonstrates an important step in this process by setting up a console.log to just confirm that a connection exists. Always replicate this step, it will save you time in the long run. Particularly because, as it turns out, the error message displayed when the connection did not exist pointed directly at the issue. We then have the fix.

Building Photo Upload Workflow - 14:24
To make our project even more useful to our client, we want to visibly associate certain images in our Turbo datastore (which will appear on the client’s dashboard) to particular buildings. We have a unique ID for each building and also for each image, so we want to leverage those properties to further customize our data model, thereby creating an intuitive workflow. It’s a simple programmable solution, we pass in the id variable into our button’s #id field. We pass in the data.result.url into the submit event callback. Again we use the console.log workflow to test. We’ve now created a UserImage model, into which we now pass the apartment ID by binding the event target. If you need to, rewatch this section more than once to make sure you got each step as there were some intricacies.

Data Model Relationships - 25:30
We now have unique id’s for images we’ve “associated” with particular apartment id’s. This allows us to establish and work with relationships within the respective data models. In this case, an apartment “has many” images! We then jump into the routes, where we can leverage this relationship to query the images for a particular entity. We create the query document inside the route using the apt.id object. This will allow us to persist this data through to the back-end, where our app will be able to render these objects when someone navigates to that particular endpoint.

Configure the Promise - 40:54
Remembering that these are async calls in the routes, we need to configure the Promise function so that it returns after loading all the images that we need. We had our rendering outside the promise block, so we fix the issue we were having by moving it inside, but at that correct ‘level’. We do this by using the array.length property and comparing that to our index value. We then troubleshoot a few front-end issues like the light box, which we need to add into our list of scripts.

Membership Options