Imagine a React app, delivered by CDN, that sends GraphQL queries to a back end running AWS Lambdas around the world, all accessible via a
git push. This is Redwood — an opinionated, full-stack framework that embraces the Jamstack.
The ideas behind the Redwood framework are embodied in the name itself. Redwoods are a type of tree in Northern California. They’re large trees, the tallest in the world, some as big as 380 feet (c. 116 meters). The oldest living Redwoods sprouted off the ground some 3,200 years ago. Redwood pine cones are surprisingly small. The trees are resistant to fire, and appear complex from afar, but remain simple up close. This is what the framework attempts to achieve — to give developers a way to build beautiful apps that are dense, resilient, and easy to work with.
In this tutorial, I’ll take a good look at Redwood and what it brings to the table. I’ll assume some familiarity with React, GraphQL, and the Jamstack. If you want to follow along, you can find the entire demo sample code on GitHub. This tutorial will build a CRUD app (Create-Read-Update-Delete) and show how seamless this is in Redwood.
For a successful Redwood installation, the tool checks for the following version requirements:
- Node: >=12
- Yarn: >=1.5
Assuming Node is available via NVM, for example, install Yarn via
npm install -g yarn
All Redwood commands use Yarn, which is a requirement. To fire up your first app:
yarn create redwood-app getting-started-redwood-js
This is what the initial output in the terminal looks like:
Make sure the target directory is a new or empty folder, as otherwise this Yarn command fails. Change to this new directory and fire up the dev server:
cd getting-started-redwood-js yarn redwood dev
Ta-da! This automatically opens a browser set to
http://localhost:8910. Your new project should look like this:
Go ahead and leave the dev server running. I’ll be sure to let you know when it needs a reboot. Next, with the initial Redwood project in place, it’s time to commit progress:
git init git add . git commit -m "First commit"
Feel free to poke around in the skeleton project. There should be a
.gitignore file where you can append any files you want to ignore. For example, the initial skeleton project has the
node_modules folder in this file. Anything not in this file gets committed to the repo.
Now, take a deep breath, and appreciate how the tool does most of the work in getting a skeleton project off the ground. There are two folders of interest —
api — which seem to suggest both a back end and front end in this project. There’s a Babel and a GraphQL config file which suggests these are dependencies.
Go back and look at the console output after the initial project has run. There should be a message that says “Watching files in
api/src/functions”. This suggests any back-end code changes get refreshed automatically via this webpack file watcher.
Redwood Folder Structure
Open the Redwood project in a file explorer, or your favorite code editor, and look at the folder structure. Ignoring non-essential files, it has the following hierarchy:
┳ ┣━┓ api ┃ ┣━┓ db ┃ ┃ ┣━━ schema.prisma ┃ ┃ ┗━━ seed.js ┃ ┗━┓ src ┃ ┣━┓ functions ┃ ┃ ┗━━ graphql.js ┃ ┣━━ graphql ┃ ┣━┓ lib ┃ ┃ ┗━━ db.js ┃ ┗━━ services ┗━┓ web ┣━┓ public ┃ ┣━━ favicon.png ┃ ┣━━ README.md ┃ ┗━━ robots.txt ┗━┓ src ┣━━ components ┣━━ layouts ┣━┓ pages ┃ ┣━┓ FatalErrorPage ┃ ┃ ┗━━ FatalErrorPage.js ┃ ┗━┓ NotFoundPage ┃ ┗━━ NotFoundPage.js ┣━━ index.css ┣━━ index.html ┣━━ index.js ┗━━ Routes.js
At the root are the
api folders which separate front-end and back-end code. Redwood calls these “sides”, and Yarn refers to them as “workspaces”.
api folder has the following sub-directories:
db, which contains the database:
schema.prismahas the database schema definition with tables and columns.
seed.jsinitially populates the database with any zero-configuration data.
Database migrations are in SQLite and are part of the framework. After I add the database, there will be a
dev.db file, and a folder named
migrations. This is how Redwood keeps track of database schema changes in the project.
srchas all the back-end code:
functions: these will have Lambda functions and the
graphql.jsfile generated by Redwood.
graphql: this is the GraphQL schema written in Schema Definition Language (or SDL).
libhas one file
db.jsthat sets up the Prisma database. This folder is for code that does not fit in
services: this is for the business logic which works with data. Code that queries or mutates data goes here.
For the front end, look at the
publichas all static assets that are not in React. All files in this folder get copied over as-is:
favicon.png: an icon that pops up in the browser’s tab when the page first opens.
robots.txtcontrols web crawlers for search engine optimization.
README.mdexplains how and when to use this public folder.
srchas several sub-directories:
componentshas traditional React components and Redwood Cells (more on this later).
layouts: HTML/components that are shared across Pages. In a project, layouts are optional.
pageshas components that might be wrapped inside Layouts and become the landing page for URLs. For example,
/authorsmaps to one page and each page route has its own folder.
NotFoundPage/NotFoundPage.js: the framework serves this page when no page exists (look at
FatalErrorPage/FatalErrorPage.jsrenders with an uncaught error exception in the app.
index.css: a generic place to put global CSS that does not belong anywhere else.
index.html: React initial page.
index.js: bootstrap code to get the app up and running.
Routes.js: route definitions which map a URL to a Page.
Routes.js file, this is how the app routes to a
<Router> <Route notfound page=NotFoundPage /> </Router>
Meet Redwood, a Full-stack, Serverless Jamstack Framework