Building a Meme Generator with RedwoodJS - the JavaScript Answer to Rails

Michael Bogan - Dec 11 '20 - - Dev Community

When I first heard about RedwoodJS, I thought it was just another front-end JavaScript framework. I wondered whether it would it be like React or more like Angular. As it turned out, I didn't have a clue what RedwoodJS was, but now I can't wait to build more projects using it.

What is RedwoodJS?

RedwoodJS is a full-stack, serverless JavaScript framework. It is the JavaScript answer to Rails or Django. It uses the Jamstack approach to build an application with both front-end and back-end code. It also uses popular frameworks and libraries to accomplish this:

  • React
  • GraphQL
  • Prisma

Using RedwoodJS allows you to build full-stack applications quickly. The Redwood CLI generates boilerplate code for anything you need, including scaffolding pages, SDLs, and services based on your data schema. And you really don't have to think much about the database, so it works well for React developers unfamiliar with back-end code.

To dig into the details of how RedwoodJS works, consider the example of a meme generator. The meme generator allows users to create a meme based on a random image from imgflip.com. First users will need to register for an account. Then they will add text to the image. When they are done, they can click a button to save the image and store the user email and the image URL in a database. Users will view all submitted memes on another page in the app.

As you can see, RedwoodJS will create almost everything that's needed for this entire project. You will still need a few additions to your stack to make a complete project. For this example we'll use Netlify for simple user authentication, Heroku to quickly spin up and host a PostgreSQL instance to store the user data, and Cloudinary to easily host the memes we generate.

So let's get started.

Setup

First let's walk through all the necessary setup.

RedwoodJS uses Yarn for package management and project installation, so you will need to install it if you haven't already. Once you have Yarn installed, run the following command to generate the project:

yarn create redwood-app redwood-meme-generator
Enter fullscreen mode Exit fullscreen mode

You will now have a redwood-meme-generator folder with all of your project files in it.

1

RedwoodJS Project Structure

Now you can start the project locally using the development server.

cd redwood-meme-generator
yarn run redwood dev
Enter fullscreen mode Exit fullscreen mode

Once the project builds, you can view it at http://localhost:8910/.

2

RedwoodJS Default Home Page

Creating Layouts, Pages and Routes

Now that you have a working (but bare) project, let's create a layout to wrap your pages and have a consistent navigation bar.

yarn run redwood generate layout meme
Enter fullscreen mode Exit fullscreen mode

You will now see the layout, a test file, and a Storybook file in a newly created MemeLayout folder inside the layouts directory. Storybook is basically an open-source tool that lets you develop and test new UI components without affecting your overall project.

Now let's run the commands to generate the two pages your app will use.

yarn run redwood generate page home /
yarn run redwood generate page memes
Enter fullscreen mode Exit fullscreen mode

The only required parameter here is the first, which is the name of the page. For the home page, you also assign a path with the second parameter to replace the default home page you just viewed. You are not only generating pages here but also their routes at the same time. The memes page will use the default route based on its name: /memes.

3

RedwoodJS Routes

We will come back to our layouts and pages later to add functionality.

Setting Up the Database

If you don't have a Heroku account, you can sign up here. The free account should be fine for this project. Once your account is set up, create a new app. I called mine redwoodjs-meme-generator. Adding a database is very easy – just navigate to the app and click on the Resources tab in Heroku. Search for PostgreSQL and add it to your app. That's it!

4

Heroku PostgreSQL

Click on the database and you will be taken to its dashboard. Then go to the Settings tab and click View Credentials to get the database connection string. You will want the value listed in URI. From there, take that string, open up the .env file in the project, replace the dummy DATABASE_URL value with the connection string, and uncomment the line. Your Redwood app can now connect to your new Heroku Postgres database.

5

RedwoodJS env

Hosting and Authenticating with Netlify

Next you want to use Netlify as a simple way for users to create accounts and log in to your app. Before setting up Netlify, you will need an account. You will also have to push the project's repo up to either Github, Bitbucket or GitLab. Once those steps are done, log in to Netlify and click New site from Git and follow the workflow to choose the project for deployment.

6

Create New Netlify Site

When you get to the final step, add this command to the Build command field:

yarn rw build && yarn rw db up --no-db-client --auto-approve && yarn rw dataMigrate up
Enter fullscreen mode Exit fullscreen mode

This command will run build the application, generate the Prisma client, and run data migrations.

For the Publishing directory field, add web/dist.

Then click Deploy to deploy the site. You now have a live site and should see the same welcome page on Netlify.

After that, you need to set up Identity so you have authentication for your app. Go to the Identity tab in your new site dashboard and click Enable Identity. That's all you need to do. Users will now be able to register for our app once we run one command and add a few lines of code to the front end.

Now let's add our env variables to Netlify so that your application can connect to your database. To do this, copy the database connection string you added to the .env file in your project. Then click on the Site settings tab of your site's dashboard and then click Build and deploy > Environment on the side menu.

First create a DATABASE_URL variable and add your connection string. Next create a BINARY_TARGET and give it the value of rhel-openssl-1.0.x. This second variable tells Prisma what it needs to know to generate the client libraries database.

7

Netlify env Variables

Now it's time to go back to our local command line to add Netlify authentication functionality to your app with another simple command:

yarn run redwood generate auth netlify
Enter fullscreen mode Exit fullscreen mode

This will create an auth.js file in the api/src/lib folder. This file will be configured for Netlify.

The last step is to go back to your local project in the command line and run the following command:

yarn run redwood generate deploy netlify
Enter fullscreen mode Exit fullscreen mode

Once this command creates the deployment files, commit your changes and push them up to your repo. Your project is now set up for deployment.

Adding the Database Schema, Model and Service

The database for your app will be simple. It will only contain one table that saves the user's email and the meme url. Open the schema.prism file in the api\prisma and change it so it looks like the one below. Here, create the model for your meme and define the fields you'll add to the table. Be sure to also change the provider value to PostgreSQL.

8

Prisma Schema

Next, run the following command to generate the folders and files to create a new database migration:

yarn run redwood db save
Enter fullscreen mode Exit fullscreen mode

You will now see a new folder in the api\prisma\migrations folder containing these migration files. To trigger the migration you've just created, run the following command:

yarn run redwood db up
Enter fullscreen mode Exit fullscreen mode

If you go back to your Heroku account, you will see that your database now has your new table. Next you will want to generate the service needed to access database records in the app. To do this, run the following command:

yarn run redwood generate sdl meme
Enter fullscreen mode Exit fullscreen mode

This created a new schema file in the graphql folder, as well as a service and test file in the services/meme folder.

Creating the Meme Generator

That was a lot of setup, but it was straightforward and went pretty quickly. Now let's get to work on creating memes.

You are going to use html2canvas to generate your memes, so let's add that package. The generator html2canvas is a JavaScript library that will convert part of the page into an HTML canvas element which you will then convert into an image. This project also uses Yarn workspaces so you can run yarn add in the project root. You must specify either the api or the web workspace. You need to add html2canvas to the web workspace, using this command to choose that workspace:

yarn workspace web add html2canvas
Enter fullscreen mode Exit fullscreen mode

You will also need to sign up for a free Cloudinary account to host our memes.

Now let's update our MemeLayout.js file.

9

Meme Layout

In the above code, we've added a wrapper for our pages that presents a simple header with login and logout buttons, and links to view the pages on the site. Notice that there is not much to authentication here. You just call built-in functions to log in, log out, or check if the user has been authenticated. From there, the Netlify auth file you generated handles the rest. Also, notice how routes are accessed through a route method.

Before updating the HomePage.js file, you need to add a mutation to your memes schema which will handle creating memes. Add this right before the last backtick in the file.

10

Memes Schema

Then you need to add a new resolver called createMeme in your memes service file.

11

Memes Service

Now you are ready to update the HomePage.js file to create memes.

12

Home Page

At the top of the file, you have a CREATE_MEME mutation. We name the call using this create. You'll use the React Effect Hook to fetch a list of memes from imgflip.com and then to pick a random image from the 100 images this free api provides.

The app allows you to add text to the top and bottom of the image. And when you click Generate, it uses html2canvas to convert the image and added text into a single image. From there it uploads that image to Cloudinary, saves the URL you get back from Cloudinary, and adds your email from Netlify to the database. Notice we use the MemeLayout to wrap the component.

The last page you need to address is the one where you will list all submitted memes. First, you need to generate a Cell. Cells in RedwoodJS contain the GraphQL query, loading, empty, error, and success states so you don't have to write them manually. Run this command:

yarn run redwood generate cell memes
Enter fullscreen mode Exit fullscreen mode

This will generate a folder called MemeCell in the Components folder which contains MemeCell.js. Modify the MemesQuery constant so that it includes both id and image. Change the default Success constant so it returns markup for the images (instead of the default JSON).

13

Memes Cell

Because you have this Cell, modifying the MemesPage.js file is much simpler.

14

Memes Page

You'll wrap our component in the MemeLayout, add a heading, and let the MemesCell component just handle the rest.

Once it is deployed, you should see something like this:

15

Memes Home

You can find the code from this project at this repo.

And here is a completed meme:

16

Conclusion

RedwoodJS is in alpha. Their team is still adding a lot of functionality. But they are moving fast. The docs said that Storybook was still in the works, but it was functional in the project I built. Overall, I did like the experience. RedwoodJS allowed me to code and deploy this app in a few hours from one repo. Before RedwoodJS, I would have had to code a front-end project, code a back-end project, and deploy each separately. But with this, the only code I wrote myself was for the specific things I was trying to do. I didn't have to hand-code any boilerplate. I only ran into issues when I skipped a step in the docs, specifically with the Netlify deployment process. Simply put, I can't wait to try it again when it is ready for production applications.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .