A JAMStack Blog in No Time with Next.js & Bison

Mike Cavaliere
Mike CavaliereMonday, October 19, 2020
a bull and a shield

Next.js is a fantastic framework for building fast and powerful JAMStack web applications — that’s one reason among many that it’s our go-to JavaScript framework at Echobind. We’ve wrapped Next.js with a set of tools we regularly use into a JAMStack generator called Bison, which makes Next.js even more powerful. In this article, I’ll show you the steps to building a custom blog with Bison and Next.js.

If you want to jump right to the code, here’s the repo on GitHub.

Run the Bison Generator

yarn create bison-app bison-blog

This will generate your app skeleton, run yarn install and create a Git repo automatically.

Set up your database

You’ll want to check the latest README for full steps, but it’s as simple as making sure PostgresSQL is running (I highly recommend and running yarn db:setup


You’ll be asked a few questions during setup, and it’ll do the rest of the work for you.

Start the app

Run yarn dev from the directory you just created, and visit http://localhost:3000. Your app is running, and you should see a screen like the one below. We’re in business.

Create a user account

Bison comes pre-packaged with a simple user authentication mechanism, so signing in or signing up is a cinch.

First, tap Login to get to the login screen, then click Sign Up.

Fill out the form and submit, and you’ll be logged in and redirected to the home page.

Add some database tables

We’ll need a Posts table and model to create and list posts. Edit schema.prisma which is the source of truth for the data model. Adding a Post model is pretty easy.

Then run yarn prisma migrate save --experimental, to generate a database migration for it.

Now run the migration using yarn db:migrate.

If you look at your database using Postico or psql, you’ll see the resulting table and columns.

Generate a page for creating posts

Use Bison’s page generator to stub the /posts/new page:

yarn g:page posts/new

Generate components

We’ll need 2 React components for creating and showing posts PostList and PostForm, so we’ll generate them with Bison’s CLI commands. These wrap 👍 some pre-packaged Hygen generators that Bison comes with.

yarn g:component PostList yarn g:component PostForm

Now you’ll see these 4 new files in your folder tree:

All rightie! Let’s add some code.

Create the “New Post” form

The page container for /posts/new.tsx is quite simple; aside from styling, we add the component which we’ll build immediately after.

import React from 'react'; import Head from 'next/head'; import { Heading, Flex } from '@chakra-ui/core'; import { PostForm } from '../../components/PostForm'; function PostsNewPage() { return ( <> <Head> <title>PostsNewPage</title> </Head> <Flex direction="column" justify="center"> <Heading size="lg">New Post</Heading> <PostForm /> </Flex> </> ); } export default PostsNewPage;

Create the component

Full code is here. Here are some highlights.

Bison comes packaged with react-hook-form, so we build the form out like this:

<form onSubmit={handleSubmit(onSubmit)}> <FormControl isInvalid={errors.title}> <FormLabel htmlFor="title">Post Title</FormLabel> <Input type="text" name="title" id="title" ref={register({ required: true })} /> <FormErrorMessage>{errors.title && <span>This field is required</span>}</FormErrorMessage> </FormControl> <FormControl isInvalid={errors.body}> <FormLabel htmlFor="body">Post Body</FormLabel> <Textarea name="body" id="body" ref={register({ required: true })} /> <FormErrorMessage>{errors.body && <span>This field is required</span>}</FormErrorMessage> </FormControl> <Button type="submit">Submit</Button> </form>

Because Bison also sets up nexus-plugin-prisma for us, We add a mutation to create a post like so:

export const CREATE_POST_MUTATION = gql` mutation CreatePost($data: PostCreateInput!) { createOnePost(data: $data) { id title body } } `;

In turn, Bison’s graphql-codegen configuration sees the above and generates a nice React hook for us to plug into 🎉:

import { useCreatePostMutation } from '../types';

We use this and a few other hooks to get our data into the form component:

export function PostForm() { const { register, handleSubmit, errors } = useForm(); const [createPost] = useCreatePostMutation(); const router = useRouter(); const { user: { id: userId } = {} } = useAuth(); // ... }

And here’s the onSubmit handler which triggers the createPost mutation and redirects back to the homepage upon success:

const onSubmit = async (data) => { // Create the post await createPost({ variables: { data: {, author: { connect: { id: userId, }, }, }, }, }); // Redirect to homepage await router.replace('/'); };

Now we’ve got a form that saves a post to the database. Voila. 🚀

Create the component

Now that we’ve got data, let’s display it.

If you remember, we already ran the generator for the component. So we start by importing the into the homepage and displaying it like so:

Now we’ll need to fetch and display the posts. When fetching data with Bison, we recommend something called a “cell.” A cell is a concept borrowed from Redwood.js. It’s a declarative way of wrapping the GraphQL query together with loading, success, and error states.

yarn g:cell FetchPosts will create /cells/FetchPosts.tsx as below.

Now we’ll fill the cell out with the correct query and some formatting for the rendered posts.

Full code here. Important snips:

export const POSTS_QUERY = gql` query posts { posts { id title body } } `; export const Success = ({ posts }: PostsQuery) => { return ( <Stack> { => ( <Box p={5} shadow="md" key={}> <Heading>{p.title}</Heading> {p.body} </Box> ))} </Stack> ); };

Don’t forget to include the cell in the component:

export function PostList() { return ; }

And we’re done. You now have a (very simple and basic but functioning) blog built in Next.js. Add some data and start having fun.


Bison is in its early stages, but is already a useful tool for kickstarting your Next.js project quickly with great stuff like Prisma, Nexus, and Hygen built-in.

If you try out this tutorial, please drop me a line with any feedback or questions. Or comment right here.

Share this post


Related Posts:

Interested in working with us?

Give us some details about your project, and our team will be in touch with how we can help.

Get in Touch