DEV Community

h8moss
h8moss

Posted on

Build an instagram clone with react, next 13 and firebase part 1: Setup

Introduction

Good day everyone! Today we are gonna start working on a new tutorial series on firebase.

In this series we will use firebase and nextjs 13 to build a clone of instagram, complete with the following functionality:

  • Google and email sign in (with Firebase auth)
  • CRUD functionality for posts and comments (with Firebase firestore)
  • Hosting of our own images and gifs (with Firebase storage)
  • Simple automatic banning of undesired content (with Firebase functions)

I'll even throw in hosting in vercel (NextJs is easier to host in vercel than in firebase)

Hopefully this all sounds exiting, this first part of our project will focus on setting up firebase, and our NextJs project.

  • Little shameful advertising time! I actually will upload this series in my own personal website over at daniel-armenta.com. I will post parts there first, so consider checking it out and letting me know when you inevitably find bugs in my website.

Create a NextJs 13 project

To begin, let's create a new project with NextJs version 13.
To do this, run the following command inside your projects directory:

npx create-next-app@latest --ts instagram-tutorial
Enter fullscreen mode Exit fullscreen mode

For this project I will be using typescript, so I added the --ts flag, but I will also share the javascript code here for you to use if you don't like typescript, so feel free to remove that flag.

Running this command will give you the following output if you haven't installed create-next-app:

Need to install the following packages:
  create-next-app@13.3.2
Ok to proceed? (y)
Enter fullscreen mode Exit fullscreen mode

Go ahead and press enter and now you will be given a few options, I'll show what I set up, but if you have some different preference, feel free to change your answers.

  1. Would you like to use ESLint with this project? ... No / Yes
  2. Would you like to use Tailwind CSS with this project? ... No / Yes
  3. Would you like to use src/ directory with this project? ... No / Yes
  4. Would you like to use experimental app/ directory with this project? ... No / Yes
  5. What import alias would you like configured? ... @/*

Warning! keep in mind that if you decide not to use the experimental app directory, your project and mine will look very different

After running this command and waiting a bit, you should see a message like the following:

Success! Created instagram-tutorial at D:\Users\h8moss\projects\instagram-tutorial
Enter fullscreen mode Exit fullscreen mode

Go ahead and open the project in your favorite code editor and run npm run dev to start debugging on localhost:3000

Open localhost:3000 and you should see something like this:
Screenshot of initial project

Now over at our code editor, we can see our project looks like this:

File tree

The .next, .vscode and node_modules folders can be ignored. We can also ignore .gitignore, README.md, next.env.d.ts, package.json and package-lock.json

The public folder includes static files for our app, like the logo or a robots.txt file if we wanted.
The next.config.js file contains configuration for our nextJs project, we can leave it be for now.
tsconfig.json has simple typescript configuration for the project.

Finally, the src directory will contain all of our code. The app directory inside it determines the routing of our app.

We can see there is a page.tsx and a layout.tsx at the root of our app, there is also a route.ts at /api/hello. If you are new to nextjs 13, I will explain what all of these routes are shortly.

Inside the app directory, there are special files identified by their names, we currently have the following:

  • The page.tsx file, which defines a page inside of our app.
  • The layout.tsx file, which defines code that every child page will have.
  • The route.ts file which defines an API handler route.

There are also other special files we will come to know later down the tutorial series.

For now, the route.ts file inside /api/hello folder means that localhost:3000/api/hello works as an API directory, we don't actually need this behaviour, so let's remove the entire /api folder.

We also have a layout.tsx file at the root of our app folder, this means that every route will share the code inside this layout file. The layout file looks like this:

import './globals.css'
import { Inter } from 'next/font/google'

const inter = Inter({ subsets: ['latin'] })

export const metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
    </html>
  )
}
Enter fullscreen mode Exit fullscreen mode

This file first imports the globals.css file, which contains our general css.
Then imports and defines Inter which is the font used in the example.
Next we export a metadata object, which has head related information like the title and description.
It finally, exports a component, which just defines an html tag with a body and the {children} property, which will be replaced with the actual code of our pages.

All of this is pretty basic stuff, so we won't change much, let's just change the metadata object to align more with what we are trying to make:

export const metadata = {
  title: "Instagram clone",
  description:
    "A simple website for a tutorial, showcasing the capabilities of Nextjs and firebase",
};
Enter fullscreen mode Exit fullscreen mode

Let's also go over to globals.css and replace all of the default styles with something much more simple:

* {
  padding: 0;
  margin: 0;
}

html,
body {
  max-width: 100vw;
  overflow-x: hidden;
}

a {
  color: inherit;
}
Enter fullscreen mode Exit fullscreen mode

If we need more global styles, we can add them later.

This is not a CSS tutorial, so the styles we will be using will not be explained and they will be very rudamentary, I will give you the styles but I won't explain them, so feel free to experiment with your own styles.

The next file we have to take a look at is the page.tsx file.

This file, as it is in the root of our app directory, defines the root of our website, it currently has a lot of code for the website we saw earlier, so let's replace it with something far more simple:

const Root = () => {
  return (
    <div>
      <h1>Hello world</h1>
      <p>Welcome to NextJs 13</p>
    </div>
  );
};

export default Root;
Enter fullscreen mode Exit fullscreen mode

We can also delete the page.module.css file for now, as we don't have any page specific styles.

Do keep in mind we will probably create it again later, so you can just delete the contents if you want.

Setting up a firebase project

Now that we have a basic NextJs project, let's go ahead and create a firebase project.

To do this, I took the liberty of making a scribe document

If you can't see, or don't want to use the scribe, the actual steps are as follows:

  1. Go to the firebase console
  2. Sign in or create an account
  3. Click on "Add project"
  4. Give the project a name
  5. Select continue until asked about google analytics account
  6. Select default account.
  7. Select continue again
  8. Wait for the project to be created.
  9. Press continue

Now that we have a firebase project, we are gonna set up the following things:

  1. Authentication
  2. Database
  3. Storage

So first, over to the left there are some menus, under the build menu we will find the authentication option, go ahead and click it.

Setting up authentication

You know what to do, let's go over to the authentication page:
Navigating to authentication menu

Now that we are on the authentication page, let's click on the "get started" button, which after a while will take you to the following page:

Image description

This page has a list of all the different sign in options a user can have. There are 3 categories:

  1. Native providers: The most basic providers, like email and password or phone authentication
  2. Additional providers: Providers that use some different website to sign in, like twitter or google.
  3. Custom providers: These providers allow you to use some special features of authentication, but have different pricing, you can read more here

For our project, we only want the email/password provider and the google provider

Let's first register the email provider, which requires the least configuration of all, go ahead and click on the email/password button.

You will see 2 options, the first enables normal email/password sign in, the second enables password-less sign in. We only want email/password sign in, so let's only enable that one

Image description

Now it is possible to sign in to our website using an email and a password, let's continue by activating google sign in, which requires a "public-facing name" and a "support email".

So go click on the new "add new provider" button and add the google provider:

Image description

With this, we now have activated the possibility of signing in with either google or a username and password.

Challenge

With the google and email sign in we have more than enough providers, but would you like to add a different provider into your app? You could try to add a facebook sign in option or a twitter sign in option, both of which require a developer account with either facebook or twitter, which I don't have by principle, but nothing is stopping you from making them.

Here are some resources:

Setting up a database in firebase

Firebase also comes with two different databases we could use, the realtime database and the firestore database. We are gonna be using the firestore database for this project.

Go ahead and click on the firestore button on your build menu:

Image description

You should see a button to create a database, go ahead and click it, you will be asked 2 questions.

The first question asks about "production" vs "test" mode, this sets the rules for accessing the database, production mode defaults all operations to false, so you have to manually set rules while test mode sets them to true for a few days and changes them to false later.

We are gonna write our own rules later down the line, but for now, pick test mode.

The second question asks you where should the database be set up, for most projects you are gonna want either nam5 (US) or eur3 (Europe) depending on when you live. I live in Mexico, so I picked the US as that is closer.

Image description

We have now created a working database, from this page we can view and edit the database's values, we will come back to this page in the firestore chapter, but for now, let's setup the storage system.

Setting up storage

One last time, go over to the menu, this time click on storage:

Image description

You will be asked the same questions as when setting up firestore, but this time you won't be able to change the region as both firestore and storage must use the same region.

Go ahead and put the same values in.

Image description

With that, our firebase storage should be working, we could start uploading stuff to it right now.

Adding Firebase to our NextJS project

Now that we have created a firebase repository, we should try to add firebase to our NextJS project, to do that, let's install the firebase dependency:

npm install firebase
Enter fullscreen mode Exit fullscreen mode

In order to use firebase, we need some information about our firebase project, this information is private and so we are gonna put it inside of a .env.local file. NextJS automatically reads any .env.local files in our repository and sets them as the keys of the process.env object.

Note that, in reality, the data we are gonna store is not so sensitive that we need to use a .env.local file to hide it. Still, it is a good idea to do so, just in case.

So create a .env.local file at the root of the project And fill it with the following:

NEXT_PUBLIC_FIREBASE_API_KEY=...
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=...
NEXT_PUBLIC_FIREBASE_PROJECT_ID=...
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=...
NEXT_PUBLIC_FIREBASE_MESSAGE_SENDER_ID=...
NEXT_PUBLIC_FIREBASE_APP_ID=...
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=...
Enter fullscreen mode Exit fullscreen mode

Make sure to add the NEXT_PUBLIC prefix, as it will allow us to read these variables from the client

Also remember to add the file into your .gitignore file if you are using git. If you want, I recommend creating a .env.example file for keeping example data to describe what the actual .env.local file has.

I'll explain in a second where we can find all this information, but first, let's put this information to use in our project.

Inside any folder where you want to keep your utility code, create a firebase file to put all of our firebase SDK related code

Personally, I like to create a src/common/services/firebase folder, inside of which I make a single file for each of the SDKs we are gonna use (for now only the main firebase SDK, but we will add more) and then a single index.ts file that imports all of them and exports them, so we can import directly from the folder.

Inside this file, we are gonna initialize the firebase app SDK, which will be required by all other firebase SDKs.

import { initializeApp } from 'firebase/app';

const firebaseConfig = {
};

const app = initializeApp(firebaseConfig);
export default app;
Enter fullscreen mode Exit fullscreen mode

Now, the firebaseConfig object is the one that will take all of our variables, so let's go ahead and fill our object:

const firebaseConfig = {
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
  measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};
Enter fullscreen mode Exit fullscreen mode

Great! Now, let's go over to the firebase console to get our data for our .env file.

First, go over to the firebase console menu and click on "Project overview"

Image description

Here we can see information about our project, including all of the apps that use our firebase project.

We are gonna add a new web app, So click on the web simbol, from there, give your app a name.

You should now be able to see the data that we need to add to our .env file

Image description

Go ahead and copy that information over to your .env file, that should be enought to initialize firebase.

Conclusion

And we are done! I know that was a lot of setup to end up barely writing any code, but the good news is that we are done setting up and we can now focus on writing code.

Next part in the series will focus on using all of the auth setup we did to create a simple sign in page and display the username of whoever is signed in.

Top comments (0)