Walkthrough of TinyHouse Code
We'll spend a few minutes walking through the complete TinyHouse code for Part II of the course to gather context on some of the patterns we'll follow.
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
Lesson Transcript
[00:00 - 00:55] Hey folks, welcome. In this lesson, we're going to do something a little interesting. And we're going to actually walk through the finished code application for the client and server projects for part two of the course. The reason being is we're going to simply talk and address about the patterns we're going to follow, some of the folder and file structuring we're going to employ, and sort of just a high level perspective in how we're going to structure our code base. Now, I do want to reiterate that this doesn't mean we're going to learn about what we're going to do in this certain lesson. This is a very short lesson in which we talk about the high level planning of how we expected the server and client projects to be established. Now, with that said, and since we're coming from part one of the course, this might be evidence. But we're going to build the tiny house application through an API driven approach, which basically means that we're going to develop an interface.
[00:56 - 02:14] In other words, a graph QL API that exposes the server data and business logic. Our client, which is our web application is going to interact with this API to query or persist data. And this API driven development model helps split the backend and front end code, which further helps the capability if we wanted to to build multiple front end clients to interact with the same API. With that said, let's begin by surveying the server project. The server project is going to be a node express server, where its responsibility is to serve a gradual API and interact with our Mongo database to either query or persist data. The source directory is essentially where we write 99% of our actual source code. The database directory within the source folder is where we make the connection from our node application to the actual Mongo database we have in our Mongo Atlas instance. In our actual Mongo database, we 're going to have three collections for part two of the course, we're going to have a collection to essentially collect all information of the users in our application. We're going to have a collection to collect all information for the listings in our application.
[02:15 - 04:47] And we'll have a collection to collect all information for the bookings that have been made for the listings. The graph QL folder within the source directory is where we establish and create the functionality of our graph QL API. Now, if we recall from part one, we've mentioned that graph QL API is usually consists of two things. They consist of the type definitions of the actual API and the functions or in other words, the resolver functions responsible in resolving the fields of this API. We're going to have the type definitions of our entire graph QL API kept within a single type definition string. And our root query object and our root mutation object will essentially summarize all the high level fields that can be interacted with from the client. From the query standpoint, the client will be able to query for an authentication URL, a user, a listing, and a collection of listings. And from a mutation standpoint, the client will be able to conduct the login mutation, the logout mutation to mutations responsible for connecting or disconnecting with Stripe, a mutation to host a listing and another mutation to create a booking. Now, remember, these are the roots level fields. These are the only fields in which the client can interact with. In each of these fields, they often either return a graph QL type like a string or they return a custom object type we define in our type definitions, whether it's a user, a listing, a viewer, etc. And for each of these custom object types, there are additional fields where we'll also develop resolver functions for like within the user object, there will be a bookings field, listings field, etc, etc. When it comes to creating the resolver functions for all the fields in our API, we're going to follow a format we've learned in part one in how we're actually going to group and create these resolvers. There 's going to be a root level resolvers object that's going to be a collection of the merge of the different resolver maps we're going to create in our API. We're going to separate all the resolvers based on the domain that they involve in. So if a particular function is within the domain of a user, we're going to have a user resolvers map to contain that function. And this is likewise for three other domains as well, the viewer, the listing and the booking. And each of these resolver maps are going to be constructed within a file of their own.
[04:48 - 06:14] And each of these maps will have the resolver functions that pertain to the root level, query or mutation root objects, or the specific fields within the object type that pertain to the map. So the booking object, the listing object, a user object, etc. quick pause. Notice that we're not talking about how we're building each of these in detail. Once again, this lesson doesn't serve that purpose. We're going to be building all of this everything we see here throughout the course and through hours of content. This lesson is just basically a very high level summary of how we're structuring our server and client projects . Outside of the GraphQL directory in our source folder, there is a lib directory that would contain functionality in which multiple parts of our app, whether it's the GraphQL res olvers area or our database file can interact with. More importantly, is the API folder within the lib directory that consolidates all the functionality that we have to interact with third party APIs. There's going to be three third party APIs we're going to interact with in our server projects. There's going to be the Cloudinary API. There's going to be the Google Services API. And there's going to be the Stripe API. The Cloudinary API would be used primarily to help upload images that users provide to the Cloudinary dashboard.
[06:15 - 09:26] The Google API we interact with would allow us to interact with Google's people services as well as their Google Maps services for their geocoding capabilities. And the Stripe API is essentially the interaction with the third party payment provider Stripe to connect users and allow them to actually have payments received to them if they create listings within the tiny house application. Outside of this API section within the lib folder is the utils section that contains any functionality or functions where we'll need to have this run in multiple parts of our server project. And there's the shared types file that is to contain all the TypeScript typings that can be used in many different parts of our server projects. Outside of the source directory is the temp folder where we've seen in part one of the course, there's a seed function where we essentially seed our Mongo database with fake mock data. And part two will have a clear function that also gives us the ability to clear the database if we ever need to. And with that being said, that's essentially the high level walkthrough of our server projects. Other than that, there's the environment configuration file where we'll keep all our environment specific variables and any of the tooling associated with ESLint or the TS configuration with which we've seen in part one. Now let's move over to the client project. The client project is a react TypeScript project where we build a single page application. In the root source index file is where we instantiate our Apollo client to interact with the GraphQL API and where we construct the highest level app component that is essentially going to be rendered as our react application . In this parent app component is where we're going to use react router, which is a third party library to create client side routes. And the routes we construct would essentially render different components based on the path the user visits. In the index path, they 'll see a home component. In the host path, they'll see the host component and so forth and so on. Where do we define these section high level page components? We're going to define them within a sections directory that's going to group all the page level components that can be interacted with from our application. Each of these section high level components will contain information that pertain to that section. They'll contain the index file where we actually construct the component and they'll contain any assets that are sorted to them as well as any child components that they depend on. And the structure for all these directories within the sections folder resemble very similar to one another. They're just the parent page level components that get rendered for a certain route that would have more information within themselves like the child components or assets and so on. Outside of this sections directory is going to be a lib directory in which multiple parts of our app or our client app, the multiple parts of our sections can interact and use.
[09:27 - 11:30] For example, there is the shared components directory here that groups all the components that can be shared between multiple different sections. And there's going to be all the GraphQL documents that can be retrieved and interacted within each of our sections. The mutation documents, the query documents and the global types file that the Apollo CLI generates based on our GraphQL API. If we have any custom hooks we'll create, we'll group them here as well. And we'll have a utilities index file that groups all the functions that can be shared in multiple parts of our app. And last but not least, there will also be a types file where we intend to have to keep any typings that can be shared in multiple different sections. There is a styles directory that's going to be provided to you actually at some point in the course in which is going to have a single index CSS file. And the reason being is when we build part two of the course, we're not going to write any custom CSS. We're actually going to reference some of the custom CSS we've already prepared for you. This is going to be used in conjunction with the third party library that we import and use in our application known as ant design. The ant design UI framework would hold the majority of what we intend to actually build from a UI perspective. So when it comes to actually building elements in our client application, whether it's a button or a list or an avatar section , etc, we're going to leverage the ant design UI framework as much as we can. And we 're going to reference all the capabilities with it and introduce custom styling for ourselves whenever needed. There's going to be another lesson in this introduction module that's going to talk about the some more and the lesson will be titled how to go through the course. Outside of the source directory of our client application is with the majority of the things we've seen in part one of the course is where we have the public directory that contains the root markup page in which our client app is going to be mounted on top of.
[11:31 - 12:15] There's going to be the package JSON file for all the application dependencies, the auto generated schema from the Apollo CLI tool, and the TypeScript configuration that creates react app scaffolds for us. We'll also have an environment configuration file introduced in the client at a later point in the course. Now this is by all means not a detailed summary of either the client or the server projects, though we've talked about a few things, there's a lot of things we didn't talk about as well. And we're going to dive deep into each of these topics as we proceed throughout part two of the course. In the next lesson, we're going to take a very brief tangent. And we're going to talk about patterns we employ as we build the server and client projects.
[00:00 - 00:55] Hey folks, welcome. In this lesson, we're going to do something a little interesting. And we're going to actually walk through the finished code application for the client and server projects for part two of the course. The reason being is we're going to simply talk and address about the patterns we're going to follow, some of the folder and file structuring we're going to employ, and sort of just a high level perspective in how we're going to structure our code base. Now, I do want to reiterate that this doesn't mean we're going to learn about what we're going to do in this certain lesson. This is a very short lesson in which we talk about the high level planning of how we expected the server and client projects to be established. Now, with that said, and since we're coming from part one of the course, this might be evidence. But we're going to build the tiny house application through an API driven approach, which basically means that we're going to develop an interface.
[00:56 - 02:14] In other words, a graph QL API that exposes the server data and business logic. Our client, which is our web application is going to interact with this API to query or persist data. And this API driven development model helps split the backend and front end code, which further helps the capability if we wanted to to build multiple front end clients to interact with the same API. With that said, let's begin by surveying the server project. The server project is going to be a node express server, where its responsibility is to serve a gradual API and interact with our Mongo database to either query or persist data. The source directory is essentially where we write 99% of our actual source code. The database directory within the source folder is where we make the connection from our node application to the actual Mongo database we have in our Mongo Atlas instance. In our actual Mongo database, we 're going to have three collections for part two of the course, we're going to have a collection to essentially collect all information of the users in our application. We're going to have a collection to collect all information for the listings in our application.
[02:15 - 04:47] And we'll have a collection to collect all information for the bookings that have been made for the listings. The graph QL folder within the source directory is where we establish and create the functionality of our graph QL API. Now, if we recall from part one, we've mentioned that graph QL API is usually consists of two things. They consist of the type definitions of the actual API and the functions or in other words, the resolver functions responsible in resolving the fields of this API. We're going to have the type definitions of our entire graph QL API kept within a single type definition string. And our root query object and our root mutation object will essentially summarize all the high level fields that can be interacted with from the client. From the query standpoint, the client will be able to query for an authentication URL, a user, a listing, and a collection of listings. And from a mutation standpoint, the client will be able to conduct the login mutation, the logout mutation to mutations responsible for connecting or disconnecting with Stripe, a mutation to host a listing and another mutation to create a booking. Now, remember, these are the roots level fields. These are the only fields in which the client can interact with. In each of these fields, they often either return a graph QL type like a string or they return a custom object type we define in our type definitions, whether it's a user, a listing, a viewer, etc. And for each of these custom object types, there are additional fields where we'll also develop resolver functions for like within the user object, there will be a bookings field, listings field, etc, etc. When it comes to creating the resolver functions for all the fields in our API, we're going to follow a format we've learned in part one in how we're actually going to group and create these resolvers. There 's going to be a root level resolvers object that's going to be a collection of the merge of the different resolver maps we're going to create in our API. We're going to separate all the resolvers based on the domain that they involve in. So if a particular function is within the domain of a user, we're going to have a user resolvers map to contain that function. And this is likewise for three other domains as well, the viewer, the listing and the booking. And each of these resolver maps are going to be constructed within a file of their own.
[04:48 - 06:14] And each of these maps will have the resolver functions that pertain to the root level, query or mutation root objects, or the specific fields within the object type that pertain to the map. So the booking object, the listing object, a user object, etc. quick pause. Notice that we're not talking about how we're building each of these in detail. Once again, this lesson doesn't serve that purpose. We're going to be building all of this everything we see here throughout the course and through hours of content. This lesson is just basically a very high level summary of how we're structuring our server and client projects . Outside of the GraphQL directory in our source folder, there is a lib directory that would contain functionality in which multiple parts of our app, whether it's the GraphQL res olvers area or our database file can interact with. More importantly, is the API folder within the lib directory that consolidates all the functionality that we have to interact with third party APIs. There's going to be three third party APIs we're going to interact with in our server projects. There's going to be the Cloudinary API. There's going to be the Google Services API. And there's going to be the Stripe API. The Cloudinary API would be used primarily to help upload images that users provide to the Cloudinary dashboard.
[06:15 - 09:26] The Google API we interact with would allow us to interact with Google's people services as well as their Google Maps services for their geocoding capabilities. And the Stripe API is essentially the interaction with the third party payment provider Stripe to connect users and allow them to actually have payments received to them if they create listings within the tiny house application. Outside of this API section within the lib folder is the utils section that contains any functionality or functions where we'll need to have this run in multiple parts of our server project. And there's the shared types file that is to contain all the TypeScript typings that can be used in many different parts of our server projects. Outside of the source directory is the temp folder where we've seen in part one of the course, there's a seed function where we essentially seed our Mongo database with fake mock data. And part two will have a clear function that also gives us the ability to clear the database if we ever need to. And with that being said, that's essentially the high level walkthrough of our server projects. Other than that, there's the environment configuration file where we'll keep all our environment specific variables and any of the tooling associated with ESLint or the TS configuration with which we've seen in part one. Now let's move over to the client project. The client project is a react TypeScript project where we build a single page application. In the root source index file is where we instantiate our Apollo client to interact with the GraphQL API and where we construct the highest level app component that is essentially going to be rendered as our react application . In this parent app component is where we're going to use react router, which is a third party library to create client side routes. And the routes we construct would essentially render different components based on the path the user visits. In the index path, they 'll see a home component. In the host path, they'll see the host component and so forth and so on. Where do we define these section high level page components? We're going to define them within a sections directory that's going to group all the page level components that can be interacted with from our application. Each of these section high level components will contain information that pertain to that section. They'll contain the index file where we actually construct the component and they'll contain any assets that are sorted to them as well as any child components that they depend on. And the structure for all these directories within the sections folder resemble very similar to one another. They're just the parent page level components that get rendered for a certain route that would have more information within themselves like the child components or assets and so on. Outside of this sections directory is going to be a lib directory in which multiple parts of our app or our client app, the multiple parts of our sections can interact and use.
[09:27 - 11:30] For example, there is the shared components directory here that groups all the components that can be shared between multiple different sections. And there's going to be all the GraphQL documents that can be retrieved and interacted within each of our sections. The mutation documents, the query documents and the global types file that the Apollo CLI generates based on our GraphQL API. If we have any custom hooks we'll create, we'll group them here as well. And we'll have a utilities index file that groups all the functions that can be shared in multiple parts of our app. And last but not least, there will also be a types file where we intend to have to keep any typings that can be shared in multiple different sections. There is a styles directory that's going to be provided to you actually at some point in the course in which is going to have a single index CSS file. And the reason being is when we build part two of the course, we're not going to write any custom CSS. We're actually going to reference some of the custom CSS we've already prepared for you. This is going to be used in conjunction with the third party library that we import and use in our application known as ant design. The ant design UI framework would hold the majority of what we intend to actually build from a UI perspective. So when it comes to actually building elements in our client application, whether it's a button or a list or an avatar section , etc, we're going to leverage the ant design UI framework as much as we can. And we 're going to reference all the capabilities with it and introduce custom styling for ourselves whenever needed. There's going to be another lesson in this introduction module that's going to talk about the some more and the lesson will be titled how to go through the course. Outside of the source directory of our client application is with the majority of the things we've seen in part one of the course is where we have the public directory that contains the root markup page in which our client app is going to be mounted on top of.
[11:31 - 12:15] There's going to be the package JSON file for all the application dependencies, the auto generated schema from the Apollo CLI tool, and the TypeScript configuration that creates react app scaffolds for us. We'll also have an environment configuration file introduced in the client at a later point in the course. Now this is by all means not a detailed summary of either the client or the server projects, though we've talked about a few things, there's a lot of things we didn't talk about as well. And we're going to dive deep into each of these topics as we proceed throughout part two of the course. In the next lesson, we're going to take a very brief tangent. And we're going to talk about patterns we employ as we build the server and client projects.