Tired of rebuilding your React-based web framework from scratch for every new project? You're in luck! RedwoodJS is a full-stack web application framework (think Rails but for JS/TS devs) based on React, Apollo GraphQL, and Prisma 2. We do the heavy integration work so you don't have to. We also beautifully integrate Jest and Storybook, and offer built-in solutions for declarative data fetching, authentication, pre-rendering, logging, a11y, and tons more. Deploy to Netlify, Vercel, or go oldschool on AWS or bare metal. In this talk you'll learn about the RedwoodJS architecture, see core features in action, and walk away with a sense of wonder and awe in your heart.
RedwoodJS: The Full-Stack React App Framework of Your Dreams
AI Generated Video Summary
Redwood JS is a full stack React app framework that simplifies development and testing. It uses a directory structure to organize code and provides easy data fetching with cells. Redwood eliminates boilerplate and integrates Jest and Storybook. It supports pre-rendering and provides solutions for authentication and deployment. Redwood is a cross-client framework that allows for building web and mobile applications without duplicating work.
1. Building a Web App with React, Prisma, and More
To make a web app, I'll need React, Prisma, Apollo, Jest, Storybook, Webpack, Babel, authentication (probably Auth0), authorization, logging, code-splitting, OG tags, pre-rendering, and accessibility. Let's start with Create React App and then learn Prisma.
I know what you're thinking. I want to make a web app. So I'm going to need React. I'm going to need Prisma on the backend to talk to a database. I'm going to need Apollo to talk from the frontend to the backend.
I'm going to need Jest so I can write some tests. I'm going to need Storybook so I can design code and test my components in isolation. I'm going to need Webpack to glue this whole thing together. And I'm going to need Babel so I can compile, transpile ES6 down to ES5.
That's the web app, but I'm going to need to figure out how to deploy this thing. Maybe it could go to Netlify. They're really into Jamstack. Maybe it could go to Vercel. They've got a cool Triangle logo. What about render? Maybe then I could use containers and get long-running requests and GraphQL subscriptions. Or maybe I need the full power of AWS. I haven't decided yet.
In any case, I'm going to need some kind of authentication so I could use Auth0 for that. I'm not going to write my own. Gotta go further than that, though. I also need authorization. So I'm going to need some role-based access controls. And what about logging? I'm going to need really good logging send out to the provider of my choice.
I'm going to have to code-split this thing so the browser doesn't get too much code at any one time. I'm going to need OG tags, so this thing will unfurl on Twitter and Facebook. Gotta have pre-rendering probably in order to do that. And I'm going to need accessibility right out of the box. This thing works in screen readers.
All right. Let's do this thing. That's not really how it works, is it? It's more like this.
All right. Google my old friend, create react app. Okay, there you are. What's this? There we go. Launch. CX. Create react app. All right. What am I to call this thing? Gloobnox? That works. All right, we'll let that do its thing for a while. Let's learn how to use Prisma. Okay, Prisma, here we go. Nope. Not that one. Nope. Not that one either. Aha! Found you. Yep. Here we go.
2. Introduction to Redwood JS and Project Structure
I'm here to tell you about Redwood JS, the full stack React app framework. A Redwood application is broken down into two sides: the web side with React and the API side with GraphQL and Prisma. Let's see some code. I have a simple to-do application written in Redwood. I've initialized the database and spun up the web server. I can add and toggle items on my to-do list, all via GraphQL. The project structure includes separate web and API folders within a monorepo.
Prisma docs. Quick start. All right. In this page you will learn how to send queries to a, okay, great. All right. This is going to take the rest of my life. But despair not, because I'm here today to tell you about Redwood JS, the full stack React app framework of your dreams.
Now, I know what you're wondering. Who is this bozo telling me what to do? Well, I'm Tom Preston Werner. You can find me online, at MoJombo on Twitter and GitHub. In the past I've created such companies as GitHub and Chatterbug, best place to learn a foreign language. I have also very active in open source. I created Jekyll. I wrote the semver, the semantic versioning specification, TOML, the configuration language used by a variety of packages, and Gravatar, the avatars that follow you around.
3. Redwood Routes, Pages, and Cells
In the routes file, we have a router with routes for the homepage and a not found page. Redwood uses a directory structure that makes it easy to find things. The homepage is a standard React component that uses styling components. Redwood's cells concept simplifies GraphQL data fetching by exporting variables and states as components. Cells organize code around data fetching and eliminate the need for conditional logic. On the backend, Redwood breaks the application into services. Each service has its own SDL file that defines the schema, queries, and mutations. Redwood stitches these files together to present a unified GraphQL API.
So in the routes file here, you can see that we have a router. And within it, we have a route for the homepage and a route for a not found page. This is essentially the 404. So this is our homepage. And in Redwood, we have another directory for pages. It's very easy to find things, very organized, the directory structure.
So this is the homepage. This app is using styling components, which you'll see here. And it's just standard React. So this should look very familiar if you know React. So here we have a wrapper, we have the title, to-do list, and then we have a to-do list cell.
Now, Redwood has a really special concept called cells, and cells are a way to declaratively do your GraphQL data fetching. So let's go look at that. To-doListCell is in source components, to-doListCell. So source components, to-doListCell. And here's the file. And how this works is you simply export a certain set of variables from here, constants, including the query. So you start with your GraphQL query, you just type it out here as a GraphQL query or you could have a mutation in here as well, which you can actually see here. And then you have different states and you just export these states as components. You have a loading state and a success state. You can also define a failure state and an empty state. Right here, I've just done a loading. It very simply says loading. And a success state. And so what this does is really simplify and focus you on what you're building. So in this instance, when this query completes, whatever the query name is, the GraphQL query that you're doing, in this case, to-dos, that will be sent in as a variable, as a parameter into the success component. And then within that, you can do your work. So this is doing some optimistic updating which you don't have to worry about too much for Apollo. But right here, you can see that it's just taking the to-dos and mapping over them and creating to-do items which represent each of these items here. And that's what cells are. So really, it's just a simple way to think about your data fetching, so you don't have to do a lot of conditional logic. It really organizes the code around that.
4. Redwood Implementation and Testing
In Redwood, we've eliminated boilerplate by matching things up by name. The services directory contains the implementation and resolver for GraphQL queries. We use Prisma for database operations, such as find many. Redwood includes a GraphQL playground for easy exploration and testing. The code required for the front end to back end is minimal.
It feels like a lot of boilerplate. So we've eliminated all of that in Redwood and said, well, let's just match things up by name. And so, if you come into these services directory and look at services, to-do's, to-dos.js, what you're going to see here is a constant, to-dos, this is the same name as the GraphQL query, being exported, and Redwood is smart enough to match that up and say, this is the implementation. This is the resolver for that GraphQL call. And in it, we're going to use Prisma, which we just import here. DB represents the Prisma database. And now we can do any of our Prisma calls on that. In this case, we're just doing a find many. So a really fun way that we can explore that as you may be already used to is with a GraphQL playground, and Redwood, of course, ships with one of those, and that's going to be at localhost 8911. And we can try this out. So I already have loaded up the same query that we find in to do lists cells, just the to do list query ID, body status. And if we run that, then we can see that we get back exactly what we expect, milk, cheese, eggs, and everything is as it should be. And really, that's all the code that it takes to do the front end to the back end.
5. Implementing the Count Page
Let's implement a count page that shows the count of to-dos. Redwood allows us to generate this page easily. It creates the necessary files, such as the route, the count page, the stories file, and the test. We can view the generated page at /count and any changes made will be immediately reflected on the website.
So all right, that's cool. You say, what about doing this from scratch? Having it all there right now is one thing, but what if we want to do something from scratch? Well, let's give that a try. I'm going to close all of these. And I'm going to switch over here. And what should we implement? I think it would be fun to have a page that just showed me the count of to dos. Maybe something else needs that for some reason. It's a simple thing to implement. So we have the ability to generate certain things in Redwood. So I'm going to run Redwood, sorry, Yarn, Redwood generate or just G for short, page, and I'm going to call it the count page. I'm going to run that. And what I'm going to see here now in my routes file is a new route has been generated slash count, takes that from what I've typed in here. And it has created a count page for me. So let's go look at that count page. It's also creating stories file for storybook. This is integrated out of the box. And a test. This is the just test. So we're beautifully integrating all of these different elements. Right now we can go look at this in slash count. And here we go. This is just the the generated pages is what it looks like. If we make any changes in here, then they will be immediately reflected over on the website. So you can you can go back and forth very, very simply and do this.
6. Implementing Data Fetching and Creating a Cell
Now let's switch to the API side and modify the SDL file to create a new GraphQL query called 'to do's count'. We'll implement it in the services to do's JS file. After adding two lines of code, the GraphQL infrastructure is ready for the front end to consume the data on the count page. To fetch the data, we'll create a cell using the 'yarn Redwood generate cell' command. We'll correct the generated GraphQL query and define the loading, empty, error, and success states. Finally, we'll use the cell in the count page by importing it.
Okay, very cool. Now we need to get some data from the back end. So let's switch over to the API side now. And we're going to modify our SDL file to create a new GraphQL query. And we're going to call it to do's count. And it's going to return an integer always an integer. I have a Redwood extension installed in VS Code here. And it does some nice things. So here you'll see that it can tell me that this service is actually not implemented. I don't have an implementation for this specific query. And so this is just a very nice way. Because we do some things automatically for you, we want to also help you see when some of those automatic things aren't going to work properly.
So this isn't implemented. Well, let's go implement it. That's in services to do's JS, we're going to create something called to do's count. We'll do that right here. Export const to dos count. That is going to be a function. And it's going to just be db.to do.count. Okay, well, let's see if that worked. We should be able to run it and see if it worked. And here we go. All right, there we go. See, I added two lines of code and I created all of my GraphQL infrastructure that's necessary in order to get the back end working. So there we go. In a new GraphQL query, defined, ready to return some data and be consumed by the front end on this count page.
Well, we're going to need a cell. We're doing data fetching. So we need a cell. So let's create a cell. Yarn, Redwood, generate, cell, todos.count. We'll let that run. And we're going to find this in components, todos.count, cell right here. Now it's generated this and it's guessed what I'm going to write as a GraphQL query, but it's a little bit wrong. Let's make it correct. It's just going to be todos.count. Like that. The loading state is fine. The empty state, this is what I was talking about before. These are all predefined. We just change these as we like an error failure state. And the success state is just going to by default just do a JSON stringify on whatever comes out of here, which is just going to be an integer. And that's fine for now. We like that. And now we're going to use this in the count page. So let's see in here. Why don't we say todos.count is going to be the todos.count cell. And then we need to import this. We're not using that anymore. So import todos.count cell from source components, todos.count cell.
7. Redwood Development and Storybook Integration
Redwood makes it easy to develop a full stack application from front to back, with just a few lines of code and generator commands. It also provides Storybook integration, allowing easy visualization and testing of components. Redwood simplifies mocking data fetching in Storybook, making it effortless to work with cells and visualize components without worrying about data mocking. Redwood eliminates boilerplate, integrates Jest and Storybook, and removes the need for manual configuration of Webpack and Babel. Let the framework handle the heavy lifting so you can focus on your business logic.
And if we come back here before we save this, then there we go. And that's really, that's really it. We did all of that in a couple of minutes. I could, if I wasn't talking so much, I could have done that a lot faster even, but that's front to back, all the way on the React side, to the GraphQL, all the way to the backside, Prisma, to the database, the whole thing with just a few lines of code, a few generator commands, and that's really how easy Redwood tries to make everything that you do.
Now I mentioned before that we have Storybook integration as well, so I'd like to show that off real quick. In order to get the server, the storybook server running, I'm gonna run yarn Redwood storybook. And that'll take a few seconds to spin up. And when it's done, it's gonna launch this page, and you'll see here we have the storybook stories for the things that I've generated. We have the count page, which is generating, and check this out. It actually has some data for the count that's coming back, but that's interesting. 42, where did that come from? And why does it say ID there? That's a little bit weird.
Well, the reason that that's happening is that it's pulling it from here. So the count page is that whole page, is pulling from this count cell. And one of the things that we do for you, if you were paying attention over here when we created this, and I came into this directory, is you'll see this mock file. And this mock file is gonna make it really easy for you to see your cells in storybook, because mocking out your data fetching in storybook is one of the real challenges to getting storybook working really nicely with your application. Again, Redwood tries to make it really easy for you. And so, we have the concept of mocking your data fetching. And in this case, we've just said, we think that todos count is going to return an object with an ID. You might remember that that was what we guessed you were going to do. But it's very easy to come in here and just say, Oh, it's actually just returning a number. And save that. And now, you'll see that the success state of this updates. And indeed, the page itself will update. So, all of these components can use these mocks, the cells. And that means that when you have a page or you have a cell or component that has a cell in it, anytime you have one of those, if you use it in your storybook, it's cool. It's just going to pull this mock data and it's going to include that. So, it's still very easy to visualize your components and work with them without the hassle of trying to think about how you're going to get that data mocked out in there. And again, you can very easily now work on the loading states of these things. So, to dos count cell has these various states. I might want my loading state to just say, just wait. I can save that. And now, instead of trying to be in my app and clicking refresh and being like, oh, what did it, what, does it look right? Oh, I see it. It's there for like a, you know, a hundred milliseconds or something, even less. That's kind of a pain. And I can go to my inspector and I can make my page really slow. And that's annoying. But that's why we have storybook. Now, I can come in here and I can stare at it for as long as I want. And I can just, I can make it work. Or the empty state, what does that look like? What happens when I get an error? If I want to make an error happen in my application, I have to go into my implementation, probably, and add some kind of a syntax error so that it's going to throw some kind of error. Now don't screw around with that. That's why we have storybook and Redwood is all about making the entire thing, the entire application development process end to end as smooth as it can possibly be with as little amount of work, as little amount of boilerplate as we can possibly make it for you. We have spent so many hours reducing boilerplate and doing integrations of these products. Integrating Jest, integrating storybook, removing Webpack. You'll notice that in here, you really don't see Webpack at all. You don't see Babel at all. Of course, we have some config files for you in case you need to dig into them, but you never have to touch them, really. If you're just doing normal things, this is not a part of your job anymore. Let the framework do the heavy lifting for you so that you can focus on your business logic. Well, what else can Redwood do for you? Well, I'd like to show you something that we released recently.
8. Pre-rendering Pages in Redwood
9. Hydrating Static Pages and Redwood Benefits
To make a statically generated pre-rendered page that can still be dynamic, you can hydrate the page after the HTML is loaded using React's hydration. Redwood provides solutions for various aspects, including application authentication providers and deployment targets. Join the Redwood community and enjoy the benefits of a framework that simplifies integration and makes your life easier.
Remember this ridiculous screen that I assembled before, Redwood has a solution for every single one of these things. All of the stuff in the application authentication providers from Auth0 to Netlify. To many others, a bunch of deploy targets, including Netlify and Vercell and render and the ability to deploy your API side to AWS. We have so much more in the works to make your life easy. The whole point of Redwood is that we do the beautiful integration for you so that you can focus on your product and what makes your business valuable. If you want some stickers, you can get those on the website. We'll ship them to you free anywhere in the world. I'm really happy you joined me today. And I hope you come and join our community and find this stuff really useful. Completely open source, MIT licensed, free for you to use. We do this to try to make your life easier. Thanks for watching.
Web App Infrastructure and Redwood vs BlitzJS
So you are asking everyone, what kind of infrastructure do you deploy your web apps on? And it seems that Virtualized won. It's the most voted. And after that, it's followed by Container, which is render, begin, fargate, Cloud Run. And on the third place is JAMstack. I have to admit that in my opinion, I'm using Virtualized. Just because I can get my hands on the virtual machine. But what are your thoughts about those votes? I think this is really interesting also because there isn't one clear winner. There isn't one that really super dominates the rest. And I think that's super interesting.
So an interesting fact about Redwood, when I started working on it, it was really envisioned to be a full stack web application framework for the Jamstack. But as we've been working on it, we've found that exactly these results are kind of the case of how people are thinking and operating. And so we need to adjust our our homepage and our marketing now. But really, the goal is to target all of these equally and kind of follow you where you want to go. And depending on your application and what your use cases are, you might choose different ones for different reasons. Like you might choose to go on to Netlify for the ease of deployment. And it's just so simple. But you might need more control. You might need certain things around containerized, a containerized approach or just virtualize straight on easy to so that you have total control. And Redwood is happy living in all of them. There is no there's no vendor lock in. We're not specific to any given vendor. And we try to make it really easy and have built in deployments for a lot of these. Where you just say Redwood, yarn Redwood deploy, you give it a target and we'll do most of the rest for you. You'll have to make some choices, but we try to make that Redwood easy.
Redwood as a Cross-Client Framework
Redwood is a cross-client framework that allows you to build web and mobile applications without duplicating work. It provides an abstraction between the front and back end using GraphQL, which is efficient and widely supported. With Redwood, you can easily add new clients, such as a command line interface, without additional work. The flexibility of GraphQL allows you to build a GraphQL API that serves multiple clients. Redwood and Next.js have different approaches, so it's worth exploring both to find the best fit for your use case.
And one of the biggest reasons that we do that is because we've envisioned Redwood as a multi-client framework so that it becomes more than just a web app framework. It becomes a cross-client framework. So oftentimes when you start working on a new product, you're going to start with a web app that's pretty normal that you're going to have one. And we love React for that on the front end. And then later on, you'll decide, oh, I need a I need a mobile application. And at that point, what usually happens with frameworks like Rails or if you were using Blitz, this may happen. Then you say, OK, well, I need my client to talk to my back end. So now I guess I'll reimplement some kind of an API so that I can talk from my mobile app to my back end. And now you're duplicating work that you've done before. And so what we said is, let's just start with the assumption that you're going to be multi-client or eventually want to be multi-client and create the abstraction between the front and the back end and use a protocol that is really efficient, very well known. There's clients for everything that you would ever want to interface with so that when you decide that you want to do a command line interface for your project, guess what? Your application is already just a GraphQL API on the back end. And so there is no additional work to do. It's already completely engineered from the very beginning to serve a client that ends up being sort of abstracted. But you still have full control over that. You're building the GraphQL API yourself. So you have both the flexibility of GraphQL in its best parts, but also the flexibility to use it across multiple clients. So that's really the crux of why we chose GraphQL for that. So those are two of the big differences. And, of course, there are many. Just our approach to lots of things are slightly different. It's just different. We both think differently about things. And I encourage you to explore both to see which one might serve your use case better.
Redwood JS and SSR
Redwood JS handles SSR by providing pre-render support, which allows for the caching and serving of generated content. Pre-rendering is the first of many features that fall into the Redwood at scale category, which focuses on caching and performance at scale. The goal is to enable the static generation of marketing pages that can be rehydrated for interactivity. Redwood's approach to SSR may differ from Next.js, but it aims to solve the deployment and scaling challenges faced by web application developers.
It's, yeah, it's really fantastic. I mean, you took inspiration from Ruby on Rails, which also have generators, your Redwood JS also have generators. You have services like the layer that communicates with with things and the backend. It's fantastic.
I have a question. Since you also touch the Next.js part, the question from Vlad F is how is Redwood handling SSR? Since Next.js is handling SSR, how Redwood JS is handling SSR? Yeah, I think Next has really made itself a real winner in this area. So super relevant question. These are questions that we've had to kind of re-imagine from a Redwood perspective, thinking about what we really try to do is think from first principles. What do you need as an application developer? And so we're starting to really think about these problems from what is the problem that you have and how can Redwood solve them for you in the most elegant way possible? In the talk, I showed our pre-render support. So that's one portion of what SSR might do for you. You have this problem where you need to have content generated that you don't wanna generate it at build time, but you'd like to have it cached and served. And you might do that for various reasons. One of those reasons might be because you need to have OG tags and support for that. And so this is where pre-render. Pre-render is just the first of many features that fall into a category we call Redwood at scale. Because all of these things, if you think about them, all of these strategies, things like SSR are really about caching. They're really about performance at scale. And that almost always boils down to some form of caching. And so when we think about caching in Redwood, pre-render is the first implementation that we've started along that path, where we say, what do people often need? They need the ability to statically generate marketing pages, because there's no reason to do them dynamically. But it would also be nice if they could be rehydrated so that any small bits of interactivity on the page will still function. And that's what pre-render is. And as you saw, it was a single word in order to enable that across multiple different deployment platforms. And so that's really what we want to do for the rest of it. So we will eventually have solutions for something that looks a bit more like SSR or you saw Netlify today just came out with their solution for this that maintains atomicity around deploys and can make it a lot more easy to reason about. So we'll leverage those things on these different platforms and make them really easy to engage with hopefully as little work as possible in the meantime. So our approaches will be different I think than Next. They'll look a little bit different. But they're going to be really specifically aimed at solving problems that web application developers have in the deployment and scaling part of application development.
TypeScript Support in Redwood