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 installand 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 Postgres.app) 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 withreact-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-prismafor 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: {
...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>
{posts.map((p) => (
<Box p={5} shadow="md" key={p.id}>
<Heading>{p.title}</Heading>
{p.body}
</Box>
))}
</Stack>
);
};
Don’t forget to include the cell in the component:
export function PostList() { return <FetchPostsCell />;}
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.
Conclusion
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.
Contributor’s Bio
Mike Cavaliere is a web development veteran, personal development devotee, and ADHD/brain improvement aficionado who works as a Senior Software Engineer at Echobind.
He also blogs about software at MikeCavaliere.com and brain improvement at ADHDTechies.com.
--
This post originally appeared on the Echobind blog.
Top comments (0)