Building a Instagram clone in React with GraphQL and Hasura - Part I
Tags: tutorial, react, instagram, graphql
Published: 2019-12-16 13:13:34

---
title: Building a Instagram clone in React with GraphQL and Hasura - Part I
published: true
date: 2019-09-06 09:54:46 UTC
tags: tutorial, react, instagram, graphql
canonical_url: https://blog.hasura.io/instagram-clone-react-graphql-hasura-part1/
---

![](https://blog.hasura.io/content/images/2019/09/Instagram-clone.png)

_This tutorial was written by [Abhijeet Singh](https://github.com/abhi40308) and published as part of  the [Hasura Technical Writer Program](https://blog.hasura.io/the-hasura-technical-writer-program/) - an initiative that supports authors who write guides and tutorials for the open source Hasura GraphQL Engine._

# Introduction

In this tutorial I will show you how to use **Hasura GraphQL Engine** and **React** to build a clone of the Instagram web app. The final code is hosted [here](https://github.com/abhi40308/instagram-clone). See live demo of the app [here](https://instagram-1919.herokuapp.com/).

The app will have the following features:

- Users can create account (using Auth0 authentication)
- Authenticated users can upload new posts
- Authenticated users can like posts
- Authenticated users can follow user accounts
- Display posts in feed
- Realtime  updates when other users upvote a post, create a new post or follow  user profile (using react state management and updating apollo cache)

## Initial Setup

Let's start by building the frontend of our app using React.

To get started quickly, we will create a basic react app with no build configuration using [**create-react-app**](https://github.com/facebook/create-react-app). Run the following commands in terminal:

```
$ npx create-react-app instagram-clone
$ cd instagram-clone
$ npm start
```

> **Note : npx** is a **npm** package runner. The typical use is to download and run a package temporarily **or** for trials. create-react-app is an **npm** package that is expected to be run only once in a project’s lifecycle. Hence, it is preferred to use **npx** to install and run it in a single step. ([source](https://stackoverflow.com/questions/50605219/difference-between-npx-and-npm))

Server will start and you should be able to see a welcome to react screen (_like below_) on [http://localhost:3000](http://localhost:3000/).

![](https://blog.hasura.io/content/images/2019/09/image.png)

To improve the project structure, let’s create two directories, both inside the src folder. The first is called `components` and will hold all our React components. Second one `styles`, that is for all the CSS files you’ll use.

Move the required `jsx` and `css` files to appropriate directories and change the references to these files in both `index.js` and `App.js` accordingly. Your directory structure should look like this:

```
├── node_modules
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
├── src
│ ├── App.test.js
│ ├── components
│ │ └── App.js
│ ├── index.js
│ ├── logo.svg
│ ├── serviceWorker.js
│ └── styles
│ ├── App.css
│ └── index.css
└── README.md
```

I’ll be using [**react-bootstrap**](https://react-bootstrap.github.io/getting-started/introduction/) package for the styling. Install the package using:

```
$ npm install react-bootstrap bootstrap
```

Make sure to add the CDN links to stylesheets in `/public/index.html`. Copy the links from [**here**](https://react-bootstrap.github.io/getting-started/introduction/).

Also install [**react-apollo**](https://github.com/apollographql/react-apollo) GraphQL Client using the following command:

```
$ npm install apollo-boost apollo-link-context @apollo/react-hooks @apollo/react-hoc graphql
```

**Apollo Client** helps you consume a **GraphQL API** from the front-end.

Next we will setup the backend using the **Hasura GraphQL Engine** and **Postgres**.

See [this](https://docs.hasura.io/1.0/graphql/manual/getting-started/heroku-simple.html) guide to quickly get started with Hasura GraphQL engine and Postgres running on Heroku with one click deployment.

# Setting up the backend

Our Postgres Database structure :

```
type Post {
    id - integer, primary key
    caption - text
    url - text
    created_at - timestamp with time zone
    user_id - text
}
 
type User {
    name - text
    last_seen - timestamp with time zone
    avatar - text
    email - text
    id - text, primary key
}

type Like {
    id - integer, primary key
    user_id - text
    post_id - integer
}

type Follow {
    id - integer, primary key
     follower_id - text
    following_id - text
}
```

![](https://blog.hasura.io/content/images/2019/09/image-1.png)<figcaption>Database Structure</figcaption>

### Creating tables

Create the following tables : `User` table

![](https://blog.hasura.io/content/images/2019/08/user-table_1.png)<figcaption>user table</figcaption>

`Post` table (`id` has type `integer(autoincrement)`):

![](https://blog.hasura.io/content/images/2019/08/post-table_1.png)<figcaption>post table</figcaption>

Add the foreign key constraint from `user_id` column to `User.id` . Set `Update` and `Delete` Violation as `restrict`.

`Like` table (`id` has type `integer(autoincrement)`):

![](https://blog.hasura.io/content/images/2019/08/like-table_1.png)<figcaption>like table</figcaption>

`Follow` table (`id` has type `integer(autoincrement)`):

![](https://blog.hasura.io/content/images/2019/08/follow-table_1.png)<figcaption>follow table</figcaption>

Create an `object` relationship by  jumping to relationship section of tables. These relationships will help us to query data in a single query and also perform various kinds of  aggregate functions like getting number of posts for every user. See [this](https://docs.hasura.io/1.0/graphql/manual/schema/relationships/create.html#step-1-add-foreign-key-constraint) link for creating relationships through foreign key in hasura. We just need the following relationships.

![](https://blog.hasura.io/content/images/2019/08/user-table_2.png)<figcaption>user table</figcaption>

![](https://blog.hasura.io/content/images/2019/08/post-table_2.png)<figcaption>post table</figcaption>

Now we will set up the permissions for the tables, so that only logged  in users can do certain things. Set up the permissions as shown below:

![](https://blog.hasura.io/content/images/2019/08/user-table_2-1.png)<figcaption>user table</figcaption>

![](https://blog.hasura.io/content/images/2019/08/post-table_3.png)<figcaption>post table</figcaption>

![](https://blog.hasura.io/content/images/2019/08/like-table_3.png)<figcaption>Like table</figcaption>

![](https://blog.hasura.io/content/images/2019/08/follow_table2.png)<figcaption>Follow table</figcaption>

See [access control basics](https://docs.hasura.io/1.0/graphql/manual/auth/authorization/basics.html) if you are not much familiar with access control and how it works in hasura.

![](https://blog.hasura.io/content/images/2019/08/permissions-1.png)

To make it less complicated, I have given all the row level permissions as without any checks and column level as all columns and aggregation queries (used to count number of points for a post).

# Using Auth0 JWT for Authentication

The following figure quickly explains how `JWT` authentication works. Here, Application Server (our backend) needs to be configured to verify that the incoming `JWT` are created by the authentication server (Auth0).([_source_](https://medium.com/vandium-software/5-easy-steps-to-understanding-json-web-tokens-jwt-1164c0adfcec))

![](https://blog.hasura.io/content/images/2019/09/image-2.png)

We are using Auth0 as authentication server. It will create a `JWT` and pass to our react app. Then, using apollo client, we will send the `auth_token`(`access_token` in our case) to our backend (application server), i.e. Hasura GraphQL  Engine. Hasura is needed to be configured to verify that incoming JWT is created by Auth0 authentication server.

Let's get started with Auth0, using `@apollo/react-hooks` and `@auth0/auth0-spa-js`. We have to follow these steps:

**Auth0 JWT integration with Hasura** : See [this](https://docs.hasura.io/1.0/graphql/manual/guides/integrations/auth0-jwt.html) guide for Auth0 JWT Integration with Hasura and get the JWK (key for validation of incoming JWT). In Auth0 dashboard, set `Allowed Callback URLs`, `Allowed Web Origins`, `Allowed Logout URLs` to [http://localhost:3000](http://localhost:3000/) and save changes.

You may also need to disable OIDC Conformant in `Auth0 > Applications > Your_app > Settings > Advanced Settings`.  Once you have the key, next step is to activate the JWT mode in Hasura.  Go to your heroku dashboard, choose our app and go to settings. Here  you can see some `Config Vars`which we will set-up now. Add the config vars as following:

![](https://blog.hasura.io/content/images/2019/09/image-3.png)

Here, `HASURA_GRAPHQL_ADMIN_SECRET` key for the JWT mode to work. Put the key in `HASURA_GRAPHQL_JWT_SECRET`environment variable. Once you have added this, the GraphQL endpoints can only be queried using `Authorization` header or `X-Hasura-Admin-Secret` header.

Finally, set `HASURA_GRAPHQL_UNAUTHORIZED_ROLE` to `anonymous` because we do allow unauthenticated users to read some data.

> **_Unauthorized role:_** _used when access-key is not sent in access-key only mode or “Authorization” header is absent in JWT mode. Example:_ `anonymous`_. Now whenever “Authorization” header is absent, request’s role will default to “anonymous”._

Next step is to add rules in our Auth0 app. We will add 2 more rules to Auth0 app as shown below:

{% gist https://gist.github.com/abhi40308/f47c7fd4977f41041e788c203e42bbb6.js %}

Here we are replacing `idToken` with `accessToken` . Basically, auth0 provides different types of tokens and the `auth0-spa-js` does not expose the `idToken` anymore, so we will use `accessToken`.

**Update:** From version 1.2.0 of auth0-spa-js, the raw value of idToken is exposed using getIdTokenClaims method.

> Read more about tokens [here](https://auth0.com/docs/tokens).

> The new SPA SDK only uses Authorization Code Grant + PKCE (not Implicit Grant anymore) Thus we have to use `accessTokens` in place of `idTokens`. (See [this](https://community.auth0.com/t/how-to-obtain-id-token-with-auth0-spa-js/27574/3) thread).

Add one more rule for keeping our postgres database and Auth0 users in sync:

{% gist https://gist.github.com/abhi40308/ff130e625648067d76875efaad3b258a.js %}

Change `admin_secret` and `url` accordingly. Now, whenever a new user signs up or a user logs in, our  hasura postgres database will be updated automatically to store the user  information in our `users` table. See [this](https://learn.hasura.io/graphql/hasura/authentication/4-user-sync-rule) for more details.

_Note: Here we are just doing a post request with graphql mutations, and we have_ `x-hasura-admin-secret` _in header, thus the incoming request have full access to mutate the database._

We also need to create a custom API in `Auth0 Dashboard > APIs` which will point to our Hasura GraphQl API. Create a new api as shown below and give it any name. Change `Identifier` with your graphql endpoint.

![](https://blog.hasura.io/content/images/2019/09/image-4.png)

Now that we have got our backend and Auth0 setup, we can get started on building out the React app. Head over to the **[2nd part](https://blog.hasura.io/instagram-clone-react-graphql-hasura-part2/)** of this series to learn how.

## About the author 

[Abhijeet Singh](https://github.com/abhi40308) is final year UG student in Computer  Science and Engineering from IIIT Kalyani. He has done work in Full  Stack Development, Android, Deep Learning, Machine Learning and NLP. He  actively takes part in competitive programming contests and has interest  in solving algorithmic problems. He is a startup enthusiast and plays  table tennis and guitar in spare time.