Creating a Next.js project with Chakra-UI integration

Introduction

Hello, in this tutorial I will show you how to create a simple Next.js project with Chakra UI intergration. ๐Ÿ‘€


What is Chakra-UI

Chakra-UI is an open source component library used for building modular, accessible and good looking user interfaces.

The main advantages of Chakra-UI are as follows:

  • Accessibility: Chakra-UI allows us to use pre-build components created by the Chakra-UI team.
  • Themeable: The library ships with a default theme, which can be customized if needed.
  • Light and dark mode: both are supported out of the box and can rely on the user's system settings. For example if the user sets their computer to dark mode by default, Chakra-UI will default to dark mode.
  • Composibility: Components can be created from the Chakra-UI ones or if needed custom components can be created with ease.
  • Typescript Support: Chakra-UI is written in TypeScript and provides class types for easy integration.

What we will be making

In this tutorial we will use Chakra-UI to create a simple user list/profile page. We will also integrate a toggler to toggle between light and dark mode.

You will learn how to set up a basic Next.js application with Chakra-UI integration.


Creating the Next.js application and installing the dependencies

First we need to create a new Next.js app and install the dependencies needed for the example.

The Next.js app can be created via the following command:

npx create-next-app@latest

This will set up the Next.js project automatically for you.

Next we need to install Chakra-ui which can be done via the following command:

yarn add @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^4 @chakra-ui/icons

Creating fake Users

Next we will need some fake users to actually populate the page. Create a "data" folder in the root directory and create a "users.js" file and populate it with the following data: (feel free to use your own custom data but be careful of the parameter names):

https://github.com/ethand91/nextjs-chakra-sample/blob/main/data/users.js


Creating the components

Next we need to create the components needed for the sample page, create a new folder called "components" and within that create a "TopBar" folder. Within the TopBar folder create a new file called "index.js" and populate it with the following contents:

import {
  Box,
  Button,
  useColorMode
} from '@chakra-ui/react';
import { MoonIcon, SunIcon } from '@chakra-ui/icons';

function TopBar() {
  const { colorMode, toggleColorMode } = useColorMode();
  const ColorModeIcon = colorMode === 'light' ? SunIcon : MoonIcon;

  return (
    <Box width="100%" padding="1" backgroundColor="purple.700">
      <Box maxWidth="container.xl" margin="auto">
        <Button
          aria-label="ui theme"
          leftIcon={ <ColorModeIcon /> }
          onClick={ toggleColorMode }
          size="xs"
          marginRight="2"
          borderRadius="sm"
        >
          Toggle Theme
        </Button>
      </Box>
    </Box>
  );  
};

export default TopBar;

Here we create a simple top bar for the application, we give it a background color of purple and also provide a button that allows the user to toggle between light/dark mode using Chakra-UI.

Next we need a component to display the users, so create a new "UserCard" directory and within that directory create an "index.js" file and populate it with the following contents:

import Link from 'next/link';
import {
  Box,
  Text,
  Avatar,
  Center,
  VStack,
  useColorModeValue
} from '@chakra-ui/react';

function UserCard(props) {
  return (
    <Link href={ `/users/${props.username}` } passHref>
      <VStack
        spacing="4"
        borderRadius="md"
        boxShadow="x1"
        padding="5"
        backgroundColor={
          useColorModeValue('gray.50', 'gray.700')
        }
      >   
        <Center>
          <Avatar size="lg" src={ props.avatar } />
        </Center>
        <Center>
          <Box textAlign="center">
            <Text fontWeight="bold" fontSize="xl">
              { props.first_name } { props.last_name }
            </Text>
            <Text fontSize="xs">{ props.job_title }</Text>
          </Box>
        </Center>
      </VStack>
    </Link>
  );  
};

export default UserCard;

This card will link to the user details page, using Chakra-UI we are easily able to center contents using "Center". We also use Avatar to easily display the user's profile picture.

Thats the components created.


Creating the Pages

Next we need to start working on the pages.

We will be overriding the default Next.js document which can be done by creating a "_document.js" inside the pages directory. Create the file and populate it with the following:

import { ColorModeScript } from '@chakra-ui/react';
import NextDocument, {
  Html,
  Head,
  Main,
  NextScript
} from 'next/document';
import { extendTheme } from '@chakra-ui/react';

const config = { 
  useSystemColorMode: true
};

const theme = extendTheme({ config }); 

export default class Document extends NextDocument {
  render () {
    return (
      <Html lang="en">
        <Head />
        <body>
          <ColorModeScript
            initialColorMode={ theme.config.initialColorMode }
          />
          <Main />
          <NextScript />
        </body>
      </Html>
    );  
  }
}

The reason for overriding the default layout is because we want to apply both light/dark theme to the entire page.

Next we need to apply Chara-UI to the application so open up pages/_app.js and change the contents to the following:

import { ChakraProvider, Box } from '@chakra-ui/react';
import TopBar from './../components/TopBar';

function MyApp({ Component, pageProps }) {
  return (
    <ChakraProvider>
      <TopBar />
      <Box maxWidth="container.xl" margin="auto">
        <Component { ...pageProps} />
      </Box>
    </ChakraProvider>
  );  
}

export default MyApp

Here we bascially tell Next.js to use the Chara-UI provider and make sure everypage has our custom TopBar.

Next we need to edit the pages/index.js to contain the following contents:

import {
  Box,
  Grid,
  Text,
  GridItem
} from '@chakra-ui/react';

import UserCard from './../components/UserCard';
import users from './../data/users';

export default function Home() {
  return (
    <Box>
      <Text
        fontSize="xxx-large"
        fontWeight="extrabold"
        textAlign="center"
        marginTop="9"
      >   
        Users
      </Text>
    
      <Grid
        gridTemplateColumns={ ['1fr', 'repeat(2, 1fr)', 'repeat(3, 1fr)'] }
        gridGap="10"
        padding="10"
      >   
        {
          users.map((user) => (
            <GridItem key={ user.id }>
              <UserCard { ...user } />
            </GridItem>
          ))
        }
      </Grid>
    </Box>
  );  
}

Here we basically list all the users using Chakra-UI's Grid component. The "gridTemplateColumns" allows us to set the sizes for small screens, medium screens and large screens. For example if you view the page on a large screen each row will have 3 users, however if you view it on a mobile device each row will only have one user.

Feel free to run the project using:

npm run dev

If you access the page (https://localhost:3000), you should see the following page:

User List Dark

If you prefer light mode you should see the following:

![User List Light](https://i.ibb.co/54TD5GR/user-list-light.png" alt="user-list-light)

Feel free to play with the toggle button. If you try clicking on a user you will be greeted with a 404 not found response so let's create the user profile page!

Create a "users" folder inside the pages folder and create the "[username].js". (Note if you're using a terminal like me you may need to escape the brackets with a backslash).

Now fill the file with the following contents:

mport Link from 'next/link';
import {
  Avatar,
  Box,
  Center,
  Text,
  Image,
  Button,
  Flex,
  useColorModeValue
} from '@chakra-ui/react';

import users from './../../data/users';

export function getStaticPaths() {
  const paths = users.map((user) => ({
    params: {
      username: user.username
    }   
  }));

  return {
    paths,
    fallback: false
  };  
}

export function getStaticProps({ params }) {
  const { username } = params;

  return { 
    props: {
      user: users.find((user) => user.username === username)
    }   
  };  
};

function UserPage({ user }) {
  return (
    <Center
      marginTop={ ['0', '0', '8' ] }
      boxShadow="lg"
      minHeight="fit-content"
    >
      <Box>
        <Box position="relative">
          <Image src={user.cover_image} width="fit-content" height="250px" objectFit="cover" />

          <Flex
            alignItems="flex-end"
            position="absolute"
            top="0"
            left="0"
            backgroundColor={
              useColorModeValue('blackAlpha.400', 'blackAlpha.600')
            }
            width="100%"
            height="100%"
            padding="8"
            color="white"
          
            <Avatar size="lg" src={ user.avatar } />
            <Box marginLeft="6">
              <Text as="h1" fontSize="xx-large" fontWeight="bold">
                { user.first_name } { user.last_name }
              </Text>
              <Text as="p" fontSize="large" lineHeight="1.5">
                { user.job_title }
              </Text>
            </Box>
          </Flex>
        </Box>
        <Box
          maxW="container.xl"
          margin="auto"
          padding="8"
          backgroundColor={
            useColorModeValue('white', 'gray.700')
          }
        >
          <Text as="p">{ user.description }</Text>
          <Link href="/" passHref>
            <Button marginTop="8" colorScheme="whatsapp" as="a">
              Back to all users
            </Button>
          </Link>
        </Box>
      </Box>
    </Center>
  );
};

export default UserPage;

Phew! Here we use "getStaticPaths" to tell Next.js we need to render a new page for each user in the user's array. We also tell Next.js to display the default 404 page if the requested user is not found.

Chakra-UI allows us to easily center the contents. This page basically displays the contents of the user and provides a button to go back using a Chakra-UI feature.

All done fire up the dev server and load up https://localhost:3000 in the browser. Once loading try clicking on a user you should see the following page:

User Profile Dark

User Profile Light

All done! ๐Ÿ˜Ž


Conclusion

Here I have demonstrated how to use Next.js with Chakra-UI. Feel free to customize anyway you wish. ๐Ÿ˜‰

I'm actually thinking of using Next.js for my next side project.

Hopefully you have learned something new, you can find the source code for this tutorial via: https://github.com/ethand91/nextjs-chakra-sample


Like me work? I post about a variety of topics, if you would like to see more please like and follow me. Also I love coffee.

โ€œBuy Me A Coffeeโ€