Build and Deploy a Full Stack MERN AI Image Generation App | Midjourney & DALL-E Clone

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
AI image generation tools such as mid-journey and Dally have taken over social media by creating a wide range of images everything from memes and art to beautiful UI ux designs this technology is changing the way we interact with images and has the potential to revolutionize Industries hi there and welcome to a project video where you'll build and deploy a full stack mern AI image generation app your own and improved version of mid-journey and Dally with modern and minimal design Dynamic image layout a hover effect that showcases a user's prompt to generate each AI image their name and the download button search functionality the ability to create new AI generated images by clicking the surprise me button or entering absolutely any text you can think off sharing your post with the community and much more this open AI myth Journey clone is the best AI image generation app that you can currently find on YouTube after you develop this great app I'll even teach you how to deploy to the Internet so that you can share it with your friends potential employers and put it on your portfolio this video is perfect for you if you want to dive into the trend of developing AI Technologies and learn how to use open ai's apis to your advantage you might be wondering what are the prerequisites for buildings such a fantastic application well this course is entirely beginner friendly you only need a solid understanding of HTML CSS and JavaScript a basic understanding of react node and mongodb can be helpful but that's not a requirement alongside building this application you'll learn how to use the most in-demand Technologies today node.js Express mongodb and react together form the powerful man stack Tailwind the most popular CSS framework nowadays open ai's Dali model a deep learning model that generates images from text input cloudinary a cloud-based image storage service to make our image load speeds fast we're going to start simple and then move to more complex Concepts as we go I'll explain every step of the way if this video reaches 20 000 likes I'm recording more artificial intelligence videos before we start building out our project let's first get the hosting and the domain name for our new site your portfolio or any website you'll create in the future hostinger is my personal recommendation and right now they're offering a crazy deal two bucks and 79 cents a month with a four year plan plus three months extra so I simply needed to show this to you the link with an extra discount is in the description let's click the claim deal button to see if it is really as good as it sounds it seems like we're getting web hosting for about two and a half bucks and we can host 100 websites also receive 100 gigabytes of SSD storage unlimited SSL certificate meaning that we have https security we get a free domain and a free email that is crazy hostinger also has a phenomenal customer support 24 7 as you can see by all of the grade ratings right here on top of all the primary benefits that I just mentioned they also offer a ton of additional features excellent price to Quality ratio high speed servers and absolutely everything you need for our grade AI image Generation website we're going to create an entire social media platform so we want to have a custom domain name so we seem credible for every industry standard application such as the One You're Building in this video we need it to be fast reliable and trustworthy and all the features you're getting with this plan such as a custom domain name email and speed makes all the difference since I've partnered with hostinger they decided to give you an even bigger discount you can find the link and a unique discount code in the description enjoy once you visit the link in the description click claim deal and then add to cart here we have to choose the period of our hosting with a crazy discount going on right now I'll definitely choose 48 months to save the most money and down below you can choose your payment method and then you can enter your coupon code that is Javascript Mastery all caps that's going to give you an even bigger discount after you complete the purchase you'll be redirected to the hostinger's dashboard I'll see you there [Music] and we're back to the hostinger's dashboard as you can see I'm personally using hostinger for all of my company's websites if you purchase premium shared hosting you should see this claim domain button right here so let's go ahead and claim it we can choose our domain ending I'm gonna go with.com and let's go with something like JSM dally this should be available hopefully there we go it is and we can immediately claim it hopefully you can come up with something better for our AI image generation social media platform try to think of a unique and short name let's go ahead and click claim domain of course you can do this at the end of the video as well and just like that our domain is active we can also go back to home and we can start setting up our premium web hosting so that we can easily deploy it at the end of the video you can go to setup start now we can skip this entire process and create an empty website you can choose a domain in this case we're going to go for dally select and finish setup it's as easy as that and in about half a minute hostinger is going to set up everything for us so that at the end of the video you can just come back to the hostinger's dashboard and get your project deployed easily great as you can see it's already done to get started with building our great AI image generation application we're going to start as we always do on JavaScript Mastery and that is from bare Beginnings we'll start by creating a new empty folder on our desktop let's call it something like dally underscore clone and then we can drag and drop it into an empty Visual Studio code window once you're there you can go to view and then terminal we're gonna use Visual Studio code's integrated terminal to create our folder and file structure both for our client and our server side since we're building a full stack marine application so to get started let's right click right here and create a new folder called client or frontend inside of here we're going to generate our entire react file and folder structure by using Veet Veet is a new generation tool that is much faster than regular create react app so you can just go to vjs.dev click get started and then we can see how we can start a new react application that's simply going to be npm create Veet and then add latest back in our Visual Studio code we can CD into client and there we can run npm create Veet at latest and then type dot slash to create it in its current repository and press enter this is going to start a quick questionnaire asking us which framework do we want to work with in this case let's proceed with react we're going to use a JavaScript variant and that's it as you can see the file and folder structure has been generated inside of the client folder the only thing we need to do is run npm install now before we officially run our application there are a couple of things we have to set up I will give you all of the assets that we'll be using throughout building this great project so down below in the description you can find a link to the zipped assets folder now inside of our SRC you can already see some assets we can go ahead and delete that one and then you can unzip that folder from the description and then you can simply paste it right inside of here or you can drag and drop it there we're going to have a download icon a logo and a preview.png just a couple of assets that are going to make the development of our application much easier on top of that I've also prepared another file for you that's going to be inside of a folder called constants there you can create an index.js file and then again down in the description inside of a GitHub gist you can find this array it is an array of 50 different prompts which we're going to use as surprise me prompts right here so that if a user doesn't know what they would like to create we can instantly give them some ideas great now as you can see this doesn't contain any logic simply assets images and constants on top of that there are also some styles that we need to create to make the development simpler so you can delete everything that is inside of the index.css and then down in the description in the GitHub gist you can find the replacement for the index.css file again it's just 23 lines of really simple CSS where we set up things like fonts and Tailwind since we're in the topic of Tailwind let's go ahead and install it Tailwind is a utility first CSS framework that's going to make the style link of our application much simpler using utility classes now we can go to get started then you can click framework guides and then you can choose Veet there we simply need to follow all the steps we have already created our project so we can proceed to step number two and we can run this line back in our code we can go to view and then terminal make sure that you're in the client folder and then simply run npm install Dash D Tailwind CSS post CSS and auto prefixer then we can copy the next line that's going to be MPX Tailwind CSS init P that just created the tailwind.config dot CJs inside of here there are also some predefined theme styles that we have to add in that same GitHub just down in the description you can simply find the replacement for the tailwind.config.c.js and you can paste it over we're simply adding some media queries font families and box Shadows finally we have to add the Tailwind directives to our CSS which we already did inside of our index and then we are ready to run our application to make sure that we install Tailwind CSS correctly let's copy this H1 so if we go into our app we can see that right here we're importing some kind of a logo use State app CSS we don't need any of that so let's simply remove it and let's run rafce this is a function that's going to generate a simple react component if this didn't work for you you most likely don't have the right extensions installed so search for es7 plus react Redux react native Snippets install that extension and then it should work finally replace this div with an H1 that contains some Tailwind class names that way we're gonna know if we installed everything correctly Believe It or Not besides using Tailwind for styling there's only going to be one additional package you'll be using and it's incredibly lightweight so you can open up view terminal and run npm install file Dash saver we're going to use to save the files that we create besides that everything else is going to be created by you every single component every single file and the entirety of the logic to make the AI image generation work with that said to make sure that we have set up our project successfully let's run npm run Dev that's going to open up our app on localhost 5173 and there we go we can see Hello World bolded and underlined now inside of the index.css we were using a specific font called enter but we haven't yet created it so let's go to our index.html and right here above the title we can add a link tag link that's going to have a Rel equal to style sheet it's going to have an href equal to https colon forward slash forward slash rsms.me forward slash enter forward slash enter.css with this we're importing the inter font and also we can change the title to dally 2.0 now if we save this and go back you can see it's looking a bit different with that said we are ready to start developing our great application let's get started by putting our browser and our code editor side by side so that we can see our changes live great now we can close all of our files and we can start focusing on the main point of contact which is going to be our app.jsx first we're going to start with the layout and then we're going to move to functionality inside of our app.jsx we're going to set up the routing for our application and now there was one small lie I told you and that was that the file saver is going to be the only package we'll be using I for a second thought we were using nextgs and that we have routing set up for us by default but unfortunately that is not the case as we're working in react so what we have to do is install react router Dom that's going to be really simple so the only thing we have to do is type npm install react Dash router Dash Dom press enter it got installed in less than a second and we can run npm run Dev to rerun our application great now now we have everything we need to get started with the development the first things we're going to import are going to be browser router also a link a route and routes coming from react Dash router Dash Dom we're going to also import a logo inside of a curly braces coming from dot slash assets and we have to import two different pages we haven't yet created so now might be a good idea to start creating the pages and components that we'll be using throughout the entirety of our application so inside of our source we can create a new folder called pages inside of there we're gonna have two pages we're gonna have a create post.jsx as well as home.jsx inside of both of these Pages we can run rafce to generate a simple functional component there we go now to export both of these pages from the pages folder we can create an index.js file that's going to serve as our export inside of there we can first import home from dot slash home as well as import create post from dot slash create post and then we can simply export them in one object home and create post this is going to allow us to import them in one single line inside of our app.jsx the only thing we have to do is say import home and create post coming from dot slash pages to set up our app we can delete our H1 and wrap everything with a browser router we're using the version 6 of react router Dom the latest and greatest of what it has to offer inside of there we're going to create an HTML5 semantic header tag that's going to have a class name equal to W Dash full for full width Flex justify Dash between items Dash Center BG Dash white on small devices px-8 for padding horizontal usually PX4 padding y4 for top and bottom border Dash bottom or B and then border Dash B Dash inside of square brackets hash E6 EB F4 this is going to be the Border color and you can briefly see it right here now if what I wrote right here seemed like magic that must mean that you're not familiar with Tailwind and that's fully okay Tailwind is fairly new but it has great things to offer so if while you're watching this video some of these Styles and class names seem unfamiliar simply go to tailwindcss.com and do a quick search let's go with PX and if you type PX we can quickly see that that is used for padding there we go so PX is horizontal padding py is vertical padding and if you want to learn more about any other Tailwind property you can just type border Dash b or just the name of the property that I refer and you can quickly see what that is used for wonderful with that said we can get back to the development inside of our header we're going to create a link component this link is going to have a two property pointing to just forward slash that's going to be our home page and inside of there we can render a self-closing image tag that's going to have a source equal to logo an ALT tag equal to logo and also a class name equal to w-28 for width and then object Dash contain if we save that you can see a great open AI logo appear we're using this openai logo since we'll be leveraging their dally machine learning model now below this link we can add another link and this link is going to point to forward slash create Dash post it's going to have a class name equal to font Dash enter and also font medium and BG Dash inside of square brackets hash 6469ff that's going to be for the background but also text Dash White px-4 and py-2 finally we can make it rounded Dash MD and inside of there we can say create that's going to create this great looking button on top right finally below the header we're going to create a main section that main section is going to have a class name on small devices we want to give it a padding of eight usually a padding X of 4 and padding vertical or Y of eight we want to give it a full web so it takes the entire screen and give it a BG not white but a bit gray so that's going to be inside of square brackets hash F9 f a f e and we can give it a Min Dash H dash and now we can use a special property called calc where we can calculate 100 VH meaning the full height minus 73 pixels which is the height of our nav bar and I think we don't need to put spaces right here there we go so now you can see that we have a white nav bar and we have the rest of the content in this light gray color inside of there we want to render our routes inside of the routes we want to render two specific self-closing route components the first one is going to have a path equal to forward slash meaning home page and the element is going to be a self-closing home component the second route is going to also be a self-closing component is going to have a path of forward slash create Dash post and it's going to have an element equal to a self-clausing create post component there we go we can expand our Visual Studio code just to be able to see the code a bit more clearly there we go and then the browser can be as it is great with that said believe it or not our structure of the application is done now we can navigate between create post and also home pages so now we can go into one of our Pages primarily home and we can start developing it right now inside of our home component we're going to import react but also a couple of hooks that's going to be use State as well as use effect hooks then we have to import a couple of components but as of this moment we haven't yet created any components so let's create a new components folder inside of our SRC folder inside of there we can create three different components a card dot jsx component which is going to be used for our images there we can run rafce we can create another one called form field Dot jsx and again run refce inside of there and we can create our loader component loader.jsx instead of this one you don't have to run rafce rather down in the description inside of a GitHub gist you can find that entire loader file you can copy it and then paste it right here as you can see this is simply an SVG file that's going to allow us to have some loading animations finally we need to export all of these components from the components folder by creating a new index.js file there we need to import all of them one by one so let's start with import card from card secondly we can import the form field coming from dot slash form field and then finally we can import the loader coming from that slash loader then we can export everything as one object that contains a card a form field and a loader component that's it as you can see there isn't a lot of pieces of the UI when it comes to this application it is fairly minimalistic but the main focus of this video is teach you how to work with Dali API open ai's image generation API with that said we can close all of our components and go back to our home page inside of which we can now say import that's going to be loader card and form field coming from dot slash components there we go now we can use them in our UI inside of our home we can immediately create two different states that's going to be use State snippet and let's call it loading and set loading at the start loading is going to be set to false like in Iran we'll also have to work with the posts so let's create a new state called all posts set all posts and that's going to be equal to a use State that's going to start with a value of null great now let's focus on the return of our home component first we're going to create a section that section is going to have a class name equal to Max w-7xl so this is going to be a Max width of about 80 Ram and let's also give it a margin X of Auto inside of that section we can create a div that's going to have an H1 inside of it that H1 is going to say the community showcase we can also give it a class name equal to font Dash extra bold text Dash inside of square brackets hash 222328 and we can give it a text-32 pixels like this you can see the Community Showcase now we can also create a paragraph below it that paragraph is going to have a class name equal to margin top 2 mt2 text Dash hash 666 e75 and we can create text-14 pixels to make it just a bit bigger and provide a Max W 500 pixels inside of there we can say something like browse through a collection of imaginative and Visually stunning images generated by dally AI great now we can see that this text is a bit too small so maybe if we go with something like 16 pixels that's looking a bit better below the div containing the H1 and the P tag we can create a new div this div is going to have a class name equal to mt16 for March top to divide it from the text above there we can render a self-closing form field component for now we won't provide any props to it we're going to focus on that later on below that we have to focus on loadings so let's go below this div wrapping the form field and let's create another div this Dev is also going to have a class name equal to Mt but this time 10 to divide it from the top content and inside of there we can open a dynamic block of code we can check if we are loading and in that case we can render a div that div is going to have a class name equal to flex justify Dash Center and items Dash Center inside of there we can render our self-closing loader component now of course we're getting an error because we use the eternity operator that means that we have to provide the or part of the statement as well with a column sign so let's create a new pair of parentheses and let's render an empty react fragment that's going to immediately fix it now if we want to see that loader for now we can simply set the loading to true and there we go you can see how that's going to look like we can bring it back to false and we can continue with our layout if we do have any images to show while displaying images they can be from our search or just generic images so first instead of a dynamic block of code we have to check if we have something in the search text now this is a field that we haven't yet created so quickly scrolling up we can create a new use State snippet called search text set search text and at the start it's going to be set to an empty string now we can say search text and and meaning if there is any search text then we can show an H2 that's going to have a class name equal to font Dash medium text Dash hash 666 e75 that's that grayish color we used before text XL to make it larger and MB of three for margin bottom there inside of that H2 we can say showing results for span that span is going to have a class name equal to text Dash hash 222328 that's that dark color and there we can render search text there we go now as you can see we don't see that because the search text is empty but if we add something like ABC right now we can see showing results for ABC later on we're going to dynamically update this great with that said below our search text we're going to actually render through our images so let's go below this part right here render a div and that div is going to have a class name equal to grid now in most cases I would recommend using CSS flexbox instead of using CSS grid but when you literally have a grid of images as we will have soon that's one of the only times when I would recommend using grid over Flex so yes let's proceed with the Grid on large devices we want to say grid Dash calls Dash 4. meaning four columns on grid but on small devices we want to say grid Dash calls Dash 3 and then on extra small devices we want to set the grid Dash calls Dash 2. finally otherwise we're going to have created Dash calls dash one and the gap between images is going to be three inside of there we want to render our new component which we're going to create on top of our page that component is going to be called render cards so we can say const render cards is equal to that's going to be a generic react functional component and it's going to look like this there we want to accept two different parameters to it the first one is going to be data and the second one is going to be title then we want to check if data question mark dot length is greater than zero in that case we want to return data dot map right here we want to map over each post or image and then we want to return a self-closing card component that card is going to have a key equal to post dot underscore ID and we want to spread out all of the other Post Properties so da da da post just to modify this so you can see it a bit better I'm going to put it in a new line and there we go so if data is greater than zero then we want to map over the data and we want to render all of the cards while passing all of the post data to each individual card otherwise we simply want to return the title so we can say return H2 that's going to be a class name equal to mt-5 for margin top fun Dash bold text Dash hash six four six nine f f text Dash XL and uppercase inside of there we can simply render the title that we pass dynamically into this component through prompts now in just a couple of seconds you'll see the reason why we created this separate functional component primarily for reusability going down right here inside of our div with the grid we can now check if search text exists and if it does we want to render cards and we want to pass the data to it that data is going to be searched results so results corresponding to our image search and if there are no search results we want to provide a title equal to no search results found now if you're not trying to search for something if we are just trying to render all of the posts then we can add an or and we can again render cards self-closing the data that we pass are going to be all posts and the title can be no posts found If there really are no posts now here's the most important thing to figure out this data right now we simply passed it as a string but later on this is going to be an array of actual data so right now it looks like we have an error and I'm guessing it's complaining because we passed a string and it's trying to iterate over the string right here so what we can do is for now we can pass an empty array to both of these pieces of data that's going to look like this there we go no posts found so hopefully now you can see why we decided to create a new render cards functional component so that we can call it two times but pass it two entirely different sets of prompts of course this is going to make more sense once we actually have real data for all posts and real data for searched posts with that said we are entirely done for the representation part of our home page as I told you it's going to be fairly simple but of course the majority of the work actually comes down to creating the logic so what we can do as the next step is move to the create post page Implement all the UI to generate different images and then we're going to move to the backend side of our application where we're going to send the prompt from the front end to the back end and ask the AI to generate it great so we can go back to app we can open up our create post page and we can get started inside of our create post page we're going to use a use State hook later on so let's import it we're going to use the use navigate hook coming from react Dash router Dash Dom we're going to also import an icon called preview coming from assets we're going to also import inside of curly braces get random prompt coming from dot slash utils as you can see right now we're getting an error because utils don't exist but we're going to implement them really soon and then when it comes to the actual layout we're going to import the form field and loader components coming from of course data slash components with that said let's look into what these utils should be so inside of our source folder we can create a new folder called utils inside of the utils we can create a new index.js file utility functions or utils for short is a file where you can create different functions which you can then reuse across your application in our case our utility function is going to be fairly simple we first want to import surprise me prompts coming from dot slash constants if you look into that you can see that this is an array with about 50 different prompts we can generate then we need to create a function by saying export function get random prompt and it's going to accept a prompt as a parameter then we need to get a random index and we're going to get that by using the math.floor function then we want to use the math.random function and we want to multiply that by surprise me prompts dot length essentially we're getting a random index from 1 to 49. then we can retrieve that random prompt right here by saying random prompt go into surprise me prompts and use this random index now we can simply return the random prompt but there's one more tweak or an improvement that we can do and that is to implement a check to make sure that we don't get the same random prompt two times in a row or three that is incredibly unlikely but still we can improve that so we can say if random prompt is triple equal to prompt then we can just recall the get random prompt function great with that said we can now go back in our create post and we now have access to this get random prompt function which just repeat what it does every time that we call it it's going to give us a different random prompt that a user can use to generate the AI image great now inside of our create post we're going to first initialize the cons navigate Hook by saying const navigate is equal to use navigate this is going to allow us to navigate back to the home page once the post is created then we can create a new use State field called form and set form at the start that's going to be an object containing a property of name which is an empty string a property of prompt which is also an empty string and the actual photo right here which is an empty string now we'll also have to manage two different states the first state is going to be a use State and we can call it generating IMG and set the generating IMG at the start that's going to be set to false this is going to be used while we are making contact with our API and while we're waiting to get back the image and the second one is going to be just the general loading so we can say const loading set loading and that's going to be equal to use State false now we have all of the states that we need and we can start creating the UI ux of our application we're going to exchange this div into an HTML5 semantic section tag and give it a class name equal to Max Dash w 7 XL taking 80 Ram of the width and also we're going to give it an MX of Auto inside of there we're going to create a div and within that div we want to do a similar thing we've done inside of our home page so quickly we can jump into the home page and there we can copy this entire first div containing the H1 and the P tag let's paste it right here over this div and we're going to change just a couple of things instead of the Community Showcase we can say create and instead of browse through a collection of imaginative images we can say create imaginative and Visually stunning images through Dali Ai and share them with the community great as you can see now we can differentiate the Showcase page and the create page and we are ready to start creating the form through which we'll be able to generate them so just below this div we can create a form component that form is going to have a class name equal to mt-16 and Max w-3 XL finally we can give it an on submit property that's going to be equal to handle submit this function is going to be ran once we click a submit button now of course we have to create a version of that handled submit function so that's going to be a basic Arrow function for now we can leave it empty inside of that form we can create another div and that Dev is going to have a class name equal to flex Flex Dash call and GAP Dash 5. this is just going to be used to position our form Fields inside of our form so let's create our form fields that's going to be a self-closing form field it's going to have a couple of different properties it's going to have a label name which for the first one it's going to be your name then it's going to have a type which is going to be text it's going to have a name which is going to be name it's going to have a placeholder equal to in this case let's do John Doe since it's a name field it's going to have a value which is going to be equal to form.name and a handle change field which is going to be equal to handle change this handle change is a function that we haven't yet created so let's create it right here below our handle submit const handle change is equal to an arrow function that has an event or e as its first and only parameter now we can duplicate this form field one more time below instead of your name we can say prompt name is going to be prompt as well and then we can pick one of many prompts we have in our constants as a placeholder so right here let's choose something like a plush toy robot sitting against a yellow wall and we can paste it right here in the placeholder value is going to be form.prompt handle change is going to be the same but right here we can provide the additional parameter called is surprise me based on this little prop we can know whether we want to show an additional button with this form field and then of course we have to provide the handle surprise me which is going to be equal to a function of that same name this function for now can also be left empty and we can create it right here const handle surprise me this one is simply going to call our utility function to ensure that we always get a new prompt great with that said we can now only see two generic texts that say form field but let's actually control click the form field component to get into it and to start developing it to start developing our form field let's put our browser to the end right here so we can see what we are creating and let's start by wrapping everything in a div and then creating another div right inside of it that div is going to have a class name equal to flex items Dash Center gap-2 and margin bottom or mb-2 you can see our Fields disappeared and now we're ready to create the actual field before we do that we have to get access to all of the prompt that we passed into our form field component we can do that by destructuring everything from props and by everything I mean label name type name placeholder value handle change is surprise me and handle surprise me there we go now we have all the data we need to work with first we're going to focus on a little button that says surprise me and that button is made up of a label that label has to have an html4 in this case a name and a class name equal to block text Dash SM edium and text Dash gray Dash 900. finally inside of there we can render label name as you can see now we have your name and we have the prompt but below that label only for four fields that have the is surprise me prop turned on there we can render a button this button is going to be of a type is equal to button it's going to have an on click property equal to handle surprise me and it's going to have a class name equal to font semi bold text Dash XS for extra small BG Dash hash e c e c F1 padding y of 1 for top and bottom and padding X of 2 for left and right rounded Dash 5 pixels and text stash black finally inside of that button we can say surprise me if we save that you can see a little button appear right here for now it's not doing anything but soon enough it will finally let's create that form field input we've been talking about for so long below this div we can create a self-closing input tag inside of there we can provide it a type equal to a dynamic type we're passing into this component an ID equal to name a name equal to name to differentiate them then we can give it a placeholder equal to placeholder value equal to value on change equal to handle change and required if we save this you can see two ugly looking form Fields so the last thing we have to do is apply a class name equal to BG Dash gray Dash 50. that's already going to change it a bit border Dash gray Dash 300. text Dash gray Dash 900. text Dash SM for small rounded Dash LG to make it rounded on Focus ring Dash and let's apply a hash 6469ff that's that blue color also on Focus but this time modifying the border to the same color four six four nine FF we want to give it an outline none a block property W Dash full and padding Dash three and with this our fields are looking just a bit better we have a lot of Border properties but I forgot to apply a border so now this is looking even better you can see that they're matching the overall design great with that said we're done with the form field component so we can get back to our create post of course these fields are not yet functional but they soon will be below our second form field still in the same div we can create another div this div is going to have a class name equal to a relative what we're doing right now is we're creating a place where an AI generated image will be shown but also we will show a preview of the image in case it hasn't been already generated so we're creating a container for that little spot right now we're going to put it as a relative give it a BG Dash gray dash 50 give it a border as well as border Dash gray-300 text Dash gray Dash 900 text Dash SM for small rounded Dash LG on Focus we want to give it a ring Dash blue dash 500 and on Focus we also want to give it a border Dash blue dash 500 width is going to be 64. p is going to be 3 for padding H is going to be 64 as well Flex justify Center and items Dash Center based on this info we can now show if we tap into the dynamic block of code form dot photo so if there is a form.photo then we can show a self-closing image tag that's going to have a source equal to form.photo an off tag equal to form.prompt and we can also give it a class name equal to W Dash full H dash full and object Dash contain but if we don't have a form.photo then we can show a self-closing image tag that's going to have a source equal to preview image and ALT is going to be preview and class name is going to be W-9 out of 12 h-9 out of 12 and object Dash contain as well as opacity Dash 40. now if we save this I think you can see what I meant when I told you that this is where the real AI generated image will go but for now we simply have a preview placeholder now there also has to be a loader when the image is being generated So Below this Dynamic block of code we can open another Dynamic block of code and say generating image and end so if that is happening then we want to show a div and within that div we're going to render the loader but we have to position that loader so that it fits nicely right here by giving it a class name equal to Absolute inset-0 Z of zero Flex justify Dash center items Dash Center and then BG Dash rgba 0 0 and then 0.5 that's for the opacity and then rounded Dash LG now if we save this nothing really is going to happen because we're not generating an image right now but if we were just to show you I can turn on the generating image to true and then that's going to look like this wonderful now going back we of course need a way for us to submit the image so going below this div this div and then one more div just above the form we need to create a new div is going to have a class name equal to mt-5 flex gap-5 and its only purpose is going to be to wrap our button our submit button so this button is going to be of a type is equal to button on click is going to be generate image of course this is a new function we haven't yet created so at the top we can add it right here above handle submit const generate image there we go as I said the logic for all this will be implemented soon but for now let's finish the layout we can also give it a prompt or a text that's going to say something like if generating image then we can say generating da da da otherwise we can say generate and as you can see it's saying generating right now because it's not image we just had it as IMG so generate IMG right now it says generating because we reference the function instead of our use State field so that should have been generating IMG this is our field to track whether we are currently generating and of course this doesn't look like a button now so let's give it a class name equal to text Dash white BG Dash green Dash 700 font Dash medium rounded Dash MD text Dash small or SM W fool for full width on small devices W Auto padding X of 5 padding y of 2.5 and then text Dash Center this is going to generate a wonderful full-sized button to generate our image now once we generated we also have to submit it so below this div we're going to create another div and that Dev is going to have a class name equal to mt-10 inside of there we want to render a P tag and that P tag is going to say once you have created the image you want you can share it with others in the community there we go now this is looking a bit ugly so let's simply apply a class name equal to mt-2 to divide it from the top text Dash hash 666 e75 and text Dash 14 pixels there we go so this is looking just a bit better finally let's create that last button below the P tag we can render a button that's going to have a type equal to submit it's going to check if we are currently loading so if loading then we can say something like sharing dot dot dot otherwise we can say share with the community there we go now this is not looking like a button so let's give it a class name of mt-3 for margin top now let's give it a property of text Dash white BG Dash hash six four six nine FF that's that blue cooler font Dash medium rounded Dash MD text Dash small or SM W fool on small devices W Dash Auto paddingx of 5 for horizontal padding padding y of 2.5 for vertical padding and then text Dash Center and there we go we have a beautiful share with the community button now as you can see we have been viewing our website in like 1 4 of our full HD window and everything is looking great but if we keep expanding it it's still looking great and it comes a bit more closer to the center of the screen for easier viewing with that said now is it time to implement the functionality of our Fields so that we get ready to send that beta over to the back end which we're going to start creating really soon so to do that let's first make sure that we can actually type values in our form fields we can do that by focusing on our handle change function this handle change is simply going to take the event the key press event and it's going to call the set form state there we want to spread the entire form and we want to update e.target.name meaning that specific property with the newly created e.target.value meaning the character we typed in to make the syntax work we have to close the bracket right here so this is looking good to me now let's make the handle surprise me button work as well there we need to get a random prompt const random prompt and that's going to be incredibly easy because we have created a get random prompt function which accepts a form.prompt to ensure we don't render the same one once we do that we can simply call the set form state spread out the entire form and then update the prompt to be that random prompt there we go now if we click surprise me you can see that it keeps changing from a lot of different interesting things that are dally AI image generation tool can create and you can also type in your name so once we have our name once we have our prompt we are ready to generate our image so that is the generate image button right here this is the button that's going to call our backend which of course doesn't yet exist which finally brings us to the point where we absolutely need to develop our backend as the front end is basically backing for it so what we can do is close our create post close our app.js and we can get started with creating our fully custom node.js mongodb and express.js backend that's going to be interacting directly with the dally open AI API to get started with creating our backend we can collapse all of our files and folders and create a new folder right in the root of our directory let's call it server now we can go to view and then terminal and you can press this little icon right here to split the terminal in half that's going to allow us to have both front end and the backend open we need to CD dot dot to move from the client side all the way to CD server to move to our server directory there we want to run a command npm in net Dash y this is going to initialize an empty package.json file by empty I mean right now we have no dependencies there so what we can do is we can first change the script to start we want to add a script to start our backend and it's going to run nodemon index node mon is a package that ensures that our backend is always running no matter how many changes we make to it and finally we have to install all the necessary dependencies we can do that by opening the terminal and running a command npm install cloudinery which we're going to use to store our images course for cross origin requests dot EnV for storing secrets Express mongoose nodemon and open Ai and again make sure that you are inside of our server directory and press enter great all of the packages have been installed and we are almost ready to run our application but first we have to create an index.js file also we'll be working with modules es6 plus imports and exports and not old module that requires so to enable that we have to add one line right here below the description which is type is equal to module this is going to allow us to use the same import and expert statements as in react and with that said we can close our packet Json and we can create a new file called index.js inside of here we can import the libraries and packages we'll be using tools such as Express coming from Express we'll also need to import everything as dot EnV from dot EnV then we're going to import course from course that's going to be all when it comes to external packages we'll be using later on we'll have some internal ones as well but for now let's set up our DOT EnV by running the dot env.config and calling it as a function this line allows us to pool our environment variables from our DOT EnV file which we'll create soon then we can initialize our express application by running const app is equal to express and we call it as a function we can add additional middlewares to it by saying app.use and then we pass course which we also call as a function then we can also add an additional middleware in this case Express dot Json that accepts an option object where we can set the limit to 50 megabytes and we are ready to create our first route app.get simply forward slash our root route it's going to be an async function where we have a request and a response and there we simply want to rest dot send that's going to be not hello world but rather we can do something like let's put it right here hello from dally there we go so this is just going to ensure that we know that our application is running once we visit the URL of our server great now we have the base of our express application setup but we need a way for us to run it to do that we can create a function called const start server is equal to an async function where we call app.listen and let's say that the port of our application is 8080. as the second parameter we can provide a callback function that's going to call a console.log and we can say server has started on Port HTTP colon forward slash forward slash localhost 8080. there we go and we can immediately call our start server function great with this done if we open up our terminal we can now Run npm start and that's going to run our nodemon index command and run our server on localhost 8080. if you open it up in your browser you should be able to see Hello from dally which means that everything we made so far works perfectly now of course we'll have to add some complexity to this back end we'll have to connect it to mongodb we'll have to connect it to open AI API as well so let's do everything step by step let's first create a function that's going to connect our application to mongodb so we can create a new folder inside of our server called mongodb and then inside of there we can create a new file called connect.js there we can import Mongoose from Mongoose we can also create a function const connect DB is equal to it is a regular Arrow function that accepts a URL and then we want to call Mongoose and call a DOT set function and we want to set strict query to true this option that we just set is going to be useful when working with search functionality later on for now let's also connect our database which is the more important part so we can say Mongoose dot connect we're going to pass a URL or a URI string right here and then we can call a DOT then on it there we can simply console log mongodb connected or we can add a DOT catch with an error where we can simply console log the error finally we can export default connect DB so that we can import it inside of our index.js inside of here we can now import connect DB from that slash mongodb forward slash connect and now before we do app.listen we want to connect to mongodb this can fail so if it fails we can create a try and catch block we can say connect DB and then we want to pass a process.env DOT mongodb underscore URL this is going to be a special URL of our mongodb Atlas database now if it succeeds then we want to run our application on localhost 8080. if that is not the case we can simply console.log the error there we go so now let's put this nicely let's save our application and let's open up our terminal as you can see our app has crashed and that's because this variable right here process.env.mongodb URL is entirely empty we haven't yet added our mongodb Atlas URL so let's make a connection to right now you can do that by visiting mongodb.com forward slash Atlas forward slash database it is their multi-cloud online database and it is entirely free so click try free and then in here you'll have to create your account or sign up with Google in this case I'm going to sign up with Google and after you do that you'll see your organization and you can create a new project we can give it a project name something like dial e there we go and next we can set the permissions to project owner since we'll be the only ones using it and that's going to bring us to database deployments you can add your current IP address right here and we can build a database you can create one for free while the free database is selected you can choose a provider and you can choose a server that's closest to you and you can click create cluster then you'll have to choose from pictures of crosswalks or something else and we can create it wonderful so cluster is being created which is going to allow us to start uploading AI generated images into our database while that is happening you can go to database access and there we go our cluster has finished provisioning let's go to network access make sure that your IP address is added right there and then we can go to database you can click connect and then you can enter your username and password and you can choose a connection method in this case we want to connect it to our app so that's the second step right there and you can see your string right here so you can copy that string you can open up the file explorer in the code and you can create a new DOT EnV file there you can start typing mongodb underscore URL is equal to a string and then you can pass this mode with DB string now as you can see your username is going to be pre-filled but you'll have to answer your password manually in my case it's one two three one two three a and that should work so once again while you were creating that user you entered your username and password so make sure to add your password right in here for everything to work great every time we update our DOT EnV we'll have to restart our server so press Ctrl c y and then npm start one more time this is going to restart it and apparently that breaks the application again so it looks like we meant to import da dot slash mongodb connect.js and let's see if it did that we did just connect this would have worked in react but it doesn't work in node so let's fix that and there we go server has started on port 8080 mongodb connected wonderful so our connection with mongodb is successful and now we are ready to proceed with the next step which is creating a model for our post or a structure of how that post is going to look like so inside of mongodb create a new folder called models and inside of there create a new post.js file there we can import Mongoose from mongoose and we can start creating our new post schema by saying const post with a capital P is equal to new Mongoose dot schema we call it as a function and pass an object there you can add a name which is going to be type of string with a capital S like this and the required is set to true we can duplicate this two more times then we're going to have a prompt and finally we're going to have a photo and all of these are going to be of a type string and required true finally we have to create a model out of that schema const post schema is equal to Mongoose dot model and then we pass a name for that model or a schema of post and then we pass the schema we created post right here finally we need to export default post schema now we can use it when generating new posts wonderful and with that we're done with the entire mongodb side of things now we can focus on creating the routes for our backend application so let's create a new folder called routes inside of there we're going to create two types of routes first one are going to be post routes dot JS and the second one is going to be dally routes dot Js now that we have created both of these files we can go back to index and we can import them right here in the index.js file just at the top we can import them by saying import post routes coming from dot slash routes forward slash post routes.js we can duplicate that and we can repeat the process for daily routes there we go and then to use them in our application we have to also add them to the middleware right here so below our app.use Express Json we can say app.use forward slash API forward slash V1 forward slash post and then we can render post routes we can duplicate that and we can do dally so essentially what we've done is created API endpoints that we can connect that we can hook onto from our front-end side of course these routes are currently completely empty so now our job is to add additional routes that we can call from the front end first we can start with Imports for both of these files so we can import Express from Express we can also import everything as dot EnV from dot EnV allowing us to use environment variables then we can import V2 as cloudinary from cloudinary and we can import our post model so import post from dot slash mongodb forward slash models forward slash post.js and don't forget dot dot Js finally we can call the daddy NV dot config to make sure that our environment variables are indeed getting populated and finally we can create a new instance of the router const Router is equal to express.router with a capital R now we can copy that entire thing and we can move to daily routes and paste it right here Express is still going to be needed dot EnV is going to be needed but instead of cloudinery here we'll be working with open AI API so we can import configuration and open AI API that's coming from open AI let's fix a typo right here we don't need to import the post right here but we do need to set up the router great so now we have the Baseline for all of the files set up I'm going to close everything and just go back to index to recap what we've done so far we've created a simple instance of our backend API that simply has one route so far where we can verify that our application is working then we have also started our server and we have connected it to mongodb by passing a specific mongodb URI query for our mongodb Atlas cluster then we have added post routes and Dally routes right here I noticed that I misspelled it so this right here must be daily routes for everything to work great that we caught that and finally now is our turn to start adding post routes which are going to be used for creating the posts and retrieving the posts but before that we have to enter also our daily routes which are going to be used to generate the data from the API maybe the most important part of this video so that's going to be the exact next thing that we're going to do let's get started with generating our images from open AI dally API to connect this powerful API we're of course gonna need an API key to get the key go to openai.com and press the API button in the nav bar then click get started and create our account or log in there you'll be greeted by open ai's dashboard right here they have a lot of Quick Start tutorials and examples also different applications that you can build now that we're here we can expand our browser click JavaScript Mastery or your name right here and then click view API keys there you can create a new secret key and make sure to store it securely because you won't be able to view it again once you do that you can go to the Explorer to the dot EnV file and then add it right there we'll add it like this above the mongodb URL open AI underscore API underscore key is equal to this string right here once you do that just remember you'll have to reload your terminal we're going to do that later as we Implement more changes and we can utilize that environment variable the way you set it up is you create a new variable called const configuration and that's equal to new configuration you call it as a function and provide an object as the first and only parameter there you can set the API key to be equal to process.env open AI underscore API underscore key and then you create an instance of open AI by saying new open AI API and then you pass in that configuration where you entered your API key to test this router properly we can first add a demo route by saying router dot route and then we can add just a forward slash there we can say dot get so this is a get route where we have a wreck and a res make sure that this is inside of parentheses like this rack and res and then we can simply open up a function block instead of here we can say res dot send hello from dally and we can test it out so now let's rerun our application let's see if everything is working properly it seems like we have an error it cannot find dally routes.js so let's see if we spelled it properly going back to the index Dali routes from that slash route dally routes.js this is looking good to me most likely we forgot to export the router so it cannot find it so what we have to do is at the bottom we have to say export default router and you need to repeat this thing for the Post routes as well finally we can rerun our application or never mind it fixed itself so now if we go to localhost 8000 and we go to forward slash API forward slash V1 forward slash post if I'm not mistaken we get cannot get API if we want post so let's check what API did we use we used forward slash API forward slash V1 forward slash post and then right here yeah we didn't do the post routes yet we did the daily routes my bad so right here if we type dally we get hello from dally which means that this route that we created right here works great now we have to add a real daily route the route that's going to make a call to the open AI daily API and based on our prompt it's going to return a real AI generated image we can do that by saying router dot route that's going to be just forward slash but this time it's going to be a post request there we get a wreck and a res and really important aspect of this is you have to make it async because it will take some time then we can open up a try and catch block and we can get the prompt from rec.body this is going to come from our front and side The Prompt that we create it's going to be this one right here so going back to our application we have to generate that image and we can do that by saying const AI response is equal to a weight open AI dot create image we can pass an object with options we can pass in the prompt pass in n 1 meaning one image we can pass in a size equal to a string of 1024 times 1024 and we can set a response underscore format to be equal to b64 underscore Json great and we of course have to add a comma right here great so now that we have this AI response we need to get the image out of it and that's going to look like this const image is equal to AI response dot data dot data One More Time Zero Dot and then b64 underscore Json great finally once we get that image we can say res dot status of 200 dot Json and then we're going to pass in a photo which is going to be equal to the image and that's it we're getting that image and we're sending it back to the front end finally if something doesn't go right we can run console.log error and we can also rest that status of 500 dot send error question mark dot response dot data dot error Dot message great now if we save this our route is finalized the only thing we have to do is go back to our front end and call our backend to see if it's going to bring anything back to do that we can close all of our currently open files go back to the client side go to the source to our pages and then create post page and there we can now make a call to the back end that you have created from our generate image function we can do that by first checking if we have a prompt so if form dot prompt then we can open up a try and catch block and now we're working back on the front end so I can switch it to our Veet application there we first want to set generating IMG loading state to be true because we have started the generation then we want to get back the response so we say const response from a weight Fetch and then we have to pass the API that's going to be HTTP colon forward slash forward slash localhost 8080 forward slash API forward slash V1 forward slash dally and we have to provide a second parameter which is an object of options the most important option is method is set to post and as you can notice we have an await so we need to add an async right here as well then you need to pass headers headers is an object where content Dash type is equal to application forward slash Json make sure to type this exactly as it is right here without typos and finally we can pass in the body the body is going to be a stringified prompt so we can say json.stringify prompt form dot prompt right here and that is it we are passing all the needed data to our backend to then get back the response which is going to be the AI generated image to parse that data and to be able to see it let's say const data is equal to a weight response.json and once we got it we can set it to the state by saying set form dot dot form to spread other parameters and then we're going to set the photo to be equal to a template string of data colon image forward slash jpeg semicolon base 64 comma and then dollar sign and curly braces data dot photo so this is the way in which we're gonna save and render our image finally instead of the catch we can alert an error if there is one and then we can add a finally Clause so whatever happens we want to set the loading state of set generating image to false and then else if we don't have a prompt which is right here in that case we can add an alert saying please enter a prompt now if we save this and click generate let's see what happens usually things never work on the first try especially after we added a lot of code but let's give it a shot and then if it doesn't work I'm gonna show you how to debug it in real time so here it goes generating okay and it worked believe it or not it worked on the first try a man wanders through the Rainy Streets of Tokyo with bright neon signs 50 millimeter lens this is looking great and this image was generated by AI now before we share the image with the community you can press surprise me a couple of more times and generate multiple images so let's try one of a comic book cover of a superhero wearing headphones there we go and now if you're not happy with the image you can keep regenerating until you find the one that suits what you were looking for great this one is much better but keep in mind you don't necessarily have to use just prompts from the surprise me button you can type whatever you want to so let's try a beautiful nature photo 4K Ultra realistic and let's click generate there we go this is wonderful and now we are ready to share with the community but now at this point that doesn't yet work we only created the API endpoints for generating these AI images but now we have to create post shrouds to actually upload the image and the prompt in the post itself to our AI image sharing social media platform that is where the merge stack comes in that is what makes this application a full stack marine application so we can close all of the currently open files go to server routes and then post routes and we can get started with implementing our almost grad like functionality to get started with our post routes we'll have to set up an account on cloudinery cloudinery is going to host our images for us so we can retrieve them later on once we submit them and make our application so much faster to create an account with cloudinery you can go to cloudinery.com Let's expand our browser right here and let's click get started right here you can sign up using email Google or GitHub and after your creator account this is what you should see if this is not what you're seeing right now you might need to create a new account as they might have changed some things then you can move to dashboard and there are three different pieces of input that we need first one is the cloud name so you can copy it we can go back to our DOT EnV and we can add a cloudinery underscore Cloud underscore name is equal to and then you can paste it the second thing we need we can duplicate this three times is going to be cloudinary API key so we can put it here and the last thing is the API secret great so now let's copy the API key paste it right here and let's copy the API secret and paste it right here as well great now we have everything we need from cloudinery and that's it we can go back to our application we can close our Dottie and V and remember whenever you change it you have to stop your terminal from running by pressing Ctrl C and then Y and then re-run it again great and now we are ready to start creating our post routes but let's utilize those keys that we just got so we can say cloudinery dot config we can pass in an object that's going to contain a cloud underscore name that's going to be process.env.cloudinary underscore Cloud underscore name and we can duplicate that two times for the second one we need API underscore key and we can change this to API underscore key and the last one is going to be API underscore secret and right here we can change this to API underscore Secret great now our cloudinary is configured and we'll be able to upload our images there now we can move on to creating post routes we're gonna have two different routes the first one is going to be a get route to get all posts and then the second one is going to be a create a post route so let's create it that's going to be router dot route forward slash or you can simply say router.get and then we can say dot get async and then we can provide a function that's going to have a request and response as parameters and we can close it like so now we can duplicate this function below and we can put it as a post route so the only thing we have to change is the verb from get to post there we go now let's first create a post route so we can submit our post first we have to get all of the data we're sending from the front end so we can destructure it by saying kant's name prompt and photo and that's going to be equal to wreck that body meaning we're sending it from the front end then we need to upload the photo URL to cloudinery const photo URL is equal to a weight cloudinary dot uploader dot upload and then we pass in the photo as the parameter this is coming from the front end we're uploading it to cloudinery and then we get cloudinary optimized URL now that we have all of the data and the newly updated photo URL we can say const new post is equal to a weight post with a capital P dot create we pass in an object that has a name a prompt and also has a photo equal to photo URL dot URL there we go these four lines are going to create a new Post in our database once we create it we can say res that status of 201 and then we can pass in dot Json success is equal to true and then beta is equal to new post finally we can wrap everything inside of a try and catch block so I'm going to copy everything we have right here I'm going to write a try and catch block paste everything in the try and then in the catch we're going to Res that status of 500. dot Json where success is set to false and then error or rather the message is equal to error there we go so this is looking great also it seems like the prompt is unused it looks like I misspelled it right here so if we spell it properly everything is good now keep in mind that what I've showed you here is the best possible approach and the actual practice of how you'll be working with databases and file storage and creating new documents in your databases in real life applications we didn't want to Simply take a shortcut and store images in base64 url that would be great for a couple of images but as we scale we'll have to provide storage for all of those images and that is exactly why before creating a new instance of a document we are uploading the image to cloudinery that stores it and gives us back a photo URL based on that info we then create a new Post in the database by only sharing the URL great with that said create a post route is done but we wouldn't be able to see their posts if we don't have get all posts route implementing this is going to be even simpler we can create a try and catch block and say cons posts is equal to a weight post dot find and we can pass an empty object as the first and only parameter then we can say res that status of 200.json we can pass an object containing the success property set to true and data set to posts that's it returning old posts we can duplicate this add it to the catch change the error message to 500 success to false and finally message to be equal to error there we go so everything is looking great right now with that our post routes are done and with them our entire backend now we should be able to generate images and then and then share them with the community I entered my name I'm gonna add a prompt and I'm going to click generate image is being generated as we speak and we can see a great image now if you're not satisfied with it you can modify your prompt or you can just click regenerate so it's going to give you another instance of that same image in this case I decided to do both there we go this is a great looking fish so let's share it with the community again this is the first time we're clicking this so it's possible it's not going to work now before we share it with the community we of course have to go back to the front end and implement the share button so we go to Source Pages create post and as you can see the generate prompt is done we did it before but now the last function we have to implement is handle submit before we begin we're going to make this function asynchronous as we'll be doing some data fetching then we're gonna get the first and only parameter of event that's going to be a submit event and then we want to call event dot prevent default this is going to ensure that the browser doesn't automatically reload our application then we need to check if we have the form and the photo before we submit so we need to check if form dot prompt and form dot photo exists if that is the case we can set the loading to be set to true we are starting with the process then we can open up a try and catch block with a catch we get the error and then into catch we can start with the data fetching and then in the try we can call our post image route we can do that by saying const response is equal to a weight fetch we have to pass the URL HTTP colon forward slash forward slash localhost 8080 forward slash API forward slash V1 forward slash post then you want to pass a second parameter which is an object containing the method equal to post headers equal to an object that's going to contain a content type equal to application Json make sure to spell it exactly as it is spelled right here and then finally we're going to provide our body which is going to be equal to json.stringify and then we're going to Simply pass the entire form wonderful as you know in our last file post routes right here to write that body is where we are getting that entire post great so now that we're doing that we're getting back the response and then once we get it we can await response dot Json that means that we got it successfully and finally we can navigate to forward slash go back to home to be able to see our image now if something goes wrong we can simply alert the error and finally this is going to happen either way we can set the loading to be set to false this is it now if we save this file our function is fully done and we also have to add just one more check if we don't have the form.prompt or form the photo we can create an else right here and then we can alert please enter a prompt and generate an image that's it now we still have our grade puffer fish right here so let's simply Click Share with the community it says sharing I'm guessing something is happening and we are brought back to our home page and that could have only happened if the response was successful because the navigate is after the await wonderful now the reason why it says no posts found is because we haven't implemented the get route in our front end so let's go back to the home page and right here we have to make a call to get all of the posts to make that call we're going to create a new use effect hook use effect is called at the start once the component loads this one will only be called at the start meaning we're going to left the dependency array as empty there we want to create a function called const Fetch posts is equal to an async function and then immediately after we want to call it fetch posts inside of this function we first want to set the loading to be set to true because we are instantly doing something then we want to open up a try and catch block like this catch has the error don't forget and then also we can give it a finally you already know what it goes into finally there we stop the loading now what do we do in the try well it's going to be similar to what we did in the post route we want to get a new response by saying equal to a weight fetch HTTP colon forward slash forward slash localhost 8080 forward slash API forward slash V1 forward slash post then as the second parameter we pass in an object where the method is get and the headers are going to be content type application Json now we have to check if the response is okay and we can do that by saying if responds that okay then we can get the result by saying const result is equal to await response.json finally once we have the result we can set all posts to be equal to result dot data dot reverse the reason why we're reversing it is because we want to show the newest posts at the top great now let's also alert the error if there is one and save the file still it says no posts and let's check our no post Clause right here so that is because the array data is equal to nothing so inside of here we can pass all posts let's do that all posts and Save and there we go we have one postcard which is our fish card now to be able to Showcase it of course we have to dive into the render cards and we have to implement the card component which is right here so far we were simply looping through them but the card itself still remained empty after implementing our card component it should look something like this some cards are going to be huge some are going to be a bit smaller but after you hover over them you should see a prompt that a user used to generate that AI generated image a user that created it and a download button great so let's go ahead and implement it right away to get started with implementing our card we can import the download icon coming from dot slash assets and we can also import download image coming from utils this is a second utility function we can create so you can control click the utils to go into it and then below our getrandom prompt you can export async function download image there you can pass the underscore ID as the first parameter and the photo as the second one there we'll be using the file saver library that we installed before so at the top we can import file saver that's coming from file Dash saver the only thing you have to do to implement this function is say file saver dot save as photo and then you pass in the string to download that's going to be download Dash underscore ID and then dot jpeg great now we can go back to the card and we have access to this download image function our card is also receiving some parameters it's receiving the underscore ID the name the prompt and also the photo now how do I know that well if we go back to home you can see that we are iterating over these cards and we're spreading all of the values that each post has great now we can work to create the layout of that card I'm going to collapse our browser just a bit and I'll open up the console to see where the error seems to be because we cannot see anything right now it's download image looks like I misspelled it so if I go back to utils and copy the correct name I can fix it right here and it should work there we go now it says card let's actually create the look and feel of that card first of all we're going to have a div that's going to have a class name equal to rounded Dash XL it's going to be a group because we're going to have multiple things inside of it it's going to be relative and it's going to have a Shadow Dash card finally on Hover we're going to change the shadow to card hover and we're going to provide a card class name if we save this we can see one huge card right here rather it's just a rectangle with a shadow but once we add the image everything is going to change so we can add a self-closing image tag with a class name equal to W Dash full H dash Auto object dash cover and rounded Dash XL then we can give it a source equal to photo and we can give it an ALT tag equal to prompt that's going to be dynamic as well if we save that we can see our wonderful image right here believe it or not this image was generated by AI That's pretty crazy but now let's say we wanted to create a similar fish like this one we don't know which prompt the user has entered to get this result that's why we'll work on creating the prompt as well so people can know what other people have used below this image we can create a div and that Dev is going to have a class name equal to a special property of group Dash hover then we want to make it into a flex it's going to be a flex Dash coal a maximum height meaning Max Dash H dash 94.5 I found this to work the best it's going to be hidden it's going to be absolute and it's going to be shown at the bottom zero and left 0. write 0 as well finally we want to set the BG Dash hash 10131f and margin Dash 2 p dash 4 rounded Dash MD this is going to provide an overlay as you can see once we hover you can see that black box appear at the bottom now inside of there we want to render a P tag that's going to render The Prompt if I save this we should be able to see the text right here now let's style it a bit let's give it a class name equal to text Dash White text Dash SM overflow Dash Y dash Auto and prompt if we save this it's looking just a bit better now below that P tag we're going to create a div and that div is going to have a class name equal to mt-5 for margin top Flex justify Dash between items Dash Center and gap-2 that is a wrapper for all of the other elements we'll have inside of there such as the name the photo and then later on the download inside of there we can create a wrapper div for the smaller part meaning just the photo and the name there we can give it a class name equal to flex items Dash Center and gap-2 and inside of there we can create a div that's going to wrap our name so there we can simply say name and then zero that's where the name is hidden if I save this we should be able to see it right here I can see just a so that's not looking good meaning that's just the first letter but based on this first letter we're going to form that Avatar we're going to form that image that you can see right here that's looking great so let's do just that by giving this div a class name equal to w-7 for with h-7 for height rounded Dash full object dash cover bg-green-700 Flex justify Dash Center items Dash Center text Dash white Dex Dash Xs and fun Dash bold if we save this and hover you can see this great looking profile photo right here now below that we can simply render a P tag and that P tag is going to render the entire name but of course let's give it a class name equal to text Dash white and text SM there we go this is already looking so much better I think this text is a bit too small so maybe we can change the prompt text to text Dash MD Yep this is looking great finally let's add a button to download the image we can create that button below this div right here with a gap two that's going to be a button it's going to have a type equal to button it's going to have an on click property where we can have a callback function that's going to call the download image function we need to provide the underscore ID as the first parameter and then the photo as the second one we can also give it a class name equal to outline Dash none BG Dash transparent and Border Dash none if we save this we cannot see anything yet because we have to add something inside of the button and that something is going to be an image that image is going to have a source equal to download and I'll tag equal to download as well and a class name equal to w-6 h-6 object Dash contain and invert now if we save this and hover over here we have this beautiful download button and it's fully functional as well if you click it immediately it downloads the image and you can see it in its full Glory this is a 1024 by 1024 image and once again it was fully AI generated an AI doesn't even know what a fish is but it created it looking like this based on the given prompt that is wonderful now believe it or not that is it when it comes to creating the layout of our card which now means that if we expand our application we have our wonderful showcase and we have successfully created this image from our create page which essentially means that our entire application is fully done isn't this great now there's just one small part we still have to finalize and that's going to be the search trust me keeping in mind everything we've done in this video that's going to be an easy job so let's go ahead and collapse our browser close all of the currently open files open up just the home page and let's focus on implementing the search to implement the search we can create a new function cold const handle search change that's going to take in an event as the first and only parameter that's a key press event and there we want to set search text to be equal to e.target.value and then we want to search for something now we also want to add a debounce to that meaning we don't want to filter out through everything for every single keystroke we want to set out a timeout and we can do that by creating the set timeout like this it accepts a callback function and then we can specify the response in this case we can do about 500 milliseconds when the function inside of it runs meaning if you type multiple characters at the same time you're not gonna make individual requests for every single character if they were typed all in this time frame now inside of here we can say const search results is equal to all posts dot filter the filter accepts a callback function where we get an item or a post and then we want to check if item dot name dot to lower case dot includes and then search text dot to lower case if that is the case then we can show that post we can filter it out but we can also look into the prompt so right here we can say or or item dot prompt dot to lowercase that includes search text Dot to lowercase so this is our filtering prompt now that we have those search results we can set searched results to be equal to search results or rather we call it as a function right here in this set search results we can create as a new use State field so at the top we can add two additional use State fields the first one is going to be searched results there we go and then set search results great and then we can add a null right here at the start and then finally we can also create a new use state cold search timeout and set search timeout at the start set to null now that we have that we're successfully setting the search results and we can wrap all of this in a new timeout so what we can do is set search timeout and then we can simply pass everything we have created right here inside of that function like so that allows us to also clear that timeout every time that we start typing something new now that we have this handle search change we can pass it into our input right here let's search for it that's going to be right here our form field so to this form field we can pass a label name equal to search posts we can pass a type equal to text a name equal to text a placeholder equal to search posts we can also pass a value equal to search text and then finally we can pass the handle change equal to handle search change and there we go now we have our search posts input finally what we have to do is we have to render cards if there is a search text then we want to render through searched results which is our new State field now if I save this you can still see our post but if we search for something like Eiffel Tower as you can see no search results found now just to see if the filtering is going to work properly we can go ahead and create a new post right here I entered my name and let's go with something like Ifill tower on a rainy day let's do impressionist painting let's try that let's click generate as the image is generating let me spread this out there we go this is looking okay I guess but we want it to be more realistic as well and let's fix the spelling so sometimes you'll have to go through a couple of iterations until you get something you're happy with there we go this is much better so finally let's share it with the community and there we go our beautiful AI generated images here and now if we search for fish you can see the fish and if we search for Eiffel you can see the Eiffel Tower which means that it works as well we can even download it you can open it up and you can see how well it is made this one is done more like a painting so you cannot see the level of detail but still it is incredibly impressive with that said our open AI dally clone application is now finalized we can see the AI generated images and we can add additional images to our database all of this is being done from the front end to the back end to cloudinary to generating all these images so recovering the full stack application essentially creating a social media platform where users can share their own AI generated images with that said as we always do on the JavaScript Mastery the next step is going to be to deploy this phenomenal application to the Internet so you can share it with your friends but in your portfolio and get a job before we deploy our application we're first going to upload it to GitHub that way we can keep track of it you can have it within your project and that's going to allow us to more easily deploy it later on so go to your GitHub profile and then on top right click a plus icon and click new repository there you can choose a repository name something like dally that's available and you can choose to make it private or public finally click create Repository then I'm going to collapse our browser just a bit we can close all of our files go to view and then terminal and we can stop both terminals from running there we go we can also delete one terminal and clear it now make sure to see the dot dot to be in the root of your folder not in client not in server but rather in root there you can type get init then as you can see we have 9 000 changes which is never a good sign so what you want to do is you want to add a new DOT get ignore file and there you can add node underscore modules hi there Adrian from the future here a really important note also make sure to add your dot EnV file right here if you don't add it it's going to be pushed to GitHub and you don't want other people to see your secret files so now you know this is going to ignore everything that's already mentioned in the packet Json and just gonna left us with 34 files that we ourselves have created great then we can say get add Dot get commit Dash M first commit then you can copy a couple of messages from here get Branch Dash M main then you wanna do get remote at origin and finally get push you origin Main and in a couple of seconds this command is going to push our repository right here to GitHub with that said we are ready to deploy the back end of our application we're going to do that using render first we're going to deploy the backend using render but then we're going to deploy the front end or the main part of our application using hostinger which is going to make it incredibly fast and also give us a custom domain name now for render you can get started or log in once you do that you can click new and choose web service next you can connect a repository now it's asking us for a public git repository so I'm going to go back to my repo settings scroll all the way down and I'm going to change the repository visibility to public once it is public simply copy the URL go back and paste it right here and click continue then we can enter the name such as dally you can choose the region the branch and then the root directory in this case the root of our directory is going to be that slash server or I think you can just do server and then we have to add a command to start our server in this case that's going to be npm run server finally you can click create web service now the process of deploying our backend can take a couple of minutes so bear with me you can pause the video and we'll be right back now it looks like our build has failed and it is possible that that happened because we didn't provide the environment variables so go back to your dot EnV which you hopefully added to the dot get ignore file which has to be in the root of our folder right here then let's copy the keys one by one add environment variable we can add the open AI API key and we can copy the value now we can add more so that's going to be mongodb URL let's paste that as well let's add a bit more let's add the cloudinary cloud name and value cloudinary API key and value and finally cloudinary API secret and the value with that said we can save the changes we can go back to events we can go back to logs and we can re-run our deployment by going to manual deploy and then clear build cache and deploy hopefully this time it's going to build successfully it looks like it failed again and I just figured out why inside of settings if you scroll a bit down you can find the build command or the start command we typed it as at npm run server but if you go to our packet Json it is actually npm run start so that was a rookie mistake if we change this to npm run start save changes and go back to logs now we can again rerun the latest Commit This will again take some time but it just shows you that even YouTubers creating educational videos make mistakes like these it happens to everybody so just know whenever you make a silly mistake it happens you're still a great developer with that said let's wait about a minute for this to build and then we'll hopefully see it live and we had yet another roadblock it looks like we're trying to access mongodb but it seems that the API we're trying to access it from isn't whitelisted so we have to whitelist that IP address back in our mongodb Atlas under network access we can see that our current IP address is whitelisted but the one belongs to the server isn't so we can click add IP address and we can allow access from anywhere at this point we're not concerned with security breaches as you can see it is pending and it is being deployed as we speak there we go it took a couple of seconds and now if we go back to render hopefully it will rerun it by itself if that doesn't happen we'll have to once again run a manual redeploy from the latest commit it is in progress and hopefully third time's a charm and there we go servers started mongodb connected and we are off to the races go ahead and click this URL right here and you can see hello from dally that means that our API is deployed now we just gotta hook it up to our application and then deploy the front-end side which is going to be much much simpler since we're using hostinger so to get started go back to render and copy this URL we're gonna need it now you can close all of the currently opened files go to client go to source and now we'll have to change our HTTP localhost 8080 in all instances to our newly redeployed backend URL so let's search for 8080. you can see we're mentioning it three times on the front end so let's simply change it in all instances right here we're going to go up to this point https we're going to enter this new link forward slash API forward slash V1 forward slash dally let's search for other instances instead of create post we're gonna also replace everything up to this forward slash there we go and let's repeat the process for the last one there we go we successfully updated our front-end URLs from the demo localhost ones to real deployed URLs and with that we are ready to deploy the front-end side of our application on our custom domain and to do that we can revisit our hosting gears dashboard I already purchased the domain as you can see it right here JSM dally that's good maybe you have a better one if you purchased yours it's going to be right here as well and if you haven't you can do that right away the link is going to be down in the description if you haven't yet connected the domain to the setup the setup is going to show right here with a yellow setup button but if you connected it as I did in the intro of this video you can just go to premium web hosting connected that domain and click manage once you're here you can go to the file manager this is going to open the hpanel where we'll be able to drag and drop our files for now there's just a public underscore HTML file there you can go into it and then we can delete the default.php this is the place where we're going to put the build of our react application to get to our build you can go back to your Visual Studio code go to view and then terminal CD into client this time and simply run mpm run build this is going to create an optimized production build of our application and will simply be able to drag and drop it to our hostinger's age panel with Veet this is super quick and it has been done while I was speaking there is a test folder you can right click it and then click reveal in File Explorer or open in finder once you have it you can simply open up the disk folder and drag and drop everything from it right here it's going to upload the files and our application is going to be live so now if you go back to your dashboard and click your chosen domain name our daily 2.0 is now live isn't this crazy we can see that it is deployed under our special domain and it is https secured that is phenomenal now of course there might be some changes we have to make to properly fetch the data but that can be fixed easily as you can see the most important part is that this deployment took less than a minute and immediately we have premium web hosting we have a domain name you can even manage emails on this domain name also it's https secured now let's right click and go to inspect to see what might be the issue with our images if we reload we can see type fail to fetch and now it's fetching posts I just reload the page one more time and then it fixed itself I'm guessing that the render backend goes to sleep after being inactive for some time so once you ping it once it's going to work perfectly the second time as you can see the images we have created are still here which means our database is up and running on mongodb the images are served using cloudinery generated by open AI this has been just a phenomenal video and you can just keep creating more great stuff let's try it out by using surprise me let's do something like a surrealist dreamlike oil painting let's generate it and there we go this is looking phenomenal let's go ahead and share it with the community and if this works we have properly ensured that all functionalities of our application are working there we go but again I'm really Amazed by the fact that we managed to deploy this in a matter of seconds essentially so with that said huge thanks to open AI for creating such an amazing software that allows us to build these AI applications huge thanks to hostinger for creating easy to use and fast hosting services and then huge thanks to you for watching this video just keep learning and you're gonna become the best there is with that said if you'd like to learn on more comprehensive projects such as a movie app or an nft Marketplace or you would like to be mentored by myself and other mentors that are going to teach you and help you get a software developer job with one-on-one mentoring just go to jsmastery.pro and browse the website a bit I'm sure you're gonna find something you like once again congratulations on coming to the end of this video and have a wonderful day [Music]
Info
Channel: JavaScript Mastery
Views: 230,597
Rating: undefined out of 5
Keywords: javascript, javascript mastery, js mastery, master javascript, ai, artificial intelligence, ai react, dalle, dall-e, dalle 2, dall-e 2, midjourney, midjourney api, dalle api, openai, openai api, image generation, mern, nodejs, mongodb, expressjs, reactjs, react js, react app, react application, tailwindcss, react social media, react mern, react full stack application, MERN AI, openai mern, openai dall-e api, openapi dalle 2, full stack mern, learn mern, mern stack, mern with ai
Id: EyIvuigqDoA
Channel Id: undefined
Length: 132min 7sec (7927 seconds)
Published: Fri Jan 20 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.