How to create a job board with Fauna and Redwood.js
Tags: redwoodjs, fauna, graphql
Published: 2020-12-03 14:57:41

---
title: How to create a job board with Fauna and Redwood.js
published: true
description: 
tags: redwoodjs, faunadb, graphql
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/jke8847l5jyci138ocqj.jpeg
---



#### INTRODUCTION

#### Redwood.js & Full Stack

[Redwood](https://redwoodjs.com) is an opinionated, full-stack, serverless web application framework that enables developers to build and deploy Jamstack applications with ease.
One of the main Redwood’s philosophies is power in standards, so it makes decisions about which technologies to use, organizing your code into files, and naming conventions.

#### Fauna
[Fauna](https://dashboard.fauna.com/accounts/register?utm_source=DevTo&utm_medium=referral&utm_campaign=WritewithFauna_MircroServicesPythonFlaskFauna_BAmolo) is a powerful and fully featured serverless database. With a web-native GraphQL interface that supports custom business logic, consistent data and total freedom from database operations since its fully managed. 

By using [Fauna](https://dashboard.fauna.com/accounts/register?utm_source=DevTo&utm_medium=referral&utm_campaign=WritewithFauna_MircroServicesPythonFlaskFauna_BAmolo) in this application’s architecture, we are able to simplify code, reduce costs and ship faster.

#### The Application.
In this tutorial, we will be developing a simple job board. 

#### Getting started.
We'll use yarn ([yarn](https://yarnpkg.com/en/docs/install) is a requirement) to create the basic structure of our app:

```
yarn create redwood-app ./job-board
```

You'll have a new directory “job-board” containing several directories and files. Change to that directory.

#### Redwood File Structure
Let's take a look at the files and directories that were created for us (config files have been excluded for now):

In the web folder.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/zdss0v4tg4xbyk6waigd.png)

In the api folder.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ds8wt9kpatx3hdb3cvxt.png)


From the above structure, it's clear how Redwood makes decisions for you about which technologies to use, how to organize your code into files, and how to name things.
It can be a little overwhelming to look at everything that’s already been generated for us. The first thing to pay attention to is that Redwood apps are separated into two directories:

1. web directory for the application frontend.
2. api for the backend

#### Setting Up Fauna.

Create Fauna Account
To hold all our application’s data, we will first need to create a database. Fortunately, this is just a single command or line of code, as shown below. Don’t forget to create a Fauna account before continuing!

NOTE:
[Fauna](https://dashboard.fauna.com/accounts/register?utm_source=DevTo&utm_medium=referral&utm_campaign=WritewithFauna_MircroServicesPythonFlaskFauna_BAmolo) offers a generous free tier for you not only to test your app but you can also use this to build your small hobby apps. 

#### Fauna Shell
Fauna’s API has many interfaces/clients, such as drivers in JS, GO, Java and more, a cloud console, local and cloud shells, and even a VS Code extension! For this article, we’ll start with the local Fauna Shell, which is almost 100% interchangeable with the other interfaces. 

```
npm install -g fauna-shell
```

After installing the Fauna Shell with npm, log in with your Fauna credentials:


```
$ fauna cloud-login

Email: email@example.com
Password: **********
```

#### Creating the Database
Now we are able to create our database.
To create your database enter the fauna create-database command and give your database name.

```
fauna create-database job-board
```
To start the fauna shell with our new database we’ll enter the fauna shell command followed by the name of the database.

```
fauna shell job-board
```

#### GraphQL on Fauna.

One of the many great features of [Fauna](https://dashboard.fauna.com/accounts/register?utm_source=DevTo&utm_medium=referral&utm_campaign=WritewithFauna_MircroServicesPythonFlaskFauna_BAmolo) is its first class support for GraphQL.
One big advantage of using GraphQL on Fauna is that it allows you to define a schema and it will do its magic in the background to ensure your entities, collections and their relationships are created. All you need to provide is a schema.

#### Writing Schema.

We will use the below schema for our application.
Create a file in the your directory and name it `job-board-schema.gql`

```
type Listing {
 title: String!,
 description: String!,
 location: String!
 company: String!
}
 
type Query{
 listings: [Listing]
}
```
#### Importing Schema.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/tvq8a1jcb2jtba41ps7w.png)

On your database page on Fauna, go to the GraphQL tab on the left side bar. You will see a page similar to the one above.

Click on “Import Schema” then select the sample schema from your application directory.

This will automatically create the required collection, FQL queries to fetch and create data together with indexes that will be required for query and mutation capabilities.

#### Testing the schema (Graphiql) and Writing Queries.

Now that we have successfully imported our GraphQL schema definition, we can now test if our GraphQL API is working by running the following mutations to seed initial data to our database.

```
mutation {
  createListing(data:{
    title: "Python Developer",
    description: "Experience Python developer with experience in Flask and FaunaDB",
    location: "Kisumu",
    company: "Dala Systems"
  }),
  {
    _id
    title
  }
}
```

Then

```
mutation {
  createListing(data:{
    title: "Node.js Developer",
    description: "Outstanding Node.js with 3+ Years experience in developing serverless apps",
    location: "Cape Town",
    company: "Sugar Systems"
  }),
  {
    _id
    title
  }
```

If the above mutations execute successfully, they should return the `_id` and `title` of the newly created job listing.

Moreover, you can further confirm this by running the following query should list all the available jobs posted to the collection.

```
query {
  listings {
    data{
      title
      description
      company
    }
  }
}
```

#### 4. Setting up Redwood to work with Fauna.
When generating the project using yarn, the default database is an instance of the PrismaClient. Since Prisma doesn’t support Fauna currently, we will make use of graphql-request to query the GraphQL API we created above. 

```
yarn add graphql-request graphql
```
In the `api/src/lib/db.js` add the following code.

```
import { GraphQLClient } from 'graphql-request'

export const request = async (query = {}) => {
  const endpoint = 'https://graphql.fauna.com/graphql'

  const graphQLClient = new GraphQLClient(endpoint, {
    headers: {
      authorization: 'Bearer <FAUNADB_KEY>'
    },
  })
  try {
    return await graphQLClient.request(query)
  } catch (error) {
    console.log(error)
    return error
  }}
```
To access our Fauna database through the GraphQL endpoint we’ll need to set a request header containing our database key as provided by Fauna.

#### Obtaining your Fauna database key.

Head over to your database’s Fauna Shell and create a key using the following command.

```
CreateKey({
      name: "redwood-app",
      role: "server"
   })

# Example result.
# NOTE: Make sure you copy and store the secret!
# {
#   ref: Ref(Keys(), "280185139463529993"),
#     ts: 1603464278974000,
#     role: 'server',
#     secret: 'fn…………………………………………………..',
#     hashed_secret: ...
# }
```
After this you will also be required to create a `api/src/graphql/listings.sdl.js` file and add the following contents.

```
import gql from 'graphql-tag'

export const schema = gql`

type Listing {
  title: String!,
  description: String!,
  location: String!,
  company: String!
}

type ListingsPage {
  data: [Listing]
}

type Query{
  listings: ListingsPage
  jobs: [Listing]
}
`
```

#### Redwood.js Services
In our api/src/services directory we'll create a listings directory with a file called listings.js. Services are where Redwood centralizes all business logic. These can be used by your GraphQL API or any other place in your backend code. The listings function is querying the Fauna GraphQL endpoint and returning our posts data so it can be consumed by our ListingsCell.

```
// api/src/services/listings/listings.js
 
import { request } from 'src/lib/db'
import { gql } from 'graphql-request'
 
export const listings = async () => {
 const query = gql`
 {
   listings{
     data {
       title
       description
       location
       company
     }
 }
 }
 `
 
 const data = await request(query, 'https://graphql.fauna.com/graphql')
 return data['listings']
}

```
#### 5. Writing the application.

Now that our application is already set up, we can start creating pages. We’ll use the generate page command to create a home page and a folder to hold that page. The commands for generating a page is ‘generate’ although we can use g to save some typing.

```
yarn rw g page home /
```
On this page we will list all available job listings posted in our Fauna collection.

#### Redwood.js Cells.
In Redwood.js, cells provide a simpler and more declarative approach to data fetching. They contain the GraphQL query, loading, empty, error, and success states, each one rendering itself automatically depending on what state your cell is in.
Create a folder in web/src/components called `ListingsCell` and inside that folder create a file called `ListingsCell.js`.
Inside that file add the following code.

```
// web/src/components/ListingsCell/ListingsCell.js
 
export const QUERY = gql`
 query LISTINGS {
   listings {
     data {
       title
       description
       location
       company
     }
   }
 }
`
 
export const Loading = () => <div>Loading Job Listings...</div>
export const Empty = () => <div>No Job Listings yet!</div>
export const Failure = ({ error }) => <div>Error: {error.message}</div>
 
export const Success = ({ listings }) => {
 const {data} = listings
 return (
   <div style={{maxWidth:"50%", margin:"auto"}}>
     {data.map(listing => (
       <>
       <div style={{border: "black 1pt solid", padding: ".7em"}}>
       <h4>{listing.title}</h4>
       <p>{listing.description}</p>
       <p>Organization: {listing.company} <br/>
       Location: {listing.location}</p>
       </div>
       </>
     ))}
   </div>
 )
}
```

Now in our web/src/pages folder we will see a HomePage folder with a file named HomePage.js.

In this file add the following code.

```
import ListingsCell from 'src/components/ListingsCell'
 
const HomePage = () => {
 return (
   <>
     <h1>Fauna Redwood.js Job Board</h1>
     <ListingsCell />
   </>
 )
}
 
export default HomePage
```
#### 6. Testing App.

To preview if our app is working, we will need to run the following command in your terminal.

```
yarn rw dev
```

Then visit http://localhost:8910/ you should be greeted with a preview as shown below.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/j4c9lkilgdh6z3t54jic.png)


#### 7. Deploying to Netlify.
Redwood was created to make full-stack web apps easier to build and deploy on the Jamstack. Now that we have seen what building a Redwood app is like, how about we try deploying one?
To make the app  ready for deployment, we can take advantage of the Redwood generator. To do this, run the following code.

```
yarn rw g deploy netlify
```

This creates a file at /netlify.toml which contains the commands and file paths that Netlify needs to know about to build a Redwood application.

Next, we need to ensure our application is committed and pushed to Github. 


```
git init
git add .
git commit -m 'First commit'
git remote add origin ...
git push -u origin master
```
After this, we are going to link Netlify directly to our git repo so that a simple push to main will re-deploy our entire application.

In your Netlify account select the option “New Site from Git” and follow the prompts to link your repo and it should deploy automatically.

At this point, you will discover that the posts aren’t loading. The reason for this is the lack of a Fauna key in your Netlify environment. To resolve this, go to your application page.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/c789jfvuqvw6m1xwn21m.png)

In the Build & deploy tab, scroll to the Environment section and add your Fauna database key with the key FAUNA_KEY and save. 

Now your application is live and working. When you visit the application URL you should see a similar page.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/yeletwwuuseyawpjf16l.png)


Upon loading, you will see the job listings.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/iyiqgy8ty00rqhslstyc.png)

#### Conclusion

From this tutorial, we can see how simple it can be to develop a full stack application with Redwood and Fauna which is indeed a powerful database; with a web-native GraphQL interface, which supports custom business logic and integration with the serverless ecosystem. This enables developers to simplify code and ship faster.

Combined together with [Netlify](https://www.netlify.com), we can have a truly serverless and fully managed full stack application. The advantages we get from this architecture is a great boost to productivity as we can focus on implementing features that make our application and UX unique, instead of getting hung up on the DevOps of servers and databases.

I hope you find Fauna to be exciting, like I do, and that you enjoyed this article. Feel free to follow me on Twitter [@theAmolo](https://twitter.com/theAmolo) if you enjoyed this!

BONUS: 
All code written for this tutorial can be found in the following [Github Repo](https://github.com/brianraila/rw-fauna)