Fauna logo
FeaturesPricing
Learn
Customers
Company
Support
Log InSign Up
Fauna logo
FeaturesPricing
Customers
Sign Up
© 2021 Fauna, Inc. All Rights Reserved.
<- Back
nextjs-fauna-graphql
Community Contribution

Using Next.js with Fauna and GraphQL

Lee Robinson|Aug 5th, 2021
Next.js is a frontend framework, powered by React, which provides optimizations and tools to create fast websites. It supports both hybrid static pages, as well as dynamic, real-time content. With built-in integrations like TypeScript and ESLint, Next.js simplifies the Developer Experience (DX) and optimizes for serverless and edge deployments.
Next.js is not opinionated about where you store your data. It provides APIs for the developer to hook into their content, commerce, or database of choice. Since Next.js is optimized for serverless, it makes sense to pair it with a serverless database.

Why Fauna with Next.js?

Fauna is a serverless, transactional database. It's flexible like NoSQL databases, with support for relational data and transactions. Plus, it has an excellent free tier and is a managed service. No servers to maintain or hidden fees!
Since it's serverless-first, you can consider Fauna "connectionless". Instead of battling connection limits, Fauna provides a database as an API, allowing developers to not worry about connection limits in serverless environments. Further, it provides a GraphQL API, which simplifies creating, querying, and updating your data.

Why Vercel with Next.js?

Vercel is a serverless platform for static applications and frontend frameworks, providing a frictionless Developer Experience to take care of the hard things: deploy instantly, scale automatically, and serve personalized content around the globe.
Vercel makes it easy for frontend teams to develop, preview, and ship delightful user experiences, where performance is the default. Fauna.com is built with Next.js and Vercel!
Let's explore deploying a Next.js app using Fauna to Vercel.

Deploying Next.js and Fauna to Vercel

Getting started with Fauna and Next.js only takes a few minutes, thanks to the official Next.js template and the Vercel Integration. The integration will allow you to create or connect to your Fauna database, create a new key, and then add it as an Environment Variable to your Vercel project. The value will be saved as FAUNA_ADMIN_KEY.

Manual Installation

Alternatively, you can start from the command line locally and clone the template using create-next-app.
npx create-next-app --example with-fauna with-fauna-app
Next, create a database and generate an admin token by going to the Security tab on the left and then click New Key. Give the new key a name and select the Admin Role. Save the token.

Setting Up Your Schema

The Next.js and Fauna example includes a setup script (npm run setup). After providing your admin token, the script will:
  • Import your GraphQL schema: Fauna automatically sets up collections and indexes to support your queries. You can view these in your project dashboard under GraphQL.
  • Create an index and function: The script will create a GraphQL resolver that uses User-defined functions based on a sorting index.
  • Create a scoped token: This token is for use on the client side. The admin key can be used on the server side.
After the script completes, a .env.local file will be created for you with the newly generated client token assigned to an Environment Variable.

Connecting to Fauna in your Next.js Application

To connect to your Fauna database with GraphQL, you can use the graphql-request library to securely fetch or mutate data inside lib/fauna.js.
// lib/fauna.js

import { GraphQLClient, gql } from 'graphql-request'

const graphQLClient = new GraphQLClient('https://graphql.fauna.com/graphql', {
  headers: {
    authorization: `Bearer ${process.env.FAUNA_ADMIN_KEY}`,
  },
})
Alternatively, you can use the Fauna JavaScript driver to execute FQL queries in Node.js.

Querying Fauna with GraphQL

Now that your GraphQL client has been created, you can query or mutate data using your secure connection.
// lib/fauna.js

export const listGuestbookEntries = () => {
  const query = gql`
    query Entries($size: Int) {
      entries(_size: $size) {
        data {
          _id
          _ts
          name
          message
          createdAt
        }
      }
    }
  `

  return graphQLClient
    .request(query, { size: 999 })
    .then(({ entries: { data } }) => data)
}

Displaying your Fauna Data inside Next.js

Since Next.js can handle multiple rendering strategies, including static-site generation, server-side rendering, and client-side rendering, we can display our data from Fauna in many ways.

Static Site Generation

Using getStaticProps and getStaticPaths, we can statically generate all of the content from our Fauna database.
// pages/entries/[id].js

export default function Entry({ entry }) {
  // Render entry...
}

// This function gets called at build time
export async function getStaticPaths() {
  // Query all entries from Fauna
  const res = await listGuestbookEntries()
  const entries = await res.json()

  // Get the paths we want to pre-render based on entries
  const paths = entries.map((entry) => ({
    params: { id: entry['_id'] }
  }))

  // We'll pre-render only these paths at build time.
  // { fallback: false } means other routes should 404.
  return { paths, fallback: false }
}

// This also gets called at build time
export async function getStaticProps({ params }) {
  // params contains the key `id`.
  // If the route is like /entries/1, then params.id is 1
  // We could create getGuestbookEntry similar to listGuestbookEntries
  const res = await getGuestbookEntry(params.id)
  const entry = await res.json()

  // Pass entry data to the page via props
  return { props: { entry } }
}

Server-Side Rendering

If we need to fetch new data from every request, we can use getServerSideProps.
// pages/index.js

export default function Entries({ entries }) {
  // Render entries...
}

export async function getServerSideProps(context) {
  // Query all entries from Fauna
  const res = await listGuestbookEntries()
  const entries = await res.json()

  // Pass entry data to the page via props
  return {
    props: { entries }
  }
}

Client-Side Rendering

If we want to fetch data on the client-side, initially showing a loading state, we can use a React hook library like SWR to simplify data fetching.
// pages/index.js

import useSWR from 'swr'

const fetcher = (...args) => fetch(...args).then(res => res.json())

export default function Entries() {
  const { data, error } = useSWR('/api/entries', fetcher)

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}
This example fetches the Fauna data from an API Route, which allows us to securely connect to Fauna on the server.
// pages/api/entries.js

import { listGuestbookEntries } from '../../lib/fauna'

export default async function handler(req, res) {
  const entries = await listGuestbookEntries()

  return res.json(entries)
}

Next Steps

Try out Fauna and Next.js today and deploy to Vercel. Next, you can explore:

If you enjoyed our blog, and want to work on systems and challenges related to globally distributed systems, serverless databases, GraphQL, and Jamstack, Fauna is hiring!

Share this post

TwitterLinkedIn

Subscribe to Fauna blogs & newsletter

Get latest blog posts, development tips & tricks, and latest learning material delivered right to your inbox.

<- Back