Setup your NextJS app
Tags: webdev, javascript, nextjs, googlecloud
Published: 2023-08-31 14:08:57

If you're looking to setup easy authentication for your users in NextJS, you're in the right place!

In this guide, I will show you all the steps necessary to setup your NextJS app, add google authentication to it (the `Sign In With Google` button), and deploy the application to production (using [Vercel](https://vercel.com/noblica)). 

**This is the first part of the guide**, which will focus on just setting up your NextJS environment.

# Generating the boilerplate

To setup our app, we're gonna use the tried and true method from [the official documentation](https://nextjs.org/docs/getting-started/installation). NextJS has a great CLI tool, which you don't even need to install separately. 
If you already have `node` installed, simply run `npx create-next-app@latest` in your projects directory, and answer the following questions as you please. Since I'm a big fan of **Tailwind** and **TypeScript**, this is the setup I used:

![Next project setup](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vjueu6p5om4h08k57ghc.png)

# Creating the pages

Let's personalize our app a bit. We can start by adding our sign in, and sign out buttons.

`app/components/SignInButton.tsx`
```tsx
"use client"

import { useRouter } from "next/navigation"

export const SignInButton = () => {
  const { push } = useRouter();

  return (
  <button 
    onClick={() => push("/")}
    type="button" className="text-white w-full bg-[#4285F4] hover:bg-[#4285F4]/90 focus:ring-4 focus:outline-none focus:ring-[#4285F4]/50 font-medium rounded-lg text-sm px-5 py-2.5 text-center inline-flex items-center justify-center dark:focus:ring-[#4285F4]/55">
    <GoogleIcon />
    Sign in with Google
  </button>
  )
}

const GoogleIcon = () => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    aria-hidden="true"
    className="mr-2 -ml-1 w-4 h-4"
    data-icon="google"
    data-prefix="fab"
    viewBox="0 0 488 512"
  >
    <path
      fill="currentColor"
      d="M488 261.8C488 403.3 391.1 504 248 504 110.8 504 0 393.2 0 256S110.8 8 248 8c66.8 0 123 24.5 166.3 64.9l-67.5 64.9C258.5 52.6 94.3 116.6 94.3 256c0 86.5 69.1 156.6 153.7 156.6 98.2 0 135-70.4 140.8-106.9H248v-85.3h236.1c2.3 12.7 3.9 24.9 3.9 41.4z"
    />
  </svg>
)
```

`app/components/SignOutButton.tsx`
```tsx
"use client"

import { useRouter } from "next/navigation"

export const SignOutButton = () => {
  const { push } = useRouter();
  return (
    <button className="text-black hover:text-sky-600"
      onClick={() => push("/signin")}
    >Sign out</button>
  )
}
```

For now, the only thing that should happen when clicking on these buttons is a redirect to the home page (`/`), or to the sign in page (`/signin`).

**A note on "use client"**: This is a new syntax specific to using NextJS with the App router. It marks the component as a **client component**, which means it needs to load JavaScript on the client side.
Client components are different from **server components**, which render only on the server. If you would like a deeper explanation of server vs client components, you can check out the official documentation on [server components](https://nextjs.org/docs/app/building-your-application/rendering/server-components) and [client components](https://nextjs.org/docs/app/building-your-application/rendering/client-components).

Next, let's **create our Sign in page**, so we can use our signin button!

`app/signin/page.tsx`
```tsx
import { redirect } from "next/navigation";
import { Metadata } from "next";
import { SignInButton } from "../components/SignInButton";

export const metadata: Metadata = {
  title: 'Signin',
  description: 'Please sign in ',
}

export default async function SignInPage() {

  return (
    <>
      <div className="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
        <div className="sm:mx-auto sm:w-full sm:max-w-sm">
          <h2 className="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
            Sign in to your account
          </h2>
        </div>

        <div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
          <SignInButton />
        </div>
      </div>
    </>
  )
}
```

Regarding the global styling, we can remove almost everything from the `global.css` file, and leave only the following:

`app/global.css`
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

This will just apply the Tailwind CSS reset, and make it possible to use Tailwind classes inside our components. 

For the home page itself, let's just make it as simple as possible and just leave some text indicating we're on the homepage, and also add our `SignOutButton` so we can navigate back to the sign in page:

`app/page.tsx`
```tsx
import { SignOutButton } from './components/SignOutButton';

export default async function Home() {

  return (
    <>
      <header className="border-b border-gray-200 bg-white">
        <div className="mx-auto max-w-7xl px-4">
          <div className="flex gap-10 items-center w-full justify-between lg:justify-end my-2 px-4">
            <SignOutButton />
          </div>
        </div>
      </header>
      <main className="flex min-h-screen flex-col items-center justify-between p-24">
        <h1>Hello from the homepage!</h1>
      </main>
    </>
  )
}

``` 

Running our app now using `npm run dev`, and visiting http://localhost:3000 in the browser should show the following:

![Home page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p34w694jeiu36oc3nhd8.png)

And clicking on `Sign Out`, should take you to the `/signin` page, which should look like this:


![Sign In page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g7uu3k2x9286rwmqe0xh.png)

Here's a link to the acompanying [github repo](https://github.com/noblica/next-google-auth), which contains all the code from this blogpost.
I have also deployed this code snippet on Vercel, [available here](https://next-google-auth-lac.vercel.app/signin).


But what good are all these sign in and sign out buttons without some actual authentication logic behind them?

We will expand on that topic in the following chapter!