How to Connect a Next.js Frontend to Your Redwood API

This example contains two separate repositories, one for the Redwood API and another for the Next frontend. Deploying them both from the same repo is certainly possible but may pose a challenge with getting the correct build commands and publish directories, so I’ve punted on that for now. If anyone is curious to see an example with a monorepo containing both apps just let me know and I’ll see what I can do.

The code for this example can be found on my GitHub.

Outline

Create Redwood App

We will be deploying this to Vercel.

yarn create redwood-app redwood-next
cd redwood-next
yarn rw setup deploy vercel

Prisma Schema

Our schema has the same Post model used in the Redwood tutorial.

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider      = "prisma-client-js"
  binaryTargets = "native"
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  body      String
  createdAt DateTime @default(now())
}

Set database connection string

Include DATABASE_URL in .env. See this post for instructions on quickly setting up a remote database on Railway.

DATABASE_URL=postgresql://postgres:password@containers-us-west-10.railway.app:5513/railway

Apply migration to the database and scaffold admin dashboard

yarn rw prisma migrate dev --name posts
yarn rw g scaffold post

Open localhost:8910/posts/new and create a post.

Create GitHub repository

git init
git add .
git commit -m "Nextification"
gh repo create redwood-next --public
git remote add origin https://github.com/ajcwebdev/redwood-next.git
git push -u origin main

Select the Redwood framework preset and include your database connection string. Make sure to include ?connection_limit=1 at the end of the connection string.

Test your endpoint

Our API is now deployed. Hit https://redwood-next.vercel.app/api/graphql with your favorite API tool or curl.

curl \
  --request POST \
  --header 'content-type: application/json' \
  --url 'https://redwood-next.vercel.app/api/graphql' \
  --data '{"query":"{ redwood { version currentUser prismaVersion } }"}'
{
  redwood {
    version
    currentUser
    prismaVersion
  }
}
{
  "data": {
    "redwood": {
      "version": "0.39.3",
      "currentUser": null,
      "prismaVersion": "3.5.0"
    }
  }
}
curl \
  --request POST \
  --header 'content-type: application/json' \
  --url 'https://redwood-next.vercel.app/api/graphql' \
  --data '{"query":"{ posts { id title body createdAt } }"}'
{
  posts {
    id
    title
    body
    createdAt
  }
}
{
  "data": {
    "posts": [
      {
        "id": 1,
        "title": "Redwood+Next",
        "body": "The next best thing?",
        "createdAt": "2021-12-09T19:55:33.292Z"
      }
    ]
  }
}

Create Next App

Give your project a name, cd into it, and install Apollo Client.

yarn create next-app redwood-next-frontend
cd redwood-next-frontend
yarn add @apollo/client graphql

Start your development server.

yarn dev

Open localhost:3000/.

Add posts query to Next frontend

Open pages/index.js and include the following code with your endpoint.

// pages/index.js

import Head from 'next/head'
import { ApolloClient, InMemoryCache, gql } from '@apollo/client'
import styles from '../styles/Home.module.css'

export default function Home({ posts }) {
  return (
    <div className={styles.container}>
      <Head>
        <title>Redwood+Next</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main>
        <h1>Redwood+Next ▲</h1>

        <div>
          {posts.map(post => {
            return (
              <ul key={post.id}>
                <li>
                  <h3>{post.title}</h3>
                  <p>{post.body}</p>
                </li>
              </ul>
            )
          })}
        </div>
      </main>
    </div>
  )
}

export async function getStaticProps() {
  const client = new ApolloClient({
    uri: 'https://redwood-next.vercel.app/api/graphql',
    cache: new InMemoryCache()
  })

  const { data } = await client.query({
    query: gql`
      query GetPosts {
        posts {
          id
          title
          body
        }
      }
    `
  })

  return {
    props: {
      posts: data.posts
    }
  }
}

Follow the previous steps to create a GitHub repository and deploy it on Vercel. Visit redwood-next-frontend.vercel.app to see your project.

10 Likes

Great article! This is something I been strongly considering for our customer portal. To allow for SSR.

A great addition to this would be to get authentication working within nextjs - any suggestions on how to connect the redwood API and get auth working within nextjs?

1 Like

The API itself has lots of great built in directives now, but I would assume that all the current Redwood auth solutions on the frontend are tied to the Redwood Web side and thus would not make a good drop in solution for this. (Someone can correct me if I’m wrong about that).

I know that most people will recommend NextAuth for adding authentication to a Next app. I haven’t tried it myself and I’ve heard a wide range of experiences from people who have actually used it, both positive and negative.

1 Like

Great article, i really want to know how to use it with authentication

Hey @renofizaldy! As I mentioned in my previous comment, NextAuth is probably the tool to look at to achieve this.

Since I made that comment there is actually a really interesting new metaframework called create-t3-app that gives you the ability to automatically configure NextAuth with your Next.js application.

That’s what I would look at to try and smooth out this experience, as I learn more about the framework I may build out an example with Redwood but can’t promise that’ll be anytime soon.

It would be nice if someone trying to verify @ajcwebdev’s tutorial adds the list of differences that @ajcwebdev described as:

but I would assume that all the current Redwood auth solutions on the frontend are tied to the Redwood Web side and thus would not make a good drop in solution for this

@ajcwebdev I believe that your efforts to “marry” RW with other frameworks have lots of value for further RW utility / popularity. With this realization I plan to try to continue your work, starting with my own proposal:

It would be nice if someone trying to verify @ajcwebdev’s tutorial adds the list of differences with respect to identity management

At the moment, I still owe to myself to dig into RW Authentication and determine where are user data hosted (see manage users)