The Gateway to Backend: A Frontend Developer's Guide to Full-Stack Development

Rate this content
Bookmark

This workshop will guide you through the product development life cycle of creating a real-world web application. You will learn about React Server Components, building a design system within Storybook, and using frontend development to approach becoming a full-stack developer. The workshop will cover increasing confidence in your application with unit tests and implementing authentication and authorization. You'll have the opportunity to work through product features and examine a real-world RedwoodJS project, gaining valuable experience in real-world product development. RedwoodJS makes it simple to approach full-stack development, and this workshop will give you the skills you need to create your own real-world web applications.

160 min
16 Nov, 2023

Comments

Sign in or register to post your comment.
  • Andrew Arnold
    Andrew Arnold
    New York Public Library
    Maybe this? https://gitnation.zoom.us/j/84052720570?pwd=GtX30KPC2rotjpEVXeaRkxf6Cnhwbm.1
  • Kaitlyn Higgins
    Kaitlyn Higgins
    E.W. Scripps
    Can you drop the zoom link with correct meeting ID here perhaps Isa? I'm seeing tons of channels on Discord, but none of them say troubleshoot. A bunch of the channels look like they're from a past summit.
  • Daniel Cha
    Daniel Cha
    Resilient Coders
    ty for the discord link

Video Summary and Transcription

Today's Workshop focused on RedwoodJS, a full-stack framework that makes it easy to develop web applications. The Workshop covered topics such as setting up a Redwood project, installing Tailwind CSS, using Storybook for component development, writing tests, setting up database relationships with Prisma, using GraphQL to access the database, and exploring React Server Components. The Workshop also showcased demos of creating links, refreshing pages, and using React Server Components for AI integration. Overall, the Workshop provided a comprehensive overview of RedwoodJS and its features.

Available in Español

1. Introduction to RedwoodJS and Brazilian Nut News

Short description:

Today, we will be talking about going from a front-end developer perspective to more of a full-stack developer perspective. We'll be looking at RedwoodJS, where I am a lead maintainer there. I first was introduced to Redwood a little over a year ago. I co-host a podcast called Compressed FM. We talk about web design and development. So one of the things that I really appreciate about Redwood is that it makes storybook and just JavaScript testing library. It takes Prisma, GraphQL, React, and makes all of those first class citizens and offers support out of the box. The actual project that we'll be working on is called Brazilian Nut News. The app that I mentioned is the Brazilian Nut News. And the name is just a fun name for this because Brazilian nuts automatically rise to the top in a jar of nuts. So this is what we're going to be working on. This is the completed repo. Hopefully as part of this workshop we'll work through some stuff and you'll have the ability to create pieces and parts of it and then if you want to revisit the content, there'll be plenty there that you can use this as an example repo to continue to build on and incorporate features. So let's actually take a look at the Redwood docs and we'll get a project up and running. So by default, you're required to have Node version 18 and then a version of yarn greater than 1.15.

Thanks for joining us today. Today, we will be talking about going from a front-end developer perspective to more of a full-stack developer perspective. We'll be looking at RedwoodJS, where I am a lead maintainer there. I first was introduced to Redwood a little over a year ago. I co-host a podcast called Compressed FM. Actually, it may be two years ago. Anyways, co-host a podcast called Compressed FM with James Q. Quick. You can check that out if you're interested. We talk about web design and development. Then we stay with a little bit of zest. but we had as a featured guest we had David Price here on episode 54 and so he is one of the co-founders with Redwood and he came on the show and just started talking about Redwood and really sold me on the entire concept of Redwood and just their opinions and how they've put the framework together so spent some time going through the tutorial on their website and it's still there So if you go to redwoodjs.com slash docs, and I'll include a link in the chat, there's a tutorial here that you can work through that goes through all of the content.

So I spent the weekend going through that and was just totally sold. So one of the things that I really appreciate about Redwood is that it makes storybook and just JavaScript testing library. It takes Prisma, GraphQL, React, and makes all of those first class citizens and offers support out of the box. And so you'll see when we get started that they've bundled all these things together, and it makes it really easy. So you're not trying to deal with configurations or trying to figure out settings and support so anytime any of those pieces are updated, we handle all those updates for you so you just run an update script. You don't have to do that yourself. You don't have to figure out, okay, why did my app break and then kind of dig through all kinds of documentation to we'll be using this. If you're looking at this and like, okay, this stack is interesting but maybe I just want to focus on React, it's still React. It's a full-stack React framework and the nice thing about it is it has a distinct front end and a back end layer. So we'll be working through all that.

So the actual project that we'll be working on is called Brazilian Nut News. And I can include a link to this particular repo. All this has in it is a read me. It has the agenda for how we'll work through the content. What we'll be focusing on. There's a few quick links and commands that you can use. And I'm going to try and make use of the breakout rooms and have some exercises so that hopefully I don't go too fast for you, but the things not too slow. I want to make sure that it's interesting. So please make use of the chat and I will try and keep my eye on it. The app that I mentioned is the Brazilian Nut News. And the name is just a fun name for this because Brazilian nuts automatically rise to the top in a jar of nuts. And so that's kind of how Hacker News works, right? So you submit a link, you can vote on the link, and then the best, supposedly the best links rise to the top. So this is what we're going to be working on. This is the completed repo. And there's a link to this within the readme. And you can interact with this. This is deployed on Vercel. The database itself is with Supabase. And so I'll show you how to use all that. But the main page here is our feeds page. And then you can see when you scroll down, you have access to the navigation. But you can also look at the latest feed. So this particular page is sorted by points. So for example, when I can't vote right now, because I'm not logged in, but if I log in, we'll say Amy at Redwood js.com. And log in with my password. You can see now I can vote. And if I vote up, say on Google, then this page will reorder and put it puts Google at the front because it now has one point but it was also added I think um more recently than say Apple in this article right here so if I click on latest this one is all based on time so the Redwood JS docs link was added most recently 13 hours ago and so that one appears at the top you can also submit a link once you're logged in so I could submit one for React Summit and grab the link for that and then you should see that appear in the list so now if I go to latest React Summit is at the top of the list I can also go to my profile and so you can see the links that I've shared and I also have an account set up under just Amy so if I type that in as Amy I haven't shared any links so that's currently empty but then you can also go to comments and see all the comments that I've made on links. You can see any link that I've marked as a favorite and then you can edit your profile. So don't get too overwhelmed. We'll just break pieces of this off and we're not going to build the entire application but I do have a link to the full repo if you want to check that out. Hopefully as part of this workshop we'll work through some stuff and you'll have the ability to create pieces and parts of it and then if you want to revisit the content, there'll be plenty there that you can use this as an example repo to continue to build on and incorporate features. So I want to make sure, is everybody good? We'll make sure we don't have any questions before we get started the actual meat of the content.

Okay, I'm going to keep going, but again, please use the chat and I will continue to check that throughout the workshop. Okay. So this particular repo, and again, I've shared a link to this within the chat. The first thing that we've already talked about what we're going to be building. So let's actually take a look at the Redwood docs and we'll get a project up and running. Oh, thanks, Isa. Or I think that's how you pronounce your name. I really apologize if you, if I butcher your name. I'm going to try my best. It looks like there may have been some trouble. I think we still have some support from React Summit in the room. It looks like there was an issue with the Zoom link. I know that this is being recorded. And so people will be able to view it after the fact. Cool. So here is the React website. I mean, sorry, the Redwood.js website. And you can click on this Docs link and come to Quick Start. So by default, you're required to have Node version 18 and then a version of yarn greater than 1.15. So I'm happy to support if you guys need a little bit of help getting those installed on your machine in order to get Redwood up and running. If not I've also included a link in the repo for Gitpod and I'll show you how this works. So this is a starter repo and if you look at this it looks pretty slim but if you click on you can either fork this repo to open it or you can just say open in Gitpod. And so Gitpod is pretty great. It allows you to work within VS Code within your browser. You can also sync it with the version of VS Code on your machine. So I already have an account. I encourage you to create an account with GitHub if you're going to go this route. But you can click on – you can just – you can start from scratch. So I will also show you how to run this in the terminal. I just want to show you this in case you have any trouble with Node or Yarn. This is probably the easiest way to get up and running just because you don't have to worry about installing those dependencies. But if you're comfortable installing Node and Yarn, or if you already have them, you don't have to worry about this particular step. But I just wanted to show you that once you open this, you can see that it creates a Redwood project and you can just work directly within the browser. So it's still installing all those dependencies with Yarn. As it's going through the flow, it'll also add some plugins that we've recommended for working with Redwood that just make it a little bit easier. And I'll try and point those out as we kind of come up on them.

2. Creating a Redwood Project

Short description:

I'm going to create a Redwood project using yarn. The project will be named React Summit. I'll override the Node version and continue with the installation. I'll use TypeScript and skip initializing the repo. After running yarn install, I'll start the Redwood project by running yarn RW dev. Let me know if you encounter any issues.

I'm going to exit out of this because I'm not going to be working in VS Code. If you, I mean, in GetPod, I'll be working in VS Code. But if you do want to sync this, I'll show you. Once it comes up, actually, I'm getting ahead of myself. There's a Ports tab here. And once it's up, you can load port 8910 and 8911, which we'll be looking at. So I'm going to exit. I'm just going to stop the workspace here. And I'm going to go ahead and just delete this for now. Okay, so what I'm going to do since I already have node, I'm actually running node 20 and then yarn. I'm going to copy this line of code. I'm going to open up my terminal. So this particular terminal is warp. It's warp.dev. It's a free terminal, but you can also use the terminal in VS Code or Hyper, iTerm2 that are all great for working with projects. So I'm going to paste this line in. And what this is saying is I'm gonna create a Redwood project using yarn. And this is the name of my project, my Redwood project. I'm gonna change this and I'm gonna call this React Summit just because I already have a project on my machine called Brazilian Nut News. Maybe you want to call yours Brazilian Nut News. But I'm going to say I want to create a project called React Summit. And this will get everything loaded. And you can see it's saying, hey, you have a version greater than Node 18. You can override this and continue to work with Redwood or you can adjust it. So if you want to change the version on your machine, I really encourage using MBM. You can see a link here on how to do that. So I'm going to go ahead and say override and continue install. I'm going to use TypeScript. If you're not familiar with TypeScript, that's perfectly fine. I'll kind of walk through some of the nuances of that. Don't get overwhelmed by that. You can also initialize your repo if you want. I'm going to say no for now. And now it looks like we are up and running. So I'm going to cd into my directory. And then I'm going to run yarn install. and that might take a minute as it's trying to get everything up and running i lost my there's the window perfect so now i've run yarn install and so to get a redwood project up and running all you have to do now is say yarn RW, which is Redwood for short. And I'm going to say Redwood dev. And so from here, it will open up in my browser, open it up in a different window, my Redwood splash page. So you can see here, there's a command for generating pages and that kind of thing. So the first part of today's workshop, let me know if you have any trouble in the chat, because I want to make sure that you guys are able to get up and running because otherwise I'm afraid you'll be lost. I don't want you to be lost for the whole workshop. That would be terrible. I'm going to keep kind of going. I think there's a lag, but I'm happy to circle back if anybody has trouble.

3. Installing Tailwind in Redwood Project

Short description:

Let's install Tailwind in our Redwood project. Use the command 'Yarn Redwood Setup UI Tailwind' to install it easily. After running the command, you'll have Tailwind up and running. It will handle everything for you, including adding the necessary CSS files and the Tailwind config.

So we've got our project up and running. And so the first thing let's do is let's go ahead and install Tailwind. So Tailwind is really easy to install with Redwood. You just have a single command. So I'm going to split the view here and I'm just going to run Yarn Redwood Setup UI Tailwind. And now I have Tailwind up and running. It does everything for me. Now, I just saw a few people join the Zoom room. Welcome. I will shoot you a link of the repo that we're working from. You can see the agenda. Kind of the stuff that, whoops, I sent you the wrong command. I just sent you what I just pasted into the terminal. There we go. Perfect. So now I have Tailwind up and running. So let me show you what this created. So if I pull up my Redwood project, let's say over here code and this will pull up my project so here is what we're working with just a second to kind of get my windows reconfigured make this a little bit bigger so this is my redwood project with all my files and folders oh that's a bummer about the zoom room And when we just ran that tailwind command, what that did was we already had a CSS file here, but it added our few pieces here for working with Tailwind. And then we also have our Tailwind config here inside of webconfig tailwind.

4. Folder Structure and Storybook Setup

Short description:

Now I'm going to give a high-level overview of the folder structure. The main things we'll focus on are the API folder and the web folder. Inside the API folder, we have a folder for our database, source folder for directives, functions, GraphQL, and services. Inside the web directory, we have config, node modules, public folder, source directory for components, app, CSS, and routes file. We'll start by getting Storybook up and running, which ships with Redwood out of the box.

Now, it sounded like a lot of people in the chat hadn't necessarily gotten any, you don't necessarily have experience with Redwood. So I'm going to just give a high level overview of the folder structure. If that seems a little overwhelming, don't worry. We'll take it one step at a time. And I think the folders will start to make sense as you work in it. But I just don't want you to be completely lost within the project.

So we have up here a few configuration files with Yarn and PS code and Redwood. You don't really need to worry about that. But as I mentioned, Redwood is a full stack React application. So there's a distinct front end. We have a web folder and a distinct back end called the API. We also have our node modules where it's pulling in all of our project dependencies. Don't really need to dig through that. And then we have a scripts folder. So this is perfect for if you want to, say, seed your database. I've also used it to, like, run a script to create an icon, like using an SVG sprite. So I'll include that script here.

But other than that, the two main things that we'll be focusing on is the API folder and the web folder. Inside the API folder, we have a folder for our database. So we'll be digging through this schema dot Prisma file. We also have a disk folder. You don't really need to worry about that since that's the folder that gets compiled. We have our source folder. So this is for directives. like if you want to require auth or skip auth. You can also create your custom directives. You have functions for working with GraphQL. You can also create custom functions for say dealing with a mailer, you want to do that. You also have GraphQL. So we'll be working inside that folder, we'll generate some GraphQL. And again, if you don't have experience with GraphQL, we'll walk through that. I'll give you an overview of what GraphQL is like. We have a library here for dealing with auth and our database and a logger. and then if we have any services. So we'll have some services that we're going to create as we're working with our database. And then this is for types if you're using TypeScript. We also have some configurations for working with Jest. We have a package.json file. So you'll notice we're making use of Yarn workspaces. So there's actually three package.json files in the project. There's one for our API directory. There's one for our web directory when we get down here. And then there's also one for our entire project. project. So that's just something to note.

Inside our web directory here, we have our config. So you'll notice that's where our Tailwind config got stuck into. We have our node module specifically for our web directory. We have a public folder. So anything that gets put inside the public folder automatically gets included when you get ready to work with your application. So for example, if I added a folder here called images, and then I could stick any images inside this folder that I want to be able to use on the site. So then I just reference that by saying slash images, say myimage.ping or whatever that image ends up being inside that particular folder. Inside the source directory, this is kind of the meat, at least of the front end. So we have a components directory where we'll have our project components. We have layout components. We have page components. And then we have our app. I usually don't, you have to have these in order for Redwood to work, but I usually don't mess with the app or the entry client. I think that has to do with Vite. And then we have our CSS file. So we looked at this already. When we added that Tailwind script, it added this code for setting up Tailwind. I don't usually modify the index.html because you need that piece for it to, for the app to work. But the routes file is very important. So a lot of the other frameworks, say like Next or Remix or even SvelteKit, they are all file or folder based routing. So as soon as you create a file or a folder, say like a folder called About, then all of a sudden you have a route ready for slash About. And that seems really easy. It's nice to work with, but if you ever want to change your routing system, if you ever want to change the file paths, you're moving files and folders around. And so with this routes file, you can change the name without having to reconfigure or reorganize your project files, which is really nice. So we'll work in that folder as well. And then we also have some additional configuration files. So I'm going to come back to the agenda here to make sure we kind of stay on track. The first thing that we want to do is we want to get Storybook up and running. And I'll kind of walk through Storybook and show how the benefits of using it and why that's so great. So it is a first. Oh, cool. How you didn't express. So the first thing that we want to do is I'm going to say yarn redwood Storybook. And you can see that Storybook ships with redwood out of the box. So as soon as you run yarn redwood Storybook, this is the first time I'm running it. So it's going to install some additional dependencies for me to be able to use Storybook in my project. but it'll go a lot faster after that, but you'll notice that as soon as it's done, it'll give me a port. I think it's like 7910 that I can use. There we go. It opened it up in a different window. There we go. So now I have storybook up and running. So I don't know about you, but that's like the easiest storybook setup I've ever had. Right now we don't have any components within our storybook. So that's why it's giving us an error.

5. Creating a Component and Using Storybook

Short description:

Let's create a component and see how it looks within Storybook. We'll focus on the front end in the first hour.

So let's create a component. it. So in the in the repo that I shared out, see where is that? Several different windows here. Here we go. There is a link to the design on Figma. If you want to pull that up, if you don't have Figma, you should be able to view the file whether you have it or not. I believe it's you can view the web version of it but it is also free to create a Figma account so here's the application and the design that we will be building out so I'm just gonna we're going to create a few components here okay I'm gonna actually do that we can create a few components and see what that looks like within storybook we're not going to create components for everything but just want to give you a feel for how storybook works because again this first hour we'll be focusing on the front end.

6. Creating a Component with Storybook

Short description:

Let's create a component in Redwood and use Storybook to develop it. Redwood handles library updates automatically, so you don't have to worry about managing them. The Redwood generators make it easy to prototype and create components. Storybook allows you to develop components in isolation and creates documentation for you. In Storybook, you can pass props to your components and see them update live. You can also test accessibility, actions, and different visual settings in Storybook.

So let's take a simple component, and I think I'll start with this linked shared because this is probably one of the most important components in this whole project. So I'm going to come back over to Warp, and we're going to create a component. So there's a question in the chat. If the library updates its version, for example, React Router, will Redwood pick it up it sure will so the nice thing about Redwood is that like if storybook updates for example it will handle that for you so if I'm working here in the terminal a message will come up the next time I get ready to run Redwood and it'll say there's an update available for you and you'll just run yarn Redwood update so the nice thing is you don't have to manage those updates yourself Redwood takes care of all that for you so I don't know about you but I've had several projects where a dependency like that gets updated and then I end up fighting and or trying to figure out what changed and how that needs to be updated and the fact that Redwood takes care of all that for you is really nice. They try and be very mindful of breaking changes.

What we're going to do, I'm going to open another terminal panel here and I'm going to create this component. I'm just going to say Yarn Redwood Generate and the generators that Redwood has is really one of its key features, I think, just for making it easy to be able to prototype things out quickly and being able to create your application. So I can say generate a component and I want to generate a shared link component. So I'm going to hit enter. And so you'll notice there's some shortcuts there for RW instead of Redwood and G instead of generates, but now it created this component for me. So if I come back over to VS code, we can take a look inside that component directory that we were just looking at. There's a shared link folder now, and there's three files that automatically get generated when you create a component. So I have the component itself, and you can see there's some boilerplate code. We have a testing file, which is pretty great, and then we also have a storybook file. So if I come back over to my storybook inside my browser, over here, I should be able to see, yep, there's my shared link component, and you can see there is the content inside. So storybook is pretty great, because it allows you to develop components in isolation. So if you're working with a development team, you don't necessarily have to create, say, like dummy code that's going to live on a fake page, and then say, once this gets implemented, delete this page. Because with storybook, you can create that component in isolation and then be able to hand it off. And I'll also show you, it'll basically create documentation for you. So I'm going to come into my shared link component here. And if this is what we're building, this component right here that has the voting icon, we have the title and a byline here and an arrow. So what I'm going to do is I'm just going to build this out. So we have, I'm going to create a container for my voting links. And for now, since I don't have the actual images here. I'm just going to say up and down. And I'll have another div and this will have our title. Let's maybe wrap that in an H2. And I have some metadata here. So I'll put that inside a div. And so let me copy this text. I'll just paste this in. And see, we have the amount of points, the person that submitted it, and then some comments. And then we have a link here on the far right so I'm going to put this as an arrow to go out so now since we have access to Tailwind I can say class name and I'm just going to use flexbox to get that our voting icon here and our title and our arrow all in line horizontally so now I'm going to make sure that this spans as much space as it can say class name equals flex one and give that a save. And now if we check this out inside storybook, you can see there's my up down links, we have the title and our metadata and then the arrow here on the far right. So what we can do here, let's go ahead and add a class name, make this flex, I want these to be stacked on top of each other. And then I want them to also be centered I think I say item center yep so those are stacked on top let's add just a little bit of space here so I'll say gap let's say gap four actually we could be precise and see what this needs to be so in figma if I say select this arrow and I hold down the alt key it will show me what the dimensions are how much space and pixels are in between so now I'm going to come back over here we can actually change this to five so you can see how we can just develop directly inside of storybook for our front end components um we didn't set up any of our custom fonts um i'm gonna just i can stop i can do that if you guys are interested in seeing that but i'm just gonna otherwise i'll just keep moving that way we can kind of also get to the back end piece of working with Redwood. So I have uppercase, text, and I'll put this at maybe 4XL. Now if we come back over, you can see there's our text. Let's make this bold. Cool, and then we have a link here, which I wanna come back and handle our links later, but let's pass in some props here. So you'll notice we're just working within React here. We can say we have our points. maybe we have the author and let's make this for the author maybe we want the nickname for the author and maybe we want the first name actually we can just do author here like this and specify those details with TypeScript so maybe we want the comment count we want the link title And the actual link. So now you can see it's, okay, it's saying that I need to actually use these things that I've pulled in. So let's do that. I'm going to pull in the author. So maybe be first name, author dot last name. And I zoom windows in the way. There we go. Now we have our comment count. Make this the title. and maybe we want this to link out here. So this will be the link. Okay, so we have the makings of our component. Now, if we come back over to Storybook, you'll notice, hey, our component is not working anymore. And that's because we're passing in these dynamic props that it doesn't know how to display them. So if we come back over to Storybook, This is using Storybook's, I think it's called C, Component Story Format 3. And, yes, there's a question here for the repo. Let me share that really quick. There you go. This has the agenda and a few of these key links that we're working through. Okay. so here we have our storybook file, and this is using their current version of a story format. And the nice thing about this particular format is that it really focuses on, like, you're passing in your props as a set of arguments. And I'll show you why this is nice, but we can go ahead and copy our props here and pass this into our story components. So say maybe it has 100 points the author, say first name, last name, and the comment count here. Maybe this is 10. That's good. We'll do RedwoodJS and then the link we can shoot off to the RedwoodJS website. Need a comment. Perfect. So now that I've passed in those props and I'm come over to our story book here, you can see that our component is running. And the nice thing is check this out. There is a controls panel down here so I can change these controls and you can see my component being updated live here within the top portion. So if you want to see, okay, this looks fine as Redwood JS, but what if I have say a really long title? Let's generate some lorem ipsum. Say I have a really long title here. How does that affect my title then? It doesn't like something that I wrote. But you can start to see, okay, where does the component break down and what do I need to include? Let's see. It's funny that that was. Oh, because it was expecting a JSON string. Let's see if that. There we go. So it's like, whoa, maybe that's not how we want to style our title if it's that long. or maybe we want to put in some validation there to say a title can only have so many characters or so many words. You can also change the comic count. And the other great thing about Storybook is you can, if there were any buttons, you can check the actions to make sure those are being triggered correctly here under the actions panel. And then under accessibility, it will also automatically run accessibility checks for you. So you can say, okay, are the headings not empty? does the colors work and if there's any violations there storybook also has a few other features that I'll point out so you can let's see I mentioned accessibility but you can also change like what is somebody with blurred vision what do they see or somebody that has color blindness so it's grayscale what do they see so that's also really helpful when you're doing testing You can also outline all of these divs so you can see exactly what you're working with. Let's see. I wanted it to turn off the...

7. Using Storybook Tools and Auto Docs

Short description:

You can turn on responsive, grid, light and dark mode, and use other tools like zooming in, zooming out, and refreshing the component. Another great feature is the ability to add auto docs to your components, which generates documentation for all the props passed in. You can also create multiple stories for different variations of your component. This helps in testing and documenting the different states of your component.

There we go. You can also... This is similar to the tools that you have within your Chrome DevTools where you can see the padding and the sizes for everything. You can also turn on responsive. What does that look like on a large mobile? What does it look like on small mobile? maybe that needs to be addressed because we now have a horizontal scroller that we've introduced um then we can also come over here turn on a grid and then you can also turn on light and dark mode so you'll see hey in dark mode we should address that because that contrast is not going to work um cool and then here's a few more things that you can a few other tools if you wanted to zoom in, excuse me, zoom out or refresh the component. But one of my other favorite features. So we're talking about if you are a front end developer and you're handing this off to a backend developer, you can add a tags with auto docs included. And if I add this, see, it doesn't like this spelling. Add that to my workspace. Auto docs. And I come back over. Now I have another link that Storybook automatically generated for me. And this includes all the documentation. So you can see right out of the gates that these are all the props that I'm passing in. If you wanted to include descriptions, you can do that. But then here are a few properties. So it's great that it generates that for you. And let me show you if we take that a step further. So this created a primary story for our shared link. Well, I can duplicate this and I can create another story. So maybe we can do, say, a long title story. And we could use all the same arguments, but we wanna show what a long title looks like. Well, instead of typing all this out, because this is gonna start to get really redundant, what we could do is we could just reference our primary story, reference our args object and then just pull in a really long title that's not that long but you'll get the idea now if we come back over to storybook you'll notice that there is another story here in our sidebar called long title show you what that component looks like but in our docs it's also documented both of these components so this also helps in terms of being able to see okay did anything break? And what are all the variations of the component? Cool.

8. Introduction to Testing in Redwood

Short description:

Let's talk about testing. There are several types of testing, including static tests, unit tests, integration tests, and end-to-end tests. Today, we'll focus on unit tests. Redwood has testing installed by default, making it easy to set up. You can run the entire test suite or limit it to specific components. We'll look at a test file and fix a failed test by passing in the necessary props. We'll also add type safety to our component using TypeScript. By the end, our test will pass, providing confidence in the component's functionality. If you're new to testing, don't worry. We'll explain the different types and provide resources for further learning.

Okay, so hopefully you now have a couple of components within your storybook. And now let's actually write some tests. So just I'm curious in the chat, how many people know how to write tests? Or maybe let's just start with that. How many people are familiar with writing tests? Just yes or no. yeah plus is perfect okay great awesome this is uh much better than what i would have expected if you're negative don't worry okay that's totally fine we'll talk through it a little bit um it's interesting because sometimes it's just easier or it feels easier to go ahead and just ship it okay cool that's great um okay so we'll talk a little bit about testing so the nice thing about testing is that you can write a component and you have the confidence that it is going to continue to do what it's supposed to do, even as you add to the code base and extend your application. So there's several different types of testing, and that can get a little confusing when you're just getting started and trying to learn the vocabulary. I know that it confused me a little bit, but if you're familiar with Kent C. Dodds, he has some fantastic material on testing and was really key for me as I was trying to learn what tests are and how to write them. So he kind of coined this idea called the testing trophy. So you can see this is taken directly from his site and I'll just go ahead and include the link. I'm just going to reference this particular image. But what he's talking about here is that if you start at the bottom of the trophy and the reason that the trophy is not a pyramid is because this also has to do with size. So you're probably going to have the most unit tests and we'll talk about what that is. So a static test is what's going to help you like catch typos or type errors as you write code. So that's one of the reasons why we use tools like ESLint and Prettier and even TypeScript fall into this bucket of being able to do those static tests to be able to catch those things for you. So there's not really any testing that you have to do per se, other than the fact that it will help you catch those bugs as you're writing your code. Then unit testing is when you're testing an individual piece of code to see if it's going to do what you expect it to do. So when you're talking about creating components, a lot of times you're talking about unit tests because you're just testing that individual piece of code for that component. And then you also have integration tests. So the thing about integration tests is all of a sudden you're checking to see, okay, this component works in isolation, and this component works in isolation, but when I put them together, do they still work the way that they're supposed to? When they're integrated together, is everything working in harmony the way that it should? And then an end-to-end test, usually these are done with tools like Playwright and Cypress, is they will allow you to really test your application the way a user would test the application. So with Cypress and Playwright, you can set up a helper robot that will click through or fill out forms or log in and it will check to make sure that your application is running correctly. So today we're not going to do all these different types of tests. That would be a lot, but we are going to set up unit tests. Our static tests are basically already done because we have a prettier configuration. We have ESLint already within our Redwood project. We're already doing TypeScript, but the next level up is our unit tests. So out of the box, Redwood has just testing installed. That's part of your configuration. And it's pretty great. You didn't have to do anything to get that set up. For me, that was a huge selling point. A few years ago, I created a YouTube video on getting tests set up on a different type of project. And it's like a 10 minute YouTube video. And so for me, you can imagine the amount of time it took for me to be able to figure everything out and then condense that into a 10-minute video. Whereas this, you just run a single command and you have your test library up and running. So if I come back over to my terminal, so here I have warp, I'm going to run yarn redwood test in the terminal. And it's going to run my entire test suite. So right now there's a few tests that we've created maybe out of the box. So you can see that it's saying I have one failed test, two past tests. So one of the things that we can do is we can just limit this to what we're focusing on right now. So I'm going to actually let me hit control C to exit out of this and hit the up arrow. Except this time, I'm going to add the name of our component. So the component that we created was shared link. So if I say yarn redwood test shared link, it will only test that particular component. So that's where one of my failed tests is coming from. You can also use these keys right here. So I could say run only the failed tests or hit O to only run tests related to changed files, which is pretty great once you have your entire test suite up and running and everything's working, then you can just have it check as you're working through files and just have that constantly going. Or you can use the P key to specify a file name. So I could have hit P here and typed in shared link to do that instead of just quitting and running specifically that one test. So let's come over to VS Code and let's actually check out this test file. So I can already tell what's wrong and why it's not working. So it's expecting some props that we have not passed in. So my guess is that it's not rendering correctly. That's really all this test does. So out of the box, we only have one test and it's just making sure that it renders successfully. And since we're not passing in all the props that we need, it's not going to render successfully. So I think as soon as we pass in all of the props that we need, it should work. So I'm going to come over to our story here. And actually, I think we can just grab this because we're exporting out this primary story. I think this will work if I just say, let's see if this works. I'm not 100% sure if this will work or not. We want to import primary from yep sure did there are shared link story and we're going to pass in our primary dot args and we want to spread that out so now okay it's saying that i have a okay cool so it looks like i'd be missing a few things saying that a few things are optional let me see what our test looks like now oh check that out it's passing now Curious why this isn't working. This might have to be of that's a isn't like where I put my import statement. That's why that's doing that. And then let's see if we're getting a weird thing. This is a TypeScript issue. So I'm wondering if we come back in and add type safety to our component, if that will resolve. So here we've list, uh, I'm not sure if everybody's familiar with TypeScript. So, I'll just kind of talk about it briefly. But you can outline all of the props and their types that you're passing into a component. So, I usually reach for an interface. And so, I'm going to call my interface. So, an interface is just kind of a fancy way to say that this is an object that I'm defining. And I'm going to say that the object that I'm defining are these props that I'm passing in. So, you'll notice I used a colon here. So I'm getting some errors here now because it's saying that you have these things down here that you're passing in, but you haven't defined any types for them. So if I copy that, now it just needs to know what type is it actually. Well, points is going to be a number. Author is gonna be a string. Comment count is going to be a number. My title is going to be, actually author is not gonna be a string. We'll come back to that. Our title is gonna be a string and then our link is gonna be a string. So, I'm surprised that this is not getting raised because this is actually an object where we're passing in a first name that's a string and a last name that's a string. So, now, if I come back over, see if that or it might just not like the fact that we pass that in as an object instead of listing them out as actual props. I'm going to keep moving. So if I come back over, we've already established that our test is passing. So if you're I think there are a few people that said they weren't familiar with testing. So let me just describe a little bit what's work, what's happening in this file. So all of our tests here are wrapped in this describe block.

9. Writing and Running Tests

Short description:

When writing tests, think about what the user sees and expects to happen. The tests include checking the title, points, author, comment total, upvote and downvote handling, and correct linking. Setting up the test involves rendering the component and passing in the necessary props. The JavaScript testing library is used for rendering components. Assertions are made by grabbing elements from the screen and setting expectations. Failed tests can be debugged by checking the syntax and importing necessary functions. By completing the tests one by one, the final result should show all tests passing.

And so that's just really a string for us to be able to say, OK, what are we testing? So you can see up here that that's where that's coming in. So I'm testing my shared link. This is describing the block of tests that I'm writing. You can actually have multiple describe blocks. So I could put something in here if I wanted to describe something else. But I don't always do that just because that's sometimes, depending on the component, that might not be necessary. So then I'm saying it, and then this just reads like a sentence. I want to say that it renders successfully. So it's the first parameter it takes is a string. And then the second parameter that it takes is an object. And that object is what actually runs your test. So when you're writing tests, you have to set up the test and then make an assertion based on that. So this is kind of doing everything all in one line. It might be easier if we write another test and talk through it a little bit. So when you're writing tests, try and think of it in terms of what is the user seeing and what should they expect to happen. So in this case, I'm expecting the user to see the title of my shared link. I'm expecting them to see the points. I'm expecting them to see who the author is. I'm expecting them to see how many comments there are. And then I'm expecting them to be able to click on this up and down link. And I'm expecting this arrow to link off to the correct site that we passed in as the link. So that's quite a lot of tests. Um, so when I'm thinking through this, usually I'll say it because we have our it block. And then you can also say skip. So it'll skip over that particular test. And then I'll just stub out what is this test. So that's kind of the building block that you're working with. But I'll skip over this test. I'll just make this like my to-do list. I'll write all the tests that I'm going to include. So I, it should, it should display the right title. then um actually we could or we could change this it displays the right title it displays the number of points it displays the author it displays the comment total let me spell that correctly it's um handles the upvote and it handles the downvote, and then it links to the correct link or URL that we passed in. Okay, so these are all the tasks that we need to run. Now, if I come back over to warp, you'll see that these all have open circles. So, it skipped all of these tests and it's only passing the one that we completed here. So, now we can just use this as our to-do list and walk through this one by one. So, I expect it to display the right title. So, the first thing that we need to do is we need to set up our test. So, to set it up, we need to render that component out and actually i'm going to because we're going to be changing some of these things here i'm going to get rid of this i'm going to pull these in as props which is probably what i should have done in the first place but this is fine so i'm going to do points is going to be 10 we can see if this was the problem or if there was another problem the author pass this in as an object we have our comment counts that we're going to pass in as a number, it needs to be an equals then we have our title, so it's going to be equals we're passing in the actual link and I think that's good yeah I just didn't like that spread argument so now I'm just going to copy all of this render block So render, I believe that's coming from the JavaScript testing library. And actually Kent, who I mentioned earlier, he's the creator behind the library. And what that does is that just makes it easy to test JavaScript components easily. So it works with SvelteKit and Vue as well. So we have rendered out our component that we created. We passed it in. And then we want to assert something. So I can say, we wanna make our assertion. and say, you can see Copilot helping me out. I'm gonna try and walk through this a little bit more slowly. Actually, let me delete this. So the first thing that you want to do is you want to grab the elements here. We've got to grab the title if that's what we're going to check. So I'm going to grab it. So I'll say title, and I'll just say screen is what allows me to grab that component off the screen. And this is where IntelliSense is really helpful in being able to tell what properties do I have available to me? So I want to get an element by the text and I'm going to grab the Redwood JS title. So once I have that, I think it's just saying because I haven't done anything with it yet, then I want to set our expectation. This is still kind of setting things up. So I'm expecting the title to be in the document. Curious why. and see what's happening. I'm gonna check warp. Okay, so I have a failed test. This is good, cause then you see what a failed test looks like. So the problem is that screen.getByTest is not a function. So I don't think I wrote that correctly. I'm trying to remember what the syntax is. It's come down, let me comment this out, comment this out. Usually I'll do it all in one go. Screen, there we go. There we go, it's a function, not a property. Sorry about that. Oh, I thought it was. Let me see what, just a second. Let me check my notes here. Let's pull this up. um probably something a dumb typo that I have I think you just need to expect oh sorry nevermind you're good uh back screen let's see if that That's weird. Oh, you know, I know what it is. We didn't import screen. Gotta import it for it to know what's going on. No wonder my syntax wasn't working. There we go. See if that, it would be in the document. There we go. Now it clears out. So my syntax was right, I just needed to import it. Cool. I appreciate that. Let's see what. Perfect. So now if we come back over to warp, it should say that both of our tests are passing. Pretty cool.

10. Testing in Redwood

Short description:

Testing in Redwood involves using different methods to grab elements, such as 'getByText' and 'getByAltText' for images. However, using 'getByTestId' is recommended for better user experience. Although 'getByTestId' is less visible to users, it can be used as an emergency hatch to find elements. It is important to ensure that the test IDs match the elements being tested. For example, a test ID can be added to an element using the 'data-test-id' attribute. Writing tests involves creating assertions and removing the 'skip' keyword. Tests can be run individually using the 'only' keyword. It is also important to handle cases where the expected element is not found, such as when the text is broken up by multiple elements. In such cases, wrapping the element with a span and adding a test ID can help in locating the element. Overall, there are several tests that can be written, including those for points, author, comment total, and correct URL.

Okay. So, now let's go down to the next one. And a lot of times testing is going to feel like copy and paste with this. But as much as you can, get by text is your friend. If you're dealing with images, get by alt text is also your friend. And you can see I should have better IntelliSense now that my package is imported correctly. So, if I say expect screen dot. And a lot of times I'll use this. Yeah, this list looks better. I'll use this list to figure out what I'm looking for so like get by roll kind of the like your emergency hatch when you're trying to find being able to grab an element with testing is this get by test id so the more that you can use other things is better because that's what users are going to look for they're looking for the text that you see or if you're dealing with accessibility, you're going to use that alt text piece here.

But the sometimes it's just hard to grab things. And so you can use the test ID. And the reason that it's not quite as good as because like I mentioned, users don't see that, but also it makes the test a little bit more fragile. So if the test ID changes, then your test will also break. So let me give you an example of what this actually looks like. If I wanted to say grab this up button, I could say data dash test ID and give this a value. And so now I can reference that particular element within my test by using the data test ID that we just created. So you have to make sure that those values line up. Cool. So I'm going to, I'll just write a couple more tests and then I'll let you guys have an exercise to be able to write tests by yourself. So let's do one for points. And then you can try and do some of these other tests that I've just written. So I'm just going to copy and paste this whole block. Now remember, you have to remove this skip. So we've talked about skip. You could also say only. So it's only going to run that test, that one test that we created. I'm going to remove the skip. And so now what I'm doing is I'm testing for the points. And here, I want to make sure that my points is 100, and I expect that to be in the document, so if I come back over to warp, you can see that it did not, I did something wrong, able to find an element with the text of 100, it's probably because it's looking for something different, give me just a second, so the nice thing about this is it tells you, like, there it is, it's getting there, it's just not finding it the way yet. Look right here. The text is broken up by multiple elements. So that's probably what's what I would guess is happening right here because we have a break in what we're looking at. So let's just prove what I was talking about with the data test ID. What we could do is we could wrap this with a span and say data test ID. It's a points. And now if we come back over to our test, I can say it by test ID and we want to grab it by points. There we go. Let's see. Points is not defined. We'll see what happens. Okay. So now look at that. Our test is passing. Cool. So I'm going to hit pause. If you have been following along, there's five more tests that you can try and write. you don't have to the clicking I can show you how that works but those are a little bit more complicated we actually haven't written the code for our button but if you want to do the author the comment total and the correct url I'm going to open up the break rooms again and again you can either work by yourself or join a break room

11. Database Setup and Table Relationships

Short description:

When working with databases in Redwood, you can think of them as a place to store information. Tables inside databases are like spreadsheets that refer to each other. Redwood supports SQLite and Postgres, with Prisma handling the data formatting. Establishing relationships between tables helps minimize redundancies. The main data types we need for our application are user, link, vote, favorite, and comment. These tables are linked based on relationships, such as a user marking a link as a favorite. We'll establish these relationships and ensure data consistency throughout the database. Let's start by defining the user table, which should include an ID as a unique identifier.

So let me pull up my screen again. I'll show you some of the other things. This was a website that I built for our, actually, let me pull this up in incognito. This was a website that I built for our RedwoodJS conference that we did in September. And it's just ticket.redwoodjs.com. You want to check that out, but you can, here we go. click and drag the badge around, but there's like a full application. There's a whole back-end component to this, which is where Redwood would make probably the most sense. You can run it because we've been mostly living in that web folder. You can create like a landing page with just the web piece of it and just focus on the front end inside the web folder. You can also just create, use the back end, which is how we'll spend the second hours looking in the API folder. And there's actually a company that is in Australia called BuildPass and they their application uses only the API folder of Redwood. So I'm not exactly sure why they just use the API piece of it and not the web piece together. But just to say that you could use just the front end or just the back end or both together. So, yeah, it really shines if you're trying to build build an application. So just by the show of plus or minuses, that was really helpful last time. How many people have experience with working with databases? You know, kind of help me determine how much time, how much in-depth I should go in talking about— Okay, perfect. Thank you. Cool. Oh, that's great. Kind of half and half. Perfect, perfect. Okay, great. I'll wait and just double check. If you're a minus, don't be embarrassed. That's actually really helpful to me because then I will spend a little bit more time on it, but it looks all the responses I've gotten so far are mostly positive. If you've worked with a database before, or you're familiar, you're comfortable. Okay. So, okay, perfect. I can do that. Thanks, Vivian. So when you're working with databases, you can kind of think about it just as a place where you're going to store information. And so you have tables inside of databases, and it's almost like a spreadsheet where you have one table and it refers to a second table or a third table. So every table that you work with in whatever application you're using. Now Redwood, you can use SQLite or you can use Postgres. I usually reach for Postgres. And that's just the way that the data is formatted. But as I'll show you, you don't have to worry about writing raw SQL code. That sounds miserable to me. So Redwood takes care of a lot of that for you. Well, more specifically, Prisma takes care of a lot of that for you. So I'm just going to get my notes up here. And we'll walk through the database setup for our application. So if I pull this up, there we go. So it helps, obviously, if you have a design to work from. And you can see exactly what data you're trying to collect. And then you can establish what those relationships are going to be. So that's what we'll do right now. So we'll go ahead and kind of walk through this. And then in the readme, I do have a link to this page right here that shows how all this is mapped out. But we'll kind of walk through it a little bit more slowly. So we have, let's talk about all the different types of data that we need. First of all, we have a user. We need data for the user that's logging in and creating these links and how they're interacting with those links. Then we also have a link that somebody submits. And then we have the, what else do we have? We would have the vote that somebody makes on the link. Are they voting it up or are they voting it down? We have to be able to track that. And part of dealing with databases is you want to find ways that you're not creating multiple types of data. Like I don't want to have the user's name here and in the vote and maybe that they submitted it. You want to create those relationships to minimize redundancies. And part of the reason is if a user comes in and changes their email address, you don't want to have to go throughout your entire database, be able to like change all the instances where they're doing that. You want to change it in a single place and have all the relationships automatically update. So we have a user. We have a link. We have a vote. We have maybe a table of favorites. Like has a link been marked as a favorite? And we also have a comment. So if the user comments on the link, we need to be able to track all those comments. And then, I don't think we'll get into this piece of it, but if a user, like say, voted on an actual comment to vote that up or down. And I think this just about covers all the main things that we need. I'm going to change this so we're just a little bit more explicit with the type of because this is really going to be a relationship. Right. Because we have a user and a link and we have to say that the user did mark that link as a favorite. So we have to establish a relationship between these two tables. So if I say favorite link user, you can see that we're referencing the link and the user. And I'm just putting these in alphabetical order. I think that's a general convention. I don't think that's just a personal preference, but it is a personal preference. So I'm linking the link table and the user table to specify the favorite. And then the same thing with the vote is I'm going to link the link table. I'm going to call this one, oh, that's not consistent. Let me make this consistent. I don't think I made it consistent in my application that I built. Let's say vote. that word first. There we go. Okay. So we're going to reference these two things and then we have our comments. So let's start with our user table. What's all the information that we need to include? Well, every single table in your database should have an ID.

12. User and Link Information

Short description:

Every table in the database should have an ID for easy reference. User information includes email, nickname, first name, last name, and social media links. Redwood provides tools for authentication. Link information includes title, link, submitted by ID, created at, and updated at. Relationships are established between tables using IDs.

What's all the information that we need to include? Well, every single table in your database should have an ID. This just makes it really easy to reference in the future so that you can find that specific piece of information that you're looking for. So this is going to be in our case, an integer. Then we will have their email address, which will be a string. Then we'll have I'm going to call this a nickname. So this is like this could be considered a username, but it's not what somebody is using to log in. I called it a nickname because if you go to say profile slash whatever the username is or their nickname. That's kind of like a vanity URL. That's where you would use that because I don't want to expose the user's email and I don't want to expose their ID either. So a nickname is kind of an easy way to do that. Now this nickname. Yeah, I think that's good. I was gonna say you can make it optional, but I think every user should have a nickname. Then we're going to look at the we want them to have their first name. And maybe we make the first name optional. Somebody They didn't want to give us that information. And then their last name. And we'll also need some information for authentication. I'm going to leave this off right now because Redwood has some tools for working with databases. Or, sorry, authentication. They make it really easy. So when we get to that section, we'll just let Redwood take care of that. Then we also have maybe on their profile, we want them to include Twitter or X. and then maybe a Facebook link. They're still on Facebook. And I guess we could do Instagram. That's maybe more popular now than Facebook. A string and then LinkedIn. That could be a string. Actually, let's make this all lowercase. And then we'll say for GitHub, we'll have a string. Okay, so this is all the information we wanna collect about a user. For the link, we're going to do something similar. Let's just make a list of all the information that we need. And then when we go over to build that out within our application, this will be easy. We just have all the information already listed out. So as I mentioned, every piece of information in your database needs an ID. Then for this, we'll have a title and that will be a string. We'll have a link, which will also be a string. Then we'll have maybe submitted by ID. That'll be an integer. So this is going to reference, because we're using the ID, it's going to reference something else on another table. Then we'll have created at, which will be a date time. We'll have updated at, which will be a date time. And I think that is good for links for now. so as we were talking about this id field here for submitted by id is going to reference this piece of data here on our user table so we can draw an arrow to show that these are linked together so a user can have multiple links to it a link can only have one user that actually submitted it If you had, say, a user with multiple links and a link with multiple authors, you'd need another database, another table in your database to actually link those two things together.

13. Setting Up Database Relationships

Short description:

Let's translate the database relationships we discussed into code. We'll use Prisma, an Object Relationship Manager, to handle the relationships within our database. Prisma creates an API layer between us and the database, making it easier to interact with. We'll define the relationships between the tables using IDs and enums. The relationships include one-to-many and many-to-many relationships. We'll also set up the database using SQLite, although Postgres is also an option. Prisma will handle writing the database calls and building the tables for us. In the schema.prisma file, we'll define the models and their fields, including IDs, strings, integers, and date times. We'll also have a sneak peek at a finished whimsical diagram for reference. Let's head over to the API directory in VS Code and set up the database.

Okay, now let's go to the vote for the user here. We have our ID again, because we do need that ID field. So let me make this a string. Then actually we can make this an integer. uh we have a link id that's going to link to our id up here on our link table and then we'll have a direction so a user can vote it up or vote it down now this is a little complicated we were talking about how we don't want duplicate content within our database and so if we have several entries that say up several entries that say down that could be a place where we could introduce a bug easily. So let's create, I'm not going to create a table. I'm going to create an enum for this. And so what this does is this allows us to specify one type of, the type of information and kind of lock that down. So we're just going to say that this could be up or it could be down. Notice we don't really, we don't need an ID for this because we're just, we're forcing this to be the value of that the user is using so here the type is going to be vote direction okay and then i think that looks good oh we need the user we have to assign the user that actually made that vote so that will be a integer so let's set up our relationships We have our user ID that's pointing to the ID on the user's table. And we have our direction here. So this is going to be related to our enum. And let's get this arrow. There we go. And then we have our link ID. So this is going to be related to our table here. I'm going to... These lines look they're starting to merge together a little bit. There we go. A little crisscross. Okay. Now for our favorite link user, this is going to be very similar to our vote link user, except we don't need the direction. We can just say ID type of int. We want to give this a link ID of a string and a user ID of an integer. So now if we say this is going to point to the ID on our link, link table and then we also have our user id here it's going to point to our id on our user table that is looking good here is getting weird okay and now we have our comment oh yes that's a question is this one to many or many to many um and so what we'll do is we'll use prisma and i'll talk about prisma if you're not familiar But Prisma is a ORM, which stands for Object Relationship Manager. And so that manages all the relationships within your database. And it creates almost an API layer between you and your database. So you're not having to make direct database calls. It will handle all of that for you and just becomes a lot easier to interact with. So Prisma is using JavaScript. So we're talking about front-end to back-end. We're doing everything in JavaScript, which is awesome. You only have to know one language. This right here is gonna, just showing how those relationships work with all the tables. And so when we get ready to write our schema, and actually I'll give you a sneak peek. This is on the finished application what this looks like. So we're going to list out all the fields and their types together. So, and then we'll run a migration. So we can talk about all that stuff. So with the comments, let's just do, this is our last one that we need. We have an ID and this is going to be a string. Oops, there we go. And then the other field is gonna be a body, this is string. And then we'll have our link ID, which will be a string. So that's at that relationship. We have the author ID, which is an integer. Then we'll have the created at time, which is a date time. We'll have the updated at, if I have spelling right, which is a date time. And then we'll have, maybe if we do threaded comments, you could have a nested comment. So I'll say parent comment id, so this will be a string. Now this one's kind of interesting because when we start talking about relationships, the parent id actually comes up. Oh hey, it went all the way around. But you're referencing the id on the, like a different comment id. If that makes sense. So it's like it's pointing back to itself. There we go. That looks better. So here I'm going to take the link ID that's pointing to our link table. And then we have our author ID. And that's going to be on our user table. These lines are getting a little squirrely. OK. And then we have, I think that's it. So those are all of our relationships. Now, if you want to dig into this a little bit more, if you look at the read me that has the agenda on this, the I think that's down at the bottom. Let's see. Database. I did include a link to a finished whimsical diagram. There we go. Under reference, there's the finished whimsical diagram. The errors might look a little bit different because I recreated what I'd already made. Okay, so we can use this as a reference now, and then I guess to circle back, this is recorded, so you can reference this later if you get confused or if you miss something. You're asking about the one to many, so you have one user that could have many links, and a user is going to have a lot of votes, and they're also going to have a lot of comment or favorites and they're going to have a lot of comments. One, a comment can only have one user. A link can only have one user. A vote can only have one user and one link and a favorite can only have one user and one link. Okay. So let's actually translate this into code. This diagram is great, but we actually need it to do something for us. So I'm going to come back over to VS code where we have our project that we started and we've mostly been hanging out in our web folder here but let's go over to our API directory so here under our DB folder there's a schema.prisma file and we haven't set up a database yet by default you have SQLite we could just we could probably just use that out of the box so SQLite just it gives you a file that you can use as a database usually I lean towards Postgres I'm a huge fan of Postgres, and when I do this, you can either get Postgres running locally on your computer and create a database, or a lot of times I'll reach for Supabase. So you can use, Supabase has its own API layer where you can use its APIs to make database calls, or you can just use it as a pure Postgres database. So if you wanted to use Postgres, you just change this provider to be Postgres instead of SQLite. I think, let's see if this actually works, I think I can just use this as SQLite and everything will just continue to work out of the box. And you can change it later. So that's the nice thing about Prisma. One of the things it gives you is it's going to write all the database calls for us. It's going to build out our tables for us. So you don't have to do any of that yourself. So by default, we have this user model that is an example. So it says, please remove the following example.

14. Database Models and Relationships

Short description:

We define the ID, email, name, nickname, and social media links for the user model. Prisma provides a VS Code plugin for autocomplete and intellisense. We create a model for the link table with ID, title, link, submitted by ID, created at, and updated at. We establish a relationship between the link and user tables using the submitted by ID and link ID columns. We also set up the relationship going in the other direction. We repeat the process for the comment model, including the link ID and author ID.

So we can go ahead and remove that. I'm going to collapse my sidebar and pull this up on half my screen. And then I'll pull up our whimsical diagram on the other half. So now we can just translate this into Prisma calls. So we have our ID, which is an integer. And you can see there's a few extra things that we've defined on here. We've said that this is the ID field. So this has to be unique. And that's how we're going to identify this particular user. And by default, we want that to auto increment. So we don't have to worry about what was the last entry. Now we added two, now we're gonna add three, it will handle all of that for us. Then we have Email, so we've already set that up as a string, and we said that it has to be unique, so you can't have a user with the same email address and in the saved. So that's what they're using to log in. Then we have a name, so we can either leave it as name or you can break this out into first name and then say last name. we have nickname that we created. And so we can make that a string. And let's make that actually say it's optional for now. So if it's an optional property, you add a question to the end. But I do want to make sure that our nickname is unique. Okay, so now let's go down to the next one. We have Twitter. And that's a string. We have Facebook. And that's a string. We have YouTube, and that's a string, you have LinkedIn, and that's a string. And then we have GitHub, and that's a string. Now, one of the things that's great about Prisma is they have a fantastic VS Code plugin. So I even included it within the workshop notes in the readme if you want to download and install that. And so as we start building out the relationships, they have some autocomplete and some intellisense that makes that a lot easier to create. So here, basically tables and models are kind of synonyms for each other. So we're gonna create a model for our link table. And here we have an ID with an integer. We have a title, which is gonna be a string. We want that to be required. We have our link, that's gonna be a string. We have our submitted by ID. Now that's when we're starting to get into relationships. I'm going to come back to that. We have our created at, which is a date time and our updated at, which is also a date and time. Okay, so I said I'd come back to this. Let's come back to it now. We're talking about this relationship. We have the submitted by ID. And what we have to do is we have to specify what ID is that referring to. So if you're familiar with database lingo, that's a foreign key. so what we want to do is the user id is an integer but we also need a way to link the two here so i'm also going to say submitted by and just to let it know that this is referring to the user table i'm going to set up a relationship here let me make this full screen so it's a little bit easier to read we're setting up a relationship here where the field that we're referring to is our submitted by ID and it's going to reference the ID. We're talking about the user. So here's the ID. This is what we're referring to. So this syntax might look a little funny. This is coming from Prisma and their API. Because remember we're working inside a schema dot prisma file. So just to kind of go over it again, I felt like it was a little fast and I want to make sure you follow. We created this submitted by ID that's saying this is an integer because our ID here is an integer. That's what we're referring to. And then we have to establish what that relationship looks like. So we're saying that submitted by is referring to the type of user because we have a user model up here. We're using we're creating a relationship that's based on the submitted by ID column. And then it's referencing the ID up here. So we have a few more relationships that we can go ahead and work through. So if that didn't make a whole lot of sense, we can come back to it. Now, if you're looking at this and saying, well, it's still red. Why is it red? We also have to establish the relationship going in the other direction with Prisma so that it can get the two going back and forth in both directions. So here, we'll say that we have a, we can just say link here and say that we have our links and that's gonna be an array of links. Cause remember, we have, a user can have multiple links. So that's an array and a link can only have one user. that's not an array. Okay, so we'll do this a couple more times. We have several more relationships we have to build out. We have our, let's pull this up in a side. We have our comment. Let's go ahead and take care of that one. So we have our comment model. there we go and we have our id which is going to be a type of integer it is a id we want to say that is by default it's going to auto increment we have our body which is a string we have a link id oh look it did this for me i'll try and slow it down we have our body which is a string and then And we also have our created at, which is a date time. We have our updated at, which is a date time. And then we wanna establish a link here for what comment is, what link is the comment associated with and who is the author of the comment. Awesome, that's so good to hear, Priscilla. So here, let's say that we have our link ID and that's an integer. And then now we have to set up what that relationship is. So we're going to say that we have our link here is a type of link. And some of this is copilot, but some of this is also Prisma, like I said, their IntelliSense is really great. So this is setting up the relationship. We're referring to the link ID column here and it's referencing the ID on our model, our link model here. Now again, it's saying that there's an error validating because we have to establish the relationship going the other way. So here we have links to set up, oh sorry, comments, to set up on our link table here. It's referencing an array of comments. It's going both directions. We still have, I think with our comment, that we still need to set up users because we have to have an author here. So we can say author ID is an integer.

15. Database Relationships and Migrations

Short description:

We set up the relationships between the author and user models, and the favorites and link models. We also established the vote direction as an enum. However, due to SQLite limitations, we used a string instead. Now, let's run a migration using the command 'yarn Redwood Prisma MigrateDev' to keep the database in sync with our changes.

Let me pull this up. And so now let's set up that relationship so we have the author that is referencing the user model. And then we're creating a relationship where we're referencing the author ID on that field. It's referencing the ID on our user field. So we're again getting red because we need to get that going in the other direction, too.

So if we come down here And we say that we have several comments and that is going to be an array of comments. Pretty cool. Okay. So we've gotten the easy tables out of the way. These are a little bit more complicated because you're establishing relationships between two, but it's still using the exact same concept. And I think we could maybe even... So if you're looking at the final repo, these names are closer to what I used on the final repo. And again, I used link user to show that these were the two tables that I'm linking between. But, if you want to make it, I think in this case, what we could do is even just say model favorite, which might be easier to refer to and think about. So we have our ID, because every table needs an ID. And we're gonna give that an ID. Set the default to auto increment. Then we wanna set up that link ID, Which is an integer. And as we're setting up that relationship we'll say that it refers to the link model, we're setting up the relationship so that it's pointing to that, excuse me, pointing to this column, and then it's referencing the ID on our link table. So now we've got to get this to go in the other direction. So we can say favorites. That's gonna be an array of favorites here. Now we've gotta set this up for the user because we have to figure out what user actually made that a favorite. So we can say user ID is an integer. And then user here, we're referring to the user model on the user ID column here. And we're referencing the ID on that user model. Now if we come up to the top here, and say favorites, and that's going to reference our favorite model. Cool. Okay, so now, I think this is the last one that we have is our vote direction. We've almost made it. Okay, so if we have our model and we'll call this Vote, set up our ID, because every table needs an ID. And then we have our link ID, which is an integer. And so we're gonna reference our link model here. I'm gonna go ahead and come up here and set up our, this was vote. So we have votes, which is an array, And then we need to do the same thing here for the user to say what user voted. So I'm just gonna say user ID is an integer. And we're gonna reference the user model, the user ID column, and the ID on that user model. So now if we come up here, we can say that we have votes with an array of vote. Now, the only other thing we have to include is that enum, we were talking about vote direction. So this is gonna be kind of like its own type. What we can say is instead of model, we say enum and I'm giving this two options for vote up or vote down. And what did it not like? Oh, okay so this is interesting. I'm getting an error because I'm using SQLite right now and SQLite does not support enums. So, enums is specifically a Postgres thing. So, just for ease of use for today, I'm not gonna worry about that then, and we'll just make this a string. We could set a default value. Well, I'll just leave that like there. Perfect. Sweet, so we have our database structure built out, and that's really all you have to do when you're building out your database. It's just a text file that says what all the columns are and what those relationships are. So now we have to actually do something with this. So I'm going to pull up the terminal. And I'm going to close this out because we're not using Storybook or Jess testing right now. I'll pull up another pane. And we are going to run a migration. So if you're not familiar with migrations, I think that's more popular in, say, with Python if you're using Django or if you're using Ruby and Rails. But they have this concept called migrations. And the idea is if I go say we're both working from the same Supa base database and I go into Supa base and I say I have I see your question. I'll come back to it. You go to Supa base and I make that change. Well, we're both working on the same project that could potentially break your code because you're making a change to Supa base. I'm making a change to Supa base. And so now we have a problem. Or if you have Supa base as your production database and then I have a local database and you go make changes to production, then all of a sudden my production database and my local database are out of sync. So it becomes really hard when you're working with a team of people or you're making changes and you have production data and staging data. So what migration does is it creates a file to say, hey, these are the changes that we made to the database. So that way you can keep everything in sync. And if I commit code and then you have your own code, it can look at the migration file and see what didn't line up. What's the difference and how do I fix it? So to create a migration with Redwood is really easy. You can just say yarn Redwood migrate DB dev. And so now when I hit Enter, what this will do, see, I use the wrong command. I had to say Prisma, I think. I think it's Prisma. See if that works. Shoot. What am I having a brain moment? Uh, let me just a second. That one, I did have it right. Yarn, Redwood, Prisma. Oh, I put DB in there. Okay. So I said it's Yarn, Redwood, Prisma, MigrateDev. And I may have put the wrong command in the notes. So I'll go back and check. But yeah, I see what I did. So what is asking for now is what is the migration? So I'm just going to say initial setup and you can create as many migrations as you want. So if you create this migration and you realize, oh man, I messed up. We shouldn't have called this column this or we need to change this around. That's totally fine. Just go in and change the Prisma file, then go back in and rerun the migration. So don't worry if you have like one migration, don't worry if you have 20 migrations, doesn't matter.

16. Database Setup and GraphQL

Short description:

We have created our database using Prisma and Redwood. Prisma Studio allows us to view and add records to our database. The ID type for the link table was mistakenly set as a string, but it should have been an integer. However, using a string for IDs can provide additional security by generating a unique UUID. Redwood handles database migrations automatically, generating SQL code without the need for manual writing. Redwood also generates the necessary types for TypeScript. We use GraphQL to access the database in Redwood, but in the future, Redwood may support other APIs such as Supabase or Zeta. GraphQL is widely used and popular on an enterprise level. Let's continue with a brief overview of GraphQL and pick up the pace.

Kind of the whole point is so that you see those iterative changes. So now it has created our database for us. Pretty cool. So because we are using Prisma, because we have all that shipped within Redwood, you can also say yarn Redwood Prisma Studio. And I hit enter. So Prisma Studio ships with Redwood and with Prisma. And now I can see these are all the models that we set up. These are all of our tables. So I could potentially come in. I'm not going to set up. Oh, I could set up a user this way. I can add a record now and I can just stub out my code this way to say Amy at Redwood, JS, Redwood, my first name Amy, last name Dutton, and then save change. So now we have our database created and I've already added data. Sorry, Priscilla, I promised you I'd come back to your question. So you're saying if link, this is a great question. So if the link ID is an integer, why is there a type of string for, okay, I probably messed up on that. But there are a few cases where I did use a string for an ID and I did use an integer for an ID And I can talk about that in a second. Let me see actually, I think it would have cleared Link ID is here. I think it would have thrown an error if I did the wrong type You see thank ID Think So all of those are looks like they're set up maybe I'm missing the air I messed up in Figma. My apologies. Yeah, so I can go back and fix that whimsical piece and update. My great. Making a note. So I'll push those after the workshop. But I can talk about that. So for example, an ID here on the user is an integer. That probably would have been better, honestly, as a string. um so with an id it's just going to auto increment so it'll be one two three four five going up however much you need for the comment here I was trying out the comment the link I think I did that I did that as an id here um what I was doing on the live project if you go look at that is a string and if you do it as a string it's going to generate a unique uuid which some people will will argue is um and if you do this you have to change this you can see that it's i think that's hold on what is the oh hold on i got the instead of auto increment this is uuid um and what this does is it creates this random string of content um so that somebody can't come in and guess so like i could guess what if my user id is 3, then I can guess, oh, maybe a 4 exists. And so I can test for 4. Or if I'm 3, maybe 4 doesn't exist, but 5 is. So I can kind of hack your system a little bit if you're just using plain IDs. But if you're using a string, it's this really weird generated piece of code, which makes it harder to like hack. So, for example, if I let me show you, I know I have this on the live, which is probably why you saw it on Whimsical. Here, when all the content loads, you'll see that, if I click on Google, this ID that's loading in the URL, that's the UUID. There's no way that somebody could guess what that is. So sometimes people think or consider that to be a little bit more secure. Kind of what I used when I was creating the app was, okay, is this ID gonna be exposed to the user in a way that they could guess it. And if it was, then I was, if it is exposed, I was using a string. If it's not exposed or it didn't matter, I was using an integer. But I mean, you can kind of pick and choose. So if I wanted, because I did change that to a string, then I'd have to come back and change this field here so that our link ID is referencing a string in all the places. I'm not gonna do that right now. I'm just gonna undo this. But if I did do that, then you could just run a new migration and it would update your database for you. Now, I might ask you to reset your database because you're changing that ID column, but you could run the command to reset your database. But like I said, Prisma takes care of all that for you. Okay, so we have our schema. We have our migration. And actually, let me show you what this migration is. Yeah, I'll show you what the hook is to access this on the front. So here we have this migrations file. When we ran that migration code, it created this folder called migration, with this weird timestamp, and then it took the name that we gave it initial setup and it added underscores. And then it created this migration.sql file. So the more migrations you have, the longer that folder is gonna, or the bigger that folder is gonna get. But you can see it created all the SQL code for our database and you didn't have to write any of it, which is awesome. I'm a fan. I've written SQL before, and it's not always fun. Okay, so now we have our migrations written. I showed you Prisma Studio where we could add content to our database here. Now we need a way to access it. So Priscilla, you are right in line with the direction that I'm going in. I think, let me see. Let me check my agenda and make sure you guys are. So, I think I moved that tab. Give me just a second. Grab, perfect. Let's pin this. Okay. Okay. So, we created our migration. And then the nice thing too. Yeah, I wanted to talk about this. The nice thing too is that Redwood will generate all of the types that you need. So if you're using TypeScript or anything like that, then it generates that for you. And as you make updates to your code, as we get into it, you can run this command to generate the changes that you make with the types. But again, we'll come back to that. Okay, so let's talk about GraphQL because you were asking about the hook for how do you get the front end to see the database? How do you pull all of that in? And so with Redwood, we use GraphQL. And if you peeked ahead at the agenda, we'll talk a little bit about the future of Redwood and React Server Components. So right now, Redwood is married. If you're using the website and the API side, you're married to GraphQL. and it won't necessarily always be like that. As we move into React Server components, you could use say that Supabase API, or if you like Zeta, you could use the Zeta API. You don't necessarily have to use... Or a completely different API. You don't necessarily have to use GraphQL, but right now we're using GraphQL. Personally, I really like GraphQL. It seems to be really popular on an enterprise level, but I'll show you what that looks like. So if you're not familiar with GraphQL, we can kind of talk about that. Let me see how we're doing on time. Okay, to pick up the speed a little bit.

17. Generating GraphQL Files and Resolvers

Short description:

We've run our migration and have studio running. Let's check out our GraphQL playground. We'll use Redwood generators to create GraphQL files, pages, and forms. Scaffold can be overwhelming but generates many files. We'll generate SDL files for each model, resolving any errors. The SDL files are similar to the Prisma schema but use different syntax for optional and required fields. Services handle the GraphQL queries and mutations. Redwood generates code, ensuring type safety and reducing redundancy. The users SDL file corresponds to the users.ts resolver file. Making changes in the SDL file requires corresponding changes in the resolver file.

So here, let me pull up warp. So we've run our migration. We have studio running. Let's check out our playground. So way back when, the very beginning of this workshop, when I ran YarnRedwoodDev, after I installed everything up here, we ran YarnRedwoodDev, it opened the front end that we looked at on port 8910. And it also opened up if you come on down port 8911. So I'm going to click on this, and this opens up the, this is actually the API side of our application. So if you go to, if you have Redwood running, and you go to 8911 and pull up slash GraphQL, this will pull up the GraphQL playground. So now that we have our database running, we have one line of data entered in as a user. Now we can play with that data inside of our GraphQL playground. So the cool thing, this is automatically included. You can click on this for docs and see that we have queries. And if you come down here, you can see a few things that we've already generated. Now, you can see the current user and Prisma. These are just basic things, but we've got to generate the GraphQL side in order for everything to show up. So I'm going to come back over to Warp, and we're going to use those Redwood generators that we were using before. So here, I'm going to say Yarn Redwood generates. You can do Scaffold. Scaffold is kind of interesting because it will create your GraphQL files. It'll create pages for you. It'll create forms and you can see all of your data directly on the site. So if you just want to style stuff like have Redwood generate it and then you just go in and change the styles, Scaffold is great. Scaffold, in my opinion, can also be a little overwhelming sometimes because it does create a ton of files for you. Actually, let's go ahead and just create one. I'll do Scaffold Link. I'll show you what I'm talking about. So it'll do all those things. I think that it'll kind of show like a warning at the end. Yeah, there is a build error because part of the problem is it can't, we haven't generated everything that it needs. But you can see it generated a cell, which we'll talk about cells. We're talking about pulling in the information. It generated a new link page. It generated our tests, created an edit page, a link page, all the things. So I'm curious, let me see what this, did let me do local host 8910 because this was our front end yep yeah it ran into a couple errors there so i usually like i said i usually don't run all of that because it it does generate a bunch of stuff for you so if you come into components uh that was the one we already created let's see pages it looks like it was just a build error so it didn't do it okay cool that's good because I wanted to take this one step at a time okay so I'm going to say yarn redwood generate we're going to say SDL because that's what we're generating on the background generating an SDL file and we need one for each of our models so as far as I know you have to type this line for each model that you have so it says that there's an error and basically that's because we've created relationships see looks like you have a link model in your prisma schema for a relationship, but we don't have an SDL file for your link yet. So we've got to do that for links. If you see an error there, don't worry about it until you've written everything. So you can kind of, it'll should kind of tell you what you have to write. We can, yep, looks like you have a comment model in your Prisma schema. So we don't have a SDL for our comment yet. So let's write that for our comment model then let's see what else does it need once a favorite model whoops so now it'll do it for favorite and then it's saying we have votes we haven't done it for vote yet perfect so now i've actually gone through all of my models so you'll see that there's no errors. So if you, like I said, if you start seeing all those things when you're generating SDL files, don't worry about it. Just kind of follow the arrows, errors, and it'll kind of guide you through all the things that you need. And you'll see that my issues over here on the left with my server cleared up as well. So now that we have those created, I'll show you what files are created. We're still in the API directory. This is inside of our source. We have a GraphQL folder. And this created all these SDL files. And if you look at this, this is very similar to the Prisma, the schema that we looked at. But the one main difference, I will point this out, is that our schema.prisma file, anytime we had an optional parameter, we used a question mark. The GraphQL uses the opposite. And so anytime it's a required field, it uses an explanation point. So sometimes that can get a little confusing going between the two because they're referencing the opposite. We created a SDL file inside of our GraphQL folder for all of our models. And then under services, we now have a folder for each, basically for each SDL file. So if you open this up, this has scenarios where if you wanted to mock data out and use that for testing, created a test file for us and then you also have your services and this is uh if you're not familiar with with uh GraphQL what it does is you establish your types so I'm saying these are my types for my users these are the queries that I want to run so I want to be able to grab all of my users and I want to be able to grab an individual user and then these are my mutations that's for all user definitions. So if you're thinking, oh, you skipped over these, this is just a way of saying when I create a user, these are the fields that I wanna collect. And that Create User Inputs gets passed in here so that you're not having to retype all these out each time, you can actually just kinda use a shorthand. So that's where that's getting referenced. So I'll say it again and just walk through it a little bit slower. But with GraphQL, you're defining the types that you need. fields that a user will have. And we have, these are the fields when you're creating. These are the fields you have when you're updating. And then you have a list of mutations or sorry, mutations are down here. So mutations is anytime you want to mutate or change the data. So if you're creating or updating or deleting, you're changing that data. If you're just querying for it, like kind of selecting it, then you're using a query. Okay. So Priscilla asks, so the yarn generate for all these models would automatically justify the type for all your data that's right so all of my data is tight safe everything and i didn't really have to do anything i just defined say didn't do anything i defined it here in my schema dot prisma file and then uh if you normally work with other projects with graphql you have to write all this stuff out yourself you also have to write out all of your uh resolvers which we'll talk about in a second you have to write all that out yourself, and it just becomes very, I don't know, copy-paste, copy-paste. You feel like you're very redundant. You feel like you're writing the same thing, so Redwood generates all that for you, which is really nice with that generate command, and then it just makes sure that all those types match up with that schema file, so if you do something different, it will realize, it'll tell you, hey, you're not doing something right, so we have our users file here. We talked to, sorry, we have our users.STL file. We have our types, we have our queries, we have our mutations, and then resolvers is how it figures out what to do with that. It's like, okay, yeah, you said you were going to query all this data. How do you actually query that? Like, what are you actually doing? Like that, where's that coming from? Or you're saying create a user. Well, how does it know create a user? Where did, what handles that code? Well, that's here under services. So we have here for users.ts because it's a TypeScript file is our users file. And this is where we are resolving, we're telling GraphQL how to handle all those things. So if you pull up the users SDL file, I'm gonna pull this up in one pane and I'm gonna pull up my users.ts file in another pane. We'll get these side by side. So anywhere where I have a query, it should have a corresponding piece here in our users.ts file. Just trying to move this over a little bit. There we go. So you can see here, users has a corresponding users here. User singular, where I'm passing in an ID, has a corresponding user right here. So if you make any changes in your SDL file, you'll also want to change it in your resolver file because those two are linked just by the name that you're using. So like create user. Well, here, here's create user. Here's the code that's actually creating the user.

18. Exploring Prisma and GraphQL

Short description:

We explored Prisma and its usage in creating a user. The GraphQL playground allows us to write queries on the front end easily. We can specify the data we want to retrieve, making it more efficient than REST APIs. The returned data is already in a JSON-like format, making it easy to work with. We can copy and paste the GraphQL calls into the front end. Prisma uses JavaScript to create the GraphQL API. The Prisma schema file defines the GraphQL structure, while the corresponding resolver file handles the JavaScript code. We also created a link using Prisma Studio and established a relationship with the user. VS Code is a popular text editor for coding, providing features like IntelliSense. Prisma Studio simplifies the process of querying the database and viewing relationships. We added a record for a link and saved the changes in Prisma Studio.

I know we didn't dive too far into Prisma other than the fact that we created our schema.prisma file. But this is a Prisma call. This is part of the Prisma API. So if you look at their documentation, you'll see that this is how they're creating a user. You're calling the database. You're calling the user, that table, that model. And you're creating a user. And in this data object, you're passing in all of the data to create that user. And we'll kind of break this down a little bit more if this is a little overwhelming to show you how with that GraphQL playground that we started to look at, it'll help you write those queries on your front end. So actually let's jump over there now. So if I come over to Chrome, we pulled up our playground. Now remember, anytime you run yarn redwood dev, it's gonna pull this up. So we have, as soon as we run yarn redwood dev, we have port 8910 that shows the front end and then we have port 8911 slash GraphQL that's showing our GraphQL playground. Now, if I hit refresh, so you'll notice I just have some general information about Redwood. If I hit refresh and now go to our folder, you'll see I have all of our models that we created right here on the left, which is really helpful. So let's say I want to grab all of my users. So I'm gonna expand this, and you'll notice as I click on this, this code actually changes for me. So I'm going to grab the ID. I'm going to grab the last name and the first name, and I'm going to hit play. And you'll see that it grabbed all of my data. And the nice thing about GraphQL that I really appreciate is it's already in a format kind of like JSON. I think that is JSON that it's returning. So you don't have to do anything to reformat it. It becomes really easy to work with. The other nice thing about working with GraphQL over say like a REST API is you can specify what data you want to grab. I'm not like calling a rest API where it's going to give me every single thing that I need. You only have to ask for the parts that you want for that particular component. So when I'm working on a front end now, this is my GraphQL call. That I can then copy and paste into the front end. Pretty cool. So let's come back over to the front end. I know we created. Let's see questions. So you use JavaScript and all the components, but use GraphQL for database creation. So you're using, it's still actually, let me pull this up. This is still JavaScript right here. This is a Prisma JavaScript code. So I can even configure things here. Like say I, I don't even know what I would wanna do here, but I could console.log stuff. If you console.log, that's gonna go into the terminal and not the browser, because we're on the API, on the API side. So, but let's see, schema.prisma. This is a, I guess, Prisma syntax for being able to generate the GraphQL for us. The SDL file here, well, this is a, it's still a TypeScript file, but you can see here it is writing GraphQL. That's how you know that it's GraphQL. It's GQL and that back tick. And then, until I've been talking for a while, the corresponding file, this is a JavaScript file. So you can see users.ts And the Prisma call that you're making here is JavaScript. So let's go, let's kind of connect some of the dots here. So we focused on the front end, we built a component. We have our users or our backend here. I know we added data for a user, but let me come over and create inside of our studio here. I'm gonna create a link so that we can use that link component that we created. So I'm gonna add a record here. I don't have to add auto increment because it'll take care of that for me. And say redwood.js, Hetps, redwood.js. Yeah, sure, Mohammed. So I have, this is the reference repo. Wish I could like, don't know if there's a way to pin that to the chat. Let me see, nope. Okay, I'll just keep moving. Yeah. So with Redwood, if it's your, yeah, perfect. How to use Redwood JS and VS Code. So VS Code is just a text editor for writing code. You could write standard HTML, CSS. You could write, you could use Sublime or you'd even use text edit to edit your text files. The nice thing about using VS Code is that you do have the highlighting and with some of the extensions, it makes it a little bit easier in terms of IntelliSense because you've probably seen, like when I start typing, sometimes it'll autocomplete for me. And just so I don't get fat fingered while I'm demoing, that's one of the reasons why I've been, I mean, I use it generally when I'm writing code, but also I've been leaning on it. Okay, so I'm going to come back and get that data for my link added in. So I have my link pulled up. It's submitted by now. This is the nice thing. Yeah, sure thing. This is a nice thing about working with Prisma Studio. Instead of having to go see what the ID is for that user, I can just click on this, and check that this is this user, and so now it's related. We don't have any comments or any favorites, so now I'm gonna save that change, and I'm just gonna add one more.

19. IntelliSense Plugins and Database Links

Short description:

You can add IntelliSense plugins one at a time. Co-pilot is a helpful plugin that requires a monthly subscription. Prisma Studio allows for easy data manipulation. You can save changes to the database and establish relationships between records. RedwoodJS and React Summit are examples of links added to the database. The Redwood router handles linking pages together. Cells in Redwood are used to get GraphQL content onto a page.

Yeah, so you're asking what IntelliSense plugins I have this kind of have this blog post that I wrote a while back I'll include it in the chat but it has all the extensions that I'm running I'm running a lot you don't need all of them but here I'll just there's I have 65 going you can also if you wanted to mimic my setup I think there's a link at the bottom to download yeah you can even download the gist from github and that'll give you the exact same setup that I have on my machine If you wanted to just download all 65, but I might suggest just adding one at a time.

Cool. Co-pilot. You are asking about plugins. Co-pilot is also really helpful, but you do have to pay for a co-pilot. I think it's $10 a month. Okay, so I'm going to come back and get that data for my link added in. So I have my link pulled up. It's submitted by now. This is the nice thing. Yeah, sure thing. This is a nice thing about working with Prisma Studio. Instead of having to go see what the ID is for that user, I can just click on this, and check that this is this user, and so now it's related. We don't have any comments or any favorites, so now I'm gonna save that change, and I'm just gonna add one more. We'll say RedwoodJS. Actually, let's do React Summit so it looks completely different. I think I have the link. Or reacts summit. Yes, save to my clipboard and then this is submitted by me And it automatically fills in the crew. That's not the right created at date. That's interesting You can set the default created and updated dates. I don't think I did that that looks like it was set in 1970, okay, so let's come over and I'm going to update my query here so that I'm pulling links So you could just grab it by a specific link if you knew the actual ID. I'm going to do it this way. OK, so here's all the links that I have in my database. Now, I'm going to come back over to Yes Code where I have my front end here. I have my shared link component. And I'm going to run a new command in the terminal. And this one I'm going to call. We don't have any pages. I should realize that we don't have any pages in our application. So let's create a page first. So we can generate that and say yarn redwood generates a page. Sorry. Yeah. Generate page and I'll call a links page.

Okay. So you have a question. If users deactivate their accounts, would it also reflect on the database? So you'd have to write code to delete the user. And I will, I actually don't know if we'll have time to get to this because I tried to overload. I would rather have more content than too little content. But if you go to redwoodjs.com slash docs and search for authentication, if we have time, I'll talk about this. But there is a section here under self-hosted. And what this does is you can run this generate command and it'll set up all of your login pages for you. It'll set up your reset password pages for you. It'll set up your signup pages for you. and then it handles most of that stuff for you. So, cool. So let me come back. Got our links. We generated our page. So when it generates the page, we haven't talked about this. It's very similar to generating a component. Inside of my web directory, I have a pages folder. And yeah, Priscilla, thanks. I am a fan. So in pages, we have a links page now with some dummy content. And if we go to the front end, so if I look up local host 8910, it says, hey, here's a list of pages that you've created. We can click on the links page and there's the component. Now, I mentioned earlier that Redwood has a routes file. Let me pull that up. when I ran that generate command, it created basically a route component with saying what the path is. So you can get to that by saying slash links. And then it's saying what component should we reference? So I'm referencing the links page component. I'm going to call this route links. And that's helpful for when you're trying to link pages together. So for example, if I come back over to the terminal, let's generate another page, except this time, maybe I call this page, my latest feed. We'll do it that way. Perfect. So now when I come back over to VS Code, I have a latest page folder with my latest page that we created. And then inside of my router, I have latest and links. So the cool part is what I can do is I can link the two together. So say on the latest page, I want to create a link here to that links page. Well, I have a link component inside of Redwood. I can pull that in and then you can use to and then you pass it routes and then the name. So if I look at that and says links, you'll see that this is passing here. It's going to links and the link is going to be called links. I'm calling this function called routes to set up that link. I think it's just a component. So now if I come back over to my page over here and we're looking at our latest page so now let me go to my latest page link and i want to go to the links page i can click now this is where the route file is super handy um say i want to change the path on this i want the links page to be my home page okay so now when i hit save if i go to where i had my this was localhost c 8910 this is the homepage, I didn't have to do anything. It's not loading the splash page anymore because I have a homepage. And I didn't have to change my latest page, I didn't have to change this link cause now it's using a named link and it will update the links automatically. Which is really nice if you start trying to change the URL structure, move things around, you're not having to move files and folders around. Your router is handling all that for you. So now that I have a place for those links to live, We need to actually get that content. We need to get that GraphQL onto that page. Well, Redwood has a concept called, I'll come back to your question, Priscilla. Redwood has a concept called cells. So I'm gonna generate a cell, darn Redwood generates cell and I'm gonna call this links. So you'll notice that when you generate pages, Redwood adds page. Well, now that I generated a cell, it added cell onto the end.

20. Using Redwood Cells and Mutating Data

Short description:

So in Redwood, you can create a cell that handles different states and delivers the necessary data. By using a Redwood cell, you don't have to write code for handling loading, empty, or success states. The cell handles all that for you. In the cell, you can query for data using GraphQL. The cell will pull the data and pass it to the success component. You can customize the success component to display the data as needed. To display the cell on the front end, import the cell and add it to the page. The cell will dynamically pull in the data from the database and display it on the front end. Redwood also provides type generation for TypeScript, making it easier to work with the data. You can use Redwood's form component to create a form for submitting data on the front end.

So you can, this is helpful if you have a links page, say a Lynx layout, a Lynx cell, a Lynx component. That way, they're not gonna conflict with each other. So if you look at the cell that it created, it has several different states. And so anytime you're having to grab data from, say, a database or some other source and pull that into, say, a React component, you have to account for what is the state of that thing. So is it loading? Am I showing a spinner? Is it empty? Were there no results? was there a failure like was there a problem or was there a success state so you have to create conditionals for all those things and check whatever the current state is well that's a lot of code that you have to write especially if you're working with multiple components you have to write those things multiple times so the nice thing about a redwood cell and again this is kind of unique to redwood is that you can create the cell and the cell will deliver what it needs at that time. So for example, it knows if it's loading, so it's going to display loading. It can, it knows if it's empty. So I don't have to do that. It handles all that for me. So the thing about a cell is that a cell has to do when you're trying to query for data, when I'm trying to grab data from the database. So it's going to handle all those states. Well, hey, look at that. There's some GraphQL up here because we have this GraphQL command. So what if we take our GraphQL from our Playground. I'm going to come back over here and I'm just going to copy this query and I'm going to come back over to VS code and I'm going to paste this in. Now I'm going to use their name, Query, here. And it looks like, I think that's right, yep. So don't change the name Query because that's important for the cell. That's how part of the wiring works, but the query here does give it the name that we're calling. And I'm saying, hey, grab all the links for me. So, and you can see, look, inside of our success component, it's gonna pull the links, because we're calling the links here. It's gonna pull all the links and pass that into our success component. And then it's gonna, this is the boilerplate code, we can change this to be whatever component we want. But it's gonna map over all that. So, I'm gonna hit save. Now let's go to our front end. Oh, I need to actually put this component on the page. So, let's stick this on our links page here. I'm just gonna swap all this out and I'm gonna put in my links cell. And here at the top, I need to import that link cell from source components link cell. And then I can get rid of this because I no longer have that. Okay, so now if I'm looking on the front end, there we go. this is our homepage, and this is our data that we're getting back from GraphQL from our API layer. Kind of cool. So let's do this. Let's jump over to, back to VS Code inside of our links cell here. What we could do is we could say, instead of returning a list item, actually wants you to push a pull in that's a share link component that we created earlier And because this is TypeScript, I can hit command period and it click add missing attributes and it'll fill in all the props that it needs. So it needs points. We didn't pull in our points so we could add that up here. The author information let's see, let me update this query to be exactly what we need it to be. That would probably be the easiest. So we also wanna pull in submitted by so you'll notice it creates that relationship for us. When I get the ID of the user, their first name, Last name. Let's see what else we need. We want, I'm not going to worry about comment count right now. Title, let's see, that's down here and then we have our link. I think that's everything. Okay, cool. So, I'm going to grab this code that it generated for us and you can even test that out if you want to just to make sure that it's working. So, I know for me that's really helpful sometimes when I'm like, why is this query not working? You can test just the query on the back in to see if it's working. So you can know, okay, is this a breakdown on the API side or the front end side? So I'm going to come back over to VS Code and we're going to update this links here so that we're grabbing all the things and passing in links, links item. Here we can say item.submitted by dot first name now you'll notice it's saying hey this type doesn't exist and so this is one of the things saying that need a key property to this is one of the places where it's helpful with redwood is that you can generate the types if it yes it doesn't automatically update so if I come back over to the terminal and say yarn redwood generate types it's going to automatically generate the types now based on the changes that I've made up here. So the types that it returns will be correct. Here we go. You might have to reset your, or restart, sorry, your TypeScript server. Let me make sure I did that right. Give me just a second. I wanted to check the playground. I might not have done it right. Okay. Links submitted by first name, last name. links item submitted by there we go i was missing a capital item that's submitted by last name but now i'm getting the intellisense because it generated those types so you can say item.title and item.link so now if i come back over to the front end check that out there are the components that we created at the very beginning and it's pulling in that information dynamically from the database. Pretty cool. Priscila, you asked about the CSS stuff we put or I put tailwind on this project, to me, that's one of the easiest ways to get started with it. But when you generate a new project, you do have a index.css file right here that you can add code into. So if you do this, and you're familiar with type, sorry, with tailwind, you can add your layers right here for at layer base, at layer components and out layer utilities, which is where that would go. Okay. Perfect. I think the other thing that I wanted to really touch on is, okay, so we've queried for data. Now we need to mutate the data. So do that. And then I do want to touch a little bit on react server components at the and we might not get a chance to talk through auth. Okay. So with the mutations, let's actually set up a form so that somebody could submit a link on the front end. So I wanna create, maybe you could create a new page here to say that, actually, let's do it in the same page because I'll show you a few other things. So my links page here, we have our cell. Let's create a form here. And I'm going to use, there's a Redwood component for a form that makes actually dealing with forms really easy within React. And then we can pull in say a label, for our link. We can pull in a label, sorry, an input, let's do a text field. Call this link, we need to import this as well. So within the form package, I'm getting a form. I'm getting a label. I'm getting a text field. And then I'm just gonna duplicate this. Put this inside of div. And here I'll call this a title. Oops. Let's see. What else do I need for this to work? I'm gonna come back over to...

21. Adding Data to the Database

Short description:

To add data to the database, a form with an onSubmit function is used. The handleSubmit function receives a data object containing the link and title. The data is then mutated and sent to the database using GraphQL queries and mutations in the playground. If there are any errors, they can be fixed by updating the Prisma schema file and running the migration again. The mutation can be connected to the form in the links page using the useMutation hook from Apollo. The useMutation hook allows for handling loading and error states. The mutation can be made dynamic by passing in variables. Redwood also uses directives like requireAuth to control access to data. Finally, the mutation can be included in the handle submit function to connect it to the form.

Here, I need my link, my title. I'm gonna hard code this in for right now since we don't have auth working, but I think that's all we need, submitted by ID. Okay, so here's my form. It just needs a submit button. Say save. Okay, so if we wanna check this out on the front end, I'm gonna come over here, have this form field here, and then here's my query. And so now, if we want to add data, a form has a function on here called onSubmit. And I want to run a function called handleSubmit that will run when that form gets submitted. So this is just regular React code. Oops, put that in. And I'm going to, what it automatically gets passed is a data object. so then let's take a look at the data that I'm getting back so now I take a look at this let's submit a link I'm going to say google oh I did this backwards htps google.com and I'm going to save that title so now you can see here's my data make this bigger you can see that that data object that's coming into that handle submit form has my link and the reason it's named link is because I gave that field a name of link. And then I have my title, which has a name of Google. So now I can actually do something. We want to mutate the data and send that to the database. So let's start with our playground because I think that's probably the easiest way to write GraphQL queries and mutations. So here's a query. Let's collapse this down. Let's add a mutation. And I want to create a link. So I'm going to fill this out down here so you can get an idea of how this works. But say we have our redwoodjs.com, the submitted by ID, I'm just gonna say one for right now. The title, this can be RedwoodJS. And then we don't need to include updated at. So now, and so this is still red because you have to return something. So we're inputting this, but you have to return something to make sure that it's working. So sometimes if I don't really need a lot, I'll just add the ID. But in this case, So let's just add the title and the link. It looks like I have a typo in there. So in that case, I'd fix my Prisma.schema file and then run the migration again. So it's saying, oh, it does want to update it at, which is misspelled. I think I have a, it's a weird, shoot, what is the name? It's a specific formatting. Ah, there it is. Perfect. You had it saved in my clipboard somewhere. Okay, so if I hit play, it's going to ask me, do you want to run your Redwood query or do you want to run my mutation i want to run my mutation so when i do this okay something went wrong what went wrong so you can kind of read here and see it might not have liked that date time um i tell you what let's do this if the date time is the problem um i'm going to come back over to my prisma dot schema file and with our link here yeah it looks like a lot of the yeah All these fields are required. So, let's just make this easy. And we can make them optional. Actually, I don't think that's good. So, now let me see if I run R and Redwood. Prisma my great dev. Made fields optional. now my database i should have fixed that text yeah i'll leave it for right now okay um so now if we come back let's see if this is gonna oh so this is an interesting i'm glad we hit this uh now my uh let's see those are my links now my links.sdl file and my services are out of sync because I updated that. But I've already generated this file. So there's two ways that you can handle this. Because we haven't customized this file at all, I could just delete this. Or you can manually make the updates if you've made customization. So I'm going to delete our services and our STL file. And I'm going to come back in here and say Yarn Redwood generate STL link. And that'll regenerate that file for us. So now all that's in sync with the database. Okay, so let me come back to Chrome. We have our playground. We hit refresh. Let's see. Perfect. So now our mutation is working. So it's just a matter of an optional or a required field. Now, sometimes when you're doing this, you might get a, you don't have access to this. And if you get that, if you run into that problem, if you look inside of your, yeah, your SDL file, there are these directives that are, let's say, require auth on everything, which is really helpful if you have authentication and you're logged in and you don't want the user, like anybody, to just be able to access that data. So a lot of times when I'm in staging, if I'm just writing, building an app, I'll change all those to skip auth. And then at the end, after I have the authentication added, and everything set up, I'll go back in and add require us. Okay, so I'm going to connect this to my, my form. So I'm going to copy this my mutation, I'm going to come back over to VS Code. And we have our links page where we have our form that we've created. Yes, yes, Priscilla, it is so much easier. Okay, so I have my form where we have our handle submits and here we have our handle submit function where we're getting all that data. We looked at that. So now we have to include our mutation. So I'm going to say cont and usually when I'm writing these mutations, I'll use all uppercase. So I'll say like add link and then I usually attach on mutation just so that I know that it's a mutation. And this is helpful sometimes when you have to import and export queries and mutations to different files. but some of that's just a personal preference it's definitely not required so now i can pass this in and i want the name of my mutation here to match the name here that i'm using so i'm past i'm creating a link here and that's the mutation i'll come back and talk about how to make it dynamic. So now the Redwood also uses Apollo. And all Apollo does is it gives you a nice hook called use query, which usually you don't have to use because we have our cells. But we also have another one called use mutation that we want to use here because we are using mutation. So this is maybe the only tricky part with working with GraphQL and Redwood is there's a couple of different steps you've got to do. So we've written our mutation. We have that. We're good. You could even stick this in another file if you wanted and import it. But then we have to set up the hook for it. So I'm going to create a hook and say const. And this hook is going to be use mutations. So this is coming from Apollo. And if I, you can see it's included in the Redwood web package. And what this returns is the first thing is how you want to reference it. So I'm going to call this create you can name it whatever you want and then the second you get the second element is an object and that has say like loading an error in it so this is helpful because you can like freeze the form until this has been handled and we'll do that so the second thing that in the mutation what you're passing in is the first thing that it needs is actual name of the mutation that we created. And then the second thing you can pass it is maybe you want it to do something on certain things. So for example, uncompleted, I want an alert message.

22. Creating Links and Refreshing the Page

Short description:

We learned how to create a link using Redwood and pass in variables. We saw that the link was successfully created and displayed on the page. We also learned how to automatically refresh the page after submitting a form. Additionally, we discussed the use of loading and error states in mutations and how to disable a form during the loading state. Finally, we clarified that Redwood is a React framework that bundles React code into a framework.

Or if there's an error on error, then I want it to console.error my error for me. So I can look at that in the console. So the only reason I'm getting red right now is because I've created these things, but I haven't used them. And just as a quick recap, create is the function that is how we're going to create that thing. And it's coming back from use mutation. This is the name of the mutation that we created up here, and then we're getting back a loading object and an error object, and then we can pass in this through the second parameter or something that we want to happen on completed or on error. So now let's say in our handle, let's see, our handle submit function here, we want to create, because we're going to just use that function and we're going to pass in the variables that we got from our data. Now, right now is not dynamic. Remember, we're hard coding all these in. So actually, I'm curious if we just run this. I think this should work where it's just going to create that link for us. So we do already have a Redwood link. It doesn't matter what we're adding right now because we've hard coded in those values. But if I hit submit, it says, thank you for your submission. Awesome. And if we hit refresh, there is our Redwood.js link that we hard coded in. So let's make this dynamic. To pass in variables here, I'm going to add some parentheses here, just kind of like a function. And I want to pass in a title. So notice I'm using a dollar sign. Oh, my camera went off. Wait just a second. Okay, got timed out or overheated. Let me do this. Okay, I'm going to switch cameras. It won't be as good quality, but perfect. Okay, so we were not wasting time. So here it has to have a dollar sign in front. And I'm going to say that this is a string and it is required. So you'll notice this looks kind of similar to the code that we have been working with. We're going to pass in a link and that's a string and that should be required. And then I also want to pass in a submitted by ID. And that's going to be an integer. Remember, we need that dollar sign in front. And then we have, I'm not going to worry about updated. I'll just keep that hard coded in. So now it's saying, OK, this is great, but you're not using it. So we're going to set title to title. We're going to set link to link. We're going to set submitted by ID to submitted by ID. So now if I hit save, these are our variables that we are going to pass in down here. So we are saying create, use these variables, and we want to pass in our title, so that's going to be data.title. we're passing in oh not date data there we go we want to pass in our data.link and then we want to pass in our date and then if you had an id i'm just going to hard code this in right now okay let's say oh we need our commas because this is an object so now let's come back to chrome and i'm gonna say google oh i got these backwards hdps google.com we're passing google now when i hit save thank you for your submission if i hit refresh there's google pretty cool now um one thing that i do want to show you is that you're noticing i probably had i had to hit refresh after it was submitted that's not ideal you want it to show up automatically so the way that you can work around that is we're passing in variables here we could either say here uncompleted or no, sorry, this is a different thing. We say on what is it? No, that's not it. Give me just a second. Add moments. Oh yeah. Oh, it's up here. So after we run our mutation so we have our mutation here. We set up our create. Oh, that's our function Okay, cool, cool, cool. Down here we have uncompleted, onError. Let's say after it runs that, after it runs our mutation, we want it to refetch our queries and we wanna pass in, say that links query that we were making. Well, now we've got to import that. So if we come up to the top and that links query is in our link cell, but it's not called links query, it's called query. So we're gonna have to import query So let me, I'm going to use links query, because I just made up the name links query. It's really called query, but I'm going to reference it as links query, from, and it's going to come from ourselves. So now if I come back to our project here, let's pull up say Apple. Ah, keep doing that every time. Apple.com, and we're going to put in a title of Apple, now when we hit save, okay, we get the alert. But then it should, let's see, should have refreshed, there's Apple. Let's see, I think. That may have halted to, let me see if I take this off. Make sure this is working right. What's another? React.dev. Hit save. It should refresh. It looked like it's, there it goes, twice. Cool. You'll notice that went twice. Yeah, you don't have to use conditionals. You'll notice that that went twice when I clicked on it because I was like, oh, this isn't working. And I clicked twice. So remember, we get this loading state and this error state back from our mutation. So one thing that we can do is we can come down and here on our form, this is a little trick I like to use. If I wrap my entire form contents with a field set, I can say in a single go that if loading is true, disable the form. So now if it's stuck in that middle state here, it's going to disable that form until it's been able to resolve. So you can't have a situation where somebody is like click, click, click, click. Why is this not working? Cool. So we covered a ton of ground with in this workshop. So we talked about. Yes. So Redwood is this. What you can think about, you asked if Redwood is the same as React. Redwood is a React framework. So that means you're writing all this React code here. These are down here. These are React components that we're creating. All of this is React. But it's bundled it up into a framework.

23. RedwoodJS Features and React Server Components

Short description:

Redwood is a full-stack framework that provides generators, a command line tool, front-end and back-end support, GraphQL integration, testing, and Storybook. It offers a unique cell concept and handles routing efficiently. If you want to explore more, Redwood sponsors the Advent of JS and Advent of CSS projects, where you can work on a Redwood application at your own pace. Additionally, the co-founders of Redwood, Tom and David, have given keynotes that provide insights into the future of Redwood and its features. Redwood JS real-time project showcases interesting use cases of GraphQL, such as chat, auction, countdown timer, AI, and badge app. React Server Components are being implemented in Redwood, making it the second framework to do so. Redwood is in close collaboration with the React team to ensure alignment with React's direction. CSS can be written in the web folder, and the finished repo demonstrates styling examples. Demos of React Server Components are available in a separate repository.

So it gives you those generators. It gives you that command line tool. It gives you a front end and a back end. So you're working with GraphQL. You have the testing. You have Storybook all included, which is pretty great. um so it yeah it wraps all that stuff i would say the things that make redwood redwood that kind of differentiate it from other frameworks is this cell concept the fact that that's given to you out of the box and then how it handles routing so a lot of what makes a framework a framework is that it handles the routing and the the urls and the page redirection and all that stuff.

So, um, let's see, we are so close on time. Um, there's a couple of things that I do want to point out. So if you, um, if you like to all of this stuff, uh, and you want more, I am running advent of JS and advent of CSS next month. And so you can, Redwood is sponsoring this project. And so we will be working through a Redwood application. So I know we moved fast in three hours. If you want to move a little bit slower and focus on component by component and get some more hands-on experience, this is a great place to start. And the nice thing is it's free. So you can check that out. And if you don't have time during December, that's fine. You'll have lifetime access and can come back whenever you do have time. The other thing I want to point out is that Tom and David are two of the co-founders for Redwood. and Tom gave a keynote at the Redwood JS conference. We included his keynote here that has a lot of information about the future of Redwood. Some of the cool features that they're adding and it has some information about React server components. You can also join our newsletter here and I'll include a link to this. Actually, it's on the repo, but I'll stick it in the chat. Let's see, redwoodjs.com slash React Summit. but these are also all on that repost if you come down to the bottom there's redwood.js at react summit so that's that page that i just pulled up that has kind of the future of redwood but then i also have the advent of js and advent of css but you can join our newsletter so um you know sometimes i'm like oh man i get so many newsletters but the newsletter is helpful we include release information so as we make updates to redwood we say hey this is what we updated just so you're which are often informed. We try and be really mindful of any breaking changes that we make. And then, yeah, thanks for including that repo again. And then the, that's today, that's where you guys are at, congratulations. And then we have this project here, the Redwood JS real-time shows how we're using GraphQL in some ways that are really interesting that we didn't cover today. So for example, we've created demo projects We're working with a chat. We're doing an auction. A countdown timer. We have AI involved. Which is really interesting. We have the badge app that I mentioned earlier. And then this is the React Server components piece. So some of the demos that we're creating around React Server components. So if you want to get involved. And then there's more information. Cool. Thank you guys so much for being a part of the workshop. I will say that I know we're at time. So if you want to exit out, that's totally fine. But I also recognize I did not have a chance to cover React Server Components and kind of the future of Redwood and where we're going with it. So I'll take a few minutes and cover some of those demos. Again, if you're tight on time, this is all covered in that keynote. So you're not going to miss any information. And you can check out what Tom's been doing there. But I did want to cover React Server Components because I feel like it was mentioned in the workshop description. I want to make sure that I actually deliver on that piece of the description. So anyways, I'll show a few demos. Jasmine, I don't know when Get Nation will make the recording available. I would assume you would get an email, but I don't know for sure. I know if you go to the YouTube, RedwoodJS on YouTube, if you go to the YouTube, if you go to RedwoodJS on YouTube, I'm sure we'll either link to it or you'll be able to find it there on YouTube whenever we make it available. So, okay, so I will, I'll keep going. But again, my feelings won't be heard if you dip out. So React server components, kind of where we're at. Right now, Next is the only framework that is implementing React server components. And I know some people have complained a little bit because it's like, oh, man, why is Next receiving that kind of favoritism? But the Vercel team, who's really sponsoring the next project, they pay for somebody to sit on the React team and help develop and work closely with them. So because Redwood is going all in on React Server components, so we're aiming to be the second framework to implement React Server components. We actually have a direct channel and an open line to the React team. So we are talking to them almost daily about React server components and the things that we're building to make sure that it's in line with the direction that they're taking React. Because, you know, we kind of talked about how Redwood is a React framework. So we've been implementing that with the server. And what that means is that you'll be able to make calls on the website to an API and use things other than GraphQL, if that's your thing. So, I'll keep going. And Priscilla, you mentioned CSS. So you do have that CSS piece in your web folder. So you have this here. I, like I said, I installed Tailwind because that was immediate, but you don't have, if you don't have Tailwind, this file still works. It's just like a regular CSS file. And you can write CSS as part of your JSX if that's your thing inside a component. So you do have the CSS piece. And if you want to check out the finished repo, that's also included, you can see how I have all the styles written for the final repo. Cool. So what I'll do is I'm going to exit out of this. I'm going to show you some of the demos that we have for React server components. Just a second. Okay. So I'll include a link to this repo in the chat. So, this is a really simple example. But what it's doing is it is taking React Server components and creating a client counter. So, I'm going to, let me see if I can just open this in Gitpod because that would be easier. If not, I have this running locally, which might be faster. we will see okay I'll time we'll both go at it make sure this is not running on another project oh cool it looks like we're going to get there about the same time okay just run it here now can I talk through the code as well So this is playing at my Redwood project and it is running. I think this is still working. Oh is this not going to run? I might have to use the Gitpod. Might not have the most updated. I'll talk to the code.

24. React Server Components and Business Use Cases

Short description:

React server components allow you to run React on both the client and server. You can manage state in the browser using useStateHook. Server components can improve performance and provide access to open graph and meta tags. Redwood supports server-side rendering for applications that require open graph information. Server and client components can work together to handle state and rendering. Server mutations allow for data manipulation on the server. React server components can be combined with AI using projects like AI JSX. JavaScript can solve a wide range of business problems, such as data processing and AI. Code allows for problem-solving and figuring things out. Multiple demos showcase the functionality of React server components.

So here on the code, we have a counter. and you'll notice that we have a use client. So the difference with React server components is you can actually run React on the client and then you can also run React on the client and React on the server. So if it's on the client, that means that React is running inside the browser. And if it's running inside the browser, we have this use client at the top to say, hey, run this only in the browser. And the times that you would want to run it in a browser is like if you're managing state. So for example, if you have a navigation, you're toggling on and off, if you're using that useStateHook, you would want that to be in the browser so that it can manage that piece of state. And then if we come over to the app, you can see that here we have a counter component. We have a, first, we have a server component and then inside we have a counter component. So it's important that this component here gets rendered on the server. So maybe you're wondering, when would I want to use a server component versus when would I want to use a client component? Well, if you can pass off some of that heavy lifting to the server so that it's grabbing the data for you and then delivering HTML and CSS to the browser, it might be a little bit snappier. The other thing that is a huge benefit is you get access to open graph tags, meta tags like Google can actually go through your application and see what all the content is there, because a lot of times it doesn't necessarily know what to do with JavaScript. Now, if you're doing like a web application that's protected by a login, you don't need Google and you don't want Google to go through and read all of your content. So it really just depends on your use case. So for example, I mentioned the badge app earlier. We are using server-side rendering there because we did want open graph information as people are sharing out links to the app. So I'm gonna come back. Let's see, I'm gonna come over to Chrome here. See if this is up and running on our port. Perfect, Gitpod to the rescue. So here is the React server, this is a server component and then inside we have a client component. So this state for this counter is getting handled through the client, but this code here is being managed on the service. I think if you come to view page source, actually it's not right there because that's a different thing. But anyways you can come in and see that that code is getting passed over to the, from the server, okay. So I'm gonna close this one. Let's look at the next one that I have. So in this demo, this is create using a Redwood to create a react server component. And here we have a server mutation. So we're mutating the data that's on the server with our code. So if I pull this up, we'll the repo back up. And then I have I think this is on the website. So here, this is a server component. You can see there's a server component. We have a server counter. So this particular counter is sitting on the server. And then we have the server action that's happening. Thanks, Xavier. So, you can see this is still coming up. Takes a minute to install the dependencies the first time. Oh, we're getting close. Yeah, so the other thing I would say, if you guys wanna dive in in more depth. I know I mentioned the advent, but you can, I'll just talk while we're waiting for that to load. But if you go to redwoodjs.com and pull up the docs, there's a tutorial here. And this does a great job of basically showing you all the functionality that we walked through today. Okay, so I think this is working now. I pull up my ports panel and jump over. Yep, perfect. So this is a server component. We have a server counter. And now this button will increment the client counter. So you can see that's increasing. Now I can update the server counter here by seven. So now that jumps up, if I hit refresh, this is still gonna say it's seven because it's served on the server. But this one changes back down to one because it's on the clients. So see if I hit refresh, maintains 10, but then jumps down to one. Cool, so that's the client counter and you can kind of see... Actually, I closed that window. Some of the code and how that's working. I'm not going to go into too much detail just to, cause we're already over and then being able to get through all the demos, there's two more. And again, if you want to go into greater depth, please check out Tom's keynote. Okay. So let's take just the hot minute. What are some business problems that still need to be resolved by JavaScript? That's a good question. You know, I think I'm going to take the cop out the typical developer response and just say that it depends. It depends on kind of what you're trying to solve. There's you can do a lot with JavaScript. There's even. And I even think of some use cases where I'm like, this is harder, but there's still been people that have been able to solve it. So one of the startups that has been built on Redwood is called Statapillar, and it can process all kinds of data, like large sets of data. But some of it has to do with how they're leveraging Redwood and the API and the web folder. And it's like looking at real estate markets and predicting what's going to happen. Or it can take election data and poll data and say, I'm going to predict this is what's going to happen. And it's running statistics and analysis on that particular code. AI stuff is really interesting. There's a project called AI JSX. And actually there's a team, Fixie AI, which is a great team that we've partnered with to be able to bring AI to JavaScript and make it really easy to work with. So that's a very interesting project to check out. so um you know it's i'm a fan of marie forleo and one of the things that she says she has a book that's like everything is figureoutable um and i think one of the things that's really cool about code is you can figure out a lot of stuff you just kind of say okay this is how i'm gonna do it and if you have the network that'll help you if there's pieces of it that are still hard to understand okay so in this case um in this particular repo um yeah so this one sorry about that i was going to share the last one i forgot uh let me pull up all these and i'll copy them and then i just have one more after this okay so this is showing the client side counter running inside a server component This one is showing a server mutation, which is the two counters that we just looked at. And then the one that we're looking at right now is when you have Redwood and you have a React server component. And this kind of explains, too, what's happening here. So it shows us server functions. That's what the RSF stands for, and it's receiving a return value. So if we take a look at this, this is the counter one. And that one's it. Nope, okay, hold on. I'm gonna see if I can get this other one running while we're waiting. This is the fourth one. So in this one, it's taking a react server component and it's using ai with it so this is an ai react server component with ai jsx which i just mentioned um and so i think how is it not come on git pod let me see if i can get this one up and running at the same time Cool. Now, if you're interested, we're putting together a landing page right now that'll summarize the React server components and where we're at and where all the demos are at, but other than that, the best place to get information about that is on our forums. So if you go to a community and then go down to Discourse, and then search for React server components.

25. Redwood Project Demo and Conclusion

Short description:

Toby, one of our core maintainers, has created a video and a forum post on how to create a new project using Redwood. He provides the necessary commands to get the project up and running, as well as instructions on building and serving it. During the workshop, a server component and a client component are demonstrated, showcasing the ability to have a client component render a server count. The server component runs a function on the server, allowing for async await functionality. Another demo involves a React server component running from AI in the browser. The workshop concludes with a thank you to the participants and an invitation to connect on Twitter.

I believe it should come up. Yeah. So Toby is one of our core maintainers, lead maintainers on the core team that he's working on a lot of this functionality. So there's a video here. I'll include a link to this. And then he's included in this forum post how to create a new project. You can experiment with yourself. Here's the commands to get the project up and running. here's how you build it and how you serve it so this is also a great place to get updates I think this is about done okay so I'm going to pull up ports here's 8910 oh come on not going to work Oh, you know what? I wonder if these two are competing with each other now. Maybe not. Oh, I just did it too soon. Good. Okay, so this is a server component and this is a client component. I thought we, oh, this one's, is this one? Yeah, this one's slightly different because the other one had the server counter on the outside and this has it on the inside. So we actually have a client component rendering a server count, which is pretty cool. So you can see there's a loading here. we have a fake delay, where it updates. So because it's on a server, you can also run async await to be able to get that. So I can have a server component inside a client component that is running a function on the server, which is pretty cool. That's what that is demonstrating.

And then this one, let's pull this port up. Okay, so I'm going to say I love JavaScript and send this off. And so this is a, I just went off into the ether. There we go. See if this works. I love JavaScript. There we go. Oh, it did flash. But anyways, it responds. Looks like something might be down. But this is running a React server component from AI, the AI fixie in the browser.

So thanks for you guys that stuck around a little bit longer. I really do appreciate it and appreciate you participating. But coming to the workshop and participating, I am on Twitter. My handle is self teach me. If you want to connect, I'm happy to answer questions, but hope to see you around the Redwood community.