How to Integrate MongoDB Realm with React: Part 1
Tags: webdev, javascript, react, mongodb
Published: 2021-05-23 13:48:04

_This article was originally posted on [my personal blog](https://blog.shahednasser.com/how-to-integrate-mongo-realm-with-react-part-1/)_

_Please participate in [this survey](https://yiro6gzu369.typeform.com/to/M2TFz504) to voice your opinion as a developer for an upcoming article!_

MongoDB Realm is a serverless backend that allows you to not only write and read data easily but also provides easy ways to authenticate users, keep your data synchronized across multiple devices, and more.

In this tutorial, we'll learn how to create a MongoDB Realm application, add sample data to it, restrict data access based on user roles, then how to integrate the application with React. We'll create a website that shows restaurant reviews and allows users to create an account and add their own reviews.

You can find the code for this tutorial [here](https://github.com/shahednasser/mongodb-realm-tutorial).

---

### Create a MongoDB Realm App

**Create a MongoDB Cluster**

Before we can create a MongoDB Realm App, we need to create a MongoDB Cluster. To do that, go to the [Atlas portal](https://cloud.mongodb.com/). If you don't have an account or you're not already logged in, you need to do that first.

If you're not redirected to the Projects page, click on the logo at the top left.

![](https://res-2.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Projects-Cloud-MongoDB-Cloud.png)

Once you're on the Projects page, click on the New Project button at the right.

![](https://res-5.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Projects-Cloud-MongoDB-Cloud2.png)

Then you will be asked to enter a project name. You can name it whatever you want. After that, you'll be asked to add members, if you need to. Once done, click on Create Project.

Once the project is created, you will be redirected to the Clusters page. Click on "Build a Cluster"

![](https://res-1.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Clusters-Atlas-MongoDB-Atlas.png)

You'll be asked to pick a cluster plan. For this tutorial, you can just choose the free plan.

![](https://res-3.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Choose-a-Path-Atlas-MongoDB-Atlas.png)

Then after that you can just click on "Create Cluster"

![](https://res-4.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Create-Cluster-Atlas-MongoDB-Atlas.png)

After this, your cluster will take some time to deploy. You need to wait until it's created and deploy, which can take a couple of minutes.

The next step will be to add a sample dataset to our Cluster. If you already have a dataset, you can add your own data instead.

To start adding data, click on Collections in the Cluster you created.

![](https://res-5.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Clusters-Atlas-MongoDB-Atlas2.png)

Then, click on Load a Sample Dataset.

![](https://res-4.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Data-Atlas-MongoDB-Atlas.png)

A popup window will open to ask for confirmation. Once you confirm, a sample dataset will be installed in your cluster. This dataset contains a bunch of useful databases and collections for different use cases.

It will take a minute or two to finish installing the sample dataset. Once it's done, you'll see that now you have a few databases now.

![](https://res-2.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Data-Atlas-MongoDB-Atlas2.png)

We'll only be using the `sample_restaurants` database, so you can go ahead and delete the rest by clicking on the trash icon that appears when you hover a database name.

Now that our MongoDB Cluster is ready, let's go ahead and create a MongoDB Realm App.

**Create a MongoDB Realm App**

To go to MongoDB Realm, click on "Realm" in the tab bar next to "Atlas"

![](https://res-2.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Clusters-Atlas-MongoDB-Atlas3.png)

A dialog will show to start creating MongoDB Realm App. You'll need to enter a name for the Realm Application which can be whatever you want. Then, you'll need to choose a cluster to link the Realm App to. You'll need to choose the cluster we just created. Once you do that, click on Create Realm Application.

Next, we'll need to choose a collection from the cluster to add access to from the Realm app. To do that, click on Get Started under Add a Collection on the dashboard.

![](https://res-4.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Dashboard-MongoDB-Realm.png)

You'll have to pick the database, which is `sample_restaurants`. Then choose a collection, which will be `restaurants`.

Next, we need to select a permission template. Permission templates allow to easily restrict read and write access as necessary.

In the website we're creating, all users can read all data about restaurants, and they can write reviews in their own account.

For now, we'll just choose "Users can only read all data" from the dropdown. Once you're done, click "Add Collection." Next, click on `neighborhoods` from the sidebar and choose the same template then Add Collection.

Every time you make changes to the Realm App, you have to deploy it for changes to take effect. To deploy the changes we just made, click on "Review Draft &amp; Deploy" in the blue banner at the top.

![](https://res-1.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Data-Sources-MongoDB-Realm.png)

And that's it! We created a Realm App that's linked to our cluster and the collections in it. This will provide a serverless backend that allows us to retrieve and write data to our cluster easily.

---

## Generate Schemas

To be able to query our collections and documents, and to be able to apply certain roles, permissions and restrictions, we need to generate Schema definitions for each of the collections. To do that, click on Schema in the sidebar.

Then, click on Generate Schema button. This will generate the schema based on the data that's already in the collection.

Under "Generate schema(s) for:" choose "all unconfigured collections" and for Sample type in "20" as we don't need to sample so many documents considering our data is simple. Then, click on Generate Schema.

Once it's done, you'll see the Schema generated with all the fields and their respective types.

![](https://res-3.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Data-Sources-MongoDB-Realm3.png)

---

## Setup Authentication in Realm App

In our Realm app, we'll be using two Authentication providers:

1. Anonymous Login: Allow the user to view all data without actually having to login.
2. Email &amp; Password Login: Users have to login with email and password to write their reviews.

This means that users have permission to read all data, but only write their own data.

In the Realm Portal, click on Authentication in the sidebar. You'll see a few Authentication providers that are all disabled.

We'll first enable "Allow users to login anonymously." Click on the edit button for this one and just toggle it on.

Then go back to the Authentication page. We'll now click on Edit for the second one which is "Email/Password."

First, enable the provider. Next, for "User Confirmation Method," choose "Automatically confirm users." MongoDB Realm provides a user confirmation workflow for your app, but in our case we don't need it.

Next comes "Password Reset Method." MongoDB Realm also provides a password reset method for your users. We won't be implementing it, but because we need to enter the configuration, just enter `http://example.com/reset` in "Password Reset URL."

Once you're done, click Save. Our users are now able to login with an email and password.

The last step for setting up authentications is to allow users who are logged in with email and password to write their own reviews. To do that, go to rules in the sidebar, then choose the`restaurants`collection, then click on "New Role" in the table.

![](https://res-2.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Data-Sources-MongoDB-Realm2.png)

A popup will open. You first need to enter the role name. We'll name it "Users"

Next, we'll need to enter "Apply When" condition, which means when should the user be considered as part of this role. We want users who are logged in with their email and password to be able to write their reviews. Enter the following:

```json
{
  "%%user.data.email": {
    "%exists": true
  }
}
```

Then, for the "Document-Level Permissions" choose "Insert Documents." Once you're done, click "Done Editing."

Then, in the table click "Add Field" and type in "grades" and click the checkmark. Then check for both Read and Write for the User role. This adds the double restriction which is users are only able to write in grades, nothing else. As for Read, you can check for all fields. Then, click on the left Arrow under the "User" role name to give the User role a higher priority when matching the logged in user with the correct role. Once you're done, click on Save. The table should look like this:

![](https://res-3.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Data-Sources-MongoDB-Realm6.png)

And with this done, we can now anonymous and logged in users can read all data, but only users logged in can write their own reviews.

One last thing to do is make sure to click on Review Draft &amp; Deploy for all the changes to take effect.

Now, we have our MongoDB Realm app ready for integration with React. Next, we'll go over how to integrate it with React and use all the functionalities we've been setting up.

---

## React Setup

In case you don't have a React project ready, run the following to create one:

```bash
npm create-react-app restaurants-reviews
cd restaurants-reviews
```

Next, we'll install the MongoDB Realm Web SDK:

```bash
npm install --save realm-web
```

That's all we need to start using Realm with React. We'll also install [React Bootstrap](https://react-bootstrap.github.io/)to make styling easier:

```bash
npm install react-bootstrap bootstrap@4.6.0
```

and [React Router](https://reactrouter.com/web/guides/quick-start)to add different pages:

```bash
npm install react-router-dom
```

**Home Page**

Let's first start by modifying creating the`Home`component which will be the home page. The home page will just show a list of restaurants and their ratings.

Create the file `src/pages/Home.js` and the following basic component:

```js
function Home () {
    return (
    	<div></div>
    )
}

export default Home
```

For now, it's just a component that shows a`<div>`element. We need to make it show a list of restaurants instead.

Since we're going to fetch the restaurants from our MongoDB Realm App later on, we'll be using a state for restaurants:

```js

function Home () {
	const [restaurants, setRestaurants] = useState([])
    //...
}

```

Then, we'll loop over the restaurants and display them:

```js

<div className="mt-3">
    {restaurants.map((restaurant) => (
        <RestaurantCard key={restaurant._id} restaurant={restaurant} />
        ))
	}
</div>

```

Let's create `src/components/RestaurantCard.js` with the following content:

```js

import { Badge } from 'react-bootstrap'
import Card from 'react-bootstrap/Card'

function RestaurantCard ({restaurant}) {
    //get average of grades
    let sum = 0;
    restaurant.grades.forEach(element => {
        sum += element.score
    });
    const avg = Math.round(sum / (restaurant.grades.length))
    return (
        <Card className="m-3">
            <Card.Body>
                <Card.Title>{restaurant.name} <Badge variant="warning">{avg}</Badge></Card.Title>
            </Card.Body>
        </Card>
    )
}

export default RestaurantCard

```

We're first calculating the average grade for the restaurant, then we're just displaying a card with the restaurant's name and the average grade.

So, our home page should show a list of cards with restaurant names and grades. What's left is to actually link it to the data in our Realm app.

Let's go over how to connect to Realm Apps first. You first need an App ID. You'll find the App ID on the Dashboard or you can click the copy icon in the sidebar.

![](https://res-4.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/Data-Sources-MongoDB-Realm5.png)

Then, create a`.env`file in the root directory with the following content:

```js

REACT_APP_REALM_APP_ID=<YOUR_APP_ID>

```

Make sure to replace`<YOUR_APP_ID>`with the App ID you copied. This helps changing App IDs easy just by changing it in `.env`.

Back to `src/pages/Home.js`, we first need to import the SDK:

```js

import * as Realm from 'realm-web'

```

Then, initialize the Realm App:

```js

const app = new Realm.App({id: process.env.REACT_APP_REALM_APP_ID})

```

Notice we're using the environment variable we set earlier.

Then inside the`Home`component, we'll use`useEffect`to fetch the data on first render:

```js

useEffect(() => {

}, [])

```

Inside, we'll log in the user anonymously and then fetch the`restaurants`data. Since earlier we allowed all users to read all data, even users who aren't logged in can read the data.

To login a user anonymously:

```js

useEffect(() => {
	async function getData () {
    	const user = await app.logIn(Realm.Credentials.anonymous())
    }
    
    getData();
}, [])

```

After that, we'll get the MongoDB client for our collection using the user we just logged in:

```js

const client = app.currentUser.mongoClient('mongodb-atlas')

```

As you can tell, by using`app.currentUser`we're referring to the currently logged-in user. Then, we get the MongoDB client for that user. This means that the access to the data is restricted based on the user that is logged in, just like we defined above.

Next step would be to get the restaurants from`restaurants`collection and set the restaurants state:

```js

const rests = client.db('sample_restaurants').collection('restaurants')
setRestaurants((await rests.find()).slice(0, 10))

```

And with this, our code will display the restaurants once we retrieve them from MongoDB Realm App. We'll add also some loading to make sure we can see the loading:

```js

const [restaurants, setRestaurants] = useState([])
const [loading, setLoading] = useState(true)

useEffect(() => {
	async function getData () {
    	//...
        const rests = client.db('sample_restaurants').collection('restaurants')
        setRestaurants((await rests.find()).slice(0, 10))
        setLoading(false)
    }
    
    if (loading) {
        getData();
    }
}, [loading])

return (
    <div className="mt-3">
            {loading && (
                <div className="text-center">
                    <Loading />
                </div>
            )}
            {restaurants.map((restaurant) => (
                <RestaurantCard key={restaurant._id} restaurant={restaurant} />
            ))}
        </div>
);

```

We'll also create `src/components/Loading.js`:

```js

import { Spinner } from "react-bootstrap";

function Loading () {
    return (
        <Spinner animation="border" variant="primary">
            <span className="sr-only">Loading...</span>
        </Spinner>
    )
}

export default Loading

```

And that's it! The home page now is ready. Only thing left is to use `react-router` in `src/App.js` to ensure multiple pages:

```js

import {
  BrowserRouter as Router,
  Switch,
  Route,
} from "react-router-dom"
import Home from "./pages/Home"
import 'bootstrap/dist/css/bootstrap.min.css'
import { Container } from "react-bootstrap"

function App() {

  return (
    <Router>
        <Container>
          <Switch>
            <Route path="/" component={Home} />
          </Switch>
        </Container>
    </Router>
  );
}

export default App;

```

Let's now run the server:

```bash
npm start
```

After some loading, you'll see the restaurants with their average grades:

![](https://res-4.cloudinary.com/hbqmf3mbz/image/upload/q_auto/v1/ghost-blog-images/React-App.png)

Next, we'll create authentication forms to allow users to create accounts and login.

**Authentication Page**

Since the user just needs to enter the email and password to Sign up and Log in, we'll just create one Authentication component that changes behavior based on`type`prop that determines whether the form is being used to create an account or login.

Before we start, let's install [Formik](https://formik.org/) and [Yup](https://github.com/jquense/yup)to make creating a form easier:

```bash
npm i formik yup
```

Then, create `src/pages/Authentication.js` with the following content:

```js

import { Formik } from 'formik'
import { Button, Form } from 'react-bootstrap'
import * as yup from 'yup'
import { useState } from 'react'
import Loading from '../components/Loading'

const userSchema = yup.object().shape({
    email: yup.string().email().required(),
    password: yup.string().required().min(8)
})

function Authentication ({type = 'login'}) {
    const [loading, setLoading] = useState(false)

    async function submitHandler (values) {
        setLoading(true)
        //TODO handle login/create
    }

    return (
        <Formik 
            initialValues={{
                email: '',
                password: ''
            }}

            validationSchema={userSchema}

            onSubmit={submitHandler}
        >
            {({errors, touched, handleSubmit, values, handleChange}) => (
                <Form noValidate onSubmit={handleSubmit}>
                    {loading && <Loading />}
                    {!loading && (<div>
                        <h1>{type === 'login' ? 'Login' : 'Sign Up'}</h1>
                        <Form.Row>
                            <Form.Label>Email</Form.Label>
                            <Form.Control type="email" name="email" value={values.email} onChange={handleChange} 
                            isValid={touched.email && !errors.email} />
                            <Form.Control.Feedback>{errors.email}</Form.Control.Feedback>
                        </Form.Row>
                        <Form.Row>
                            <Form.Label>Password</Form.Label>
                            <Form.Control type="password" name="password" value={values.password} onChange={handleChange} 
                            isValid={touched.password && !errors.password} />
                            <Form.Control.Feedback>{errors.password}</Form.Control.Feedback>
                        </Form.Row>
                        <div className="text-center mt-2">
                            <Button variant="primary" type="submit">Submit</Button>
                        </div>
                    </div>)}
                </Form>
            )}
        </Formik>
    )
}

export default Authentication

```

We're using Formik to create a form that has two fields, email, and password. We're also using `yup` it to create a validation schema. On form submit if everything is valid, the function `submitHandler` will run which accepted the `values` object.

Inside `submitHandler`, we need to check the `type` prop. If it equals `create`, then we need to create a new user and login the user after that. If it's `login` then we just need to login the user.

But before we start, as it will be a hassle to use the `user` object, the MongoDB `client`, and the Realm `app`, let's create a [Context](https://reactjs.org/docs/context.html) that allows us to use the same data throughout the components easily.

Create `src/MongoContext.js` with the following content:

```js

import React from 'react'

const MongoContext = React.createContext({
    app: null,
    client: null,
    user: null,
    setApp: () => {},
    setClient: () => {},
    setUser: () => {}
})

export default MongoContext

```

We're creating a Context that has the objects `app`, `client`, and `user`and their setter functions `setApp`, `setClient` and `setUser`.

Next, let's move declarations and intialization of `user`, `app` and `client` that we did in `Home` to `App`:

```js

const [client, setClient] = useState(null)
  const [user, setUser] = useState(null)
  const [app, setApp] = useState(new Realm.App({id: process.env.REACT_APP_REALM_APP_ID}))

  useEffect(() => {
    async function init () {
      if (!user) {
        setUser(app.currentUser ? app.currentUser : await app.logIn(Realm.Credentials.anonymous()))
      }

      if (!client) {
        setClient(app.currentUser.mongoClient('mongodb-atlas'))
      }
    }

    init();
  }, [app, client, user])

```

As you can see, we're creating states for each of them and setting them in `App`. Then, we'll wrap our routes with `MongoContext.Provider`:

```js

return (
    <Router>
      <MongoContext.Provider value={{app, client, user, setClient, setUser, setApp}}>
      	<Container>
          <Switch>
            <Route path="/" component={Home} />
          </Switch>
        </Container>
      </MongoContext.Provider>
     </Router>
  );

```

Now, we need to pass the context to each of the components using `MongoContext.Consumer`. To avoid repetition, let's create a function inside `App` that does this:

```js

function renderComponent (Component, additionalProps = {}) {
    return <MongoContext.Consumer>{(mongoContext) => <Component mongoContext={mongoContext} {...additionalProps} />}</MongoContext.Consumer>
  }

```

This will wrap a component with `MongoContext.Consumer` then pass it the `mongoContext` prop, which will hold all the objects we're storing in the context and their setters.

Back to the return statement in `App`, instead of passing `component={Home}` to the route, we'll pass a render function:

```js

<Route path="/" render={() => renderComponent(Home)} />

```

Now, we have a context that holds all the objects and their setters, then we're passing it to a route's component.

Let's make changes in `src/pages/Home.js` where instead of initializing `app`, `user`, and `client`, it'll receive them as props:

```js

import { useEffect, useState } from 'react'
import RestaurantCard from '../components/RestaurantCard'
import Loading from '../components/Loading'

function Home ({mongoContext: {client, user}}) {
    const [restaurants, setRestaurants] = useState([])
    const [loading, setLoading] = useState(true)

    useEffect(() => {
        async function getData () {
            const rests = client.db('sample_restaurants').collection('restaurants')
            setRestaurants((await rests.find()).slice(0, 10))
            setLoading(false)
        }

        if (loading && user && client) {
            getData()
        }
    }, [client, loading, user])

    return (
        <div className="mt-3">
            {loading && (
                <div className="text-center">
                    <Loading />
                </div>
            )}
            {restaurants.map((restaurant) => (
                <RestaurantCard key={restaurant._id} restaurant={restaurant} />
            ))}
        </div>
    )
}

export default Home

```

If you try running the server and going to the website, you'll see that everything is working perfectly as before.

Back to the `Authentication` component, we'll now pass it the `mongoContext` prop:

```js

function Authentication ({mongoContext: {app, user, setUser}, type = 'login'})

```

Inside `submitHandler`, if the `type` is create we'll register a new user, then for both types we'll login the user with their credentials:

```js

async function submitHandler (values) {
        setLoading(true)
        if (type === 'create') {
            //create
            await app.emailPasswordAuth.registerUser(values.email, values.password);
        }

        //login user and redirect to home
        const credentials = Realm.Credentials.emailPassword(values.email, values.password);
        setUser(await app.logIn(credentials))
        setLoading(false)
    }

```

As you can see, we're using`app`and`setUser`from the context. When we use`setUser`, the user will be updated for all components using the context.

Last thing we need to add is to redirect the user if they're already logged in. To do that, first create`src/utils.js`which will hold the function`isAnon`to determine whether the user is logged in:

```js

module.exports = {
    isAnon: function (user) {
        return !user || user.identities[0].providerType === 'anon-user'
    }
}

```

Where `providerType` will be `anon-user` if the user is not logged in.

Then, inside `Authentication`, we'll get a `history` instance using `useHistory` from `react-router`:

```js

const history = useHistory()

```

Then, whenever the`user`in the context changes, we'll check if the user is logged in and then we'll redirect to home if true.

```js

useEffect(() => {	
	if (!isAnon(user)) {
		history.push('/')
	}
}, [history, user])

```

Our `Authentication` component is now done! Let's add `signin` and `signup` routes in `src/App.js`:

```js

<Route path="/signup" render={() => renderComponent(Authentication, {type: 'create'})} />
<Route path="/signin" render={() => renderComponent(Authentication)} />
<Route path="/" render={() => renderComponent(Home)} />

```

We'll also need a `LogOut` page so create `src/pages/Logout.js` with the following content:

```js

import { useEffect } from "react"
import Loading from "../components/Loading"
import * as Realm from 'realm-web'
import { useHistory } from "react-router"
import { isAnon } from "../utils"

function LogOut ({mongoContext: {app, setUser, setClient}}) {
    const history = useHistory()

    if (isAnon()) {
        history.push('/')
    }

    useEffect(() => {
        async function logout () {
            await app.currentUser.logOut()
            //login anon user
            setUser(await app.logIn(Realm.Credentials.anonymous()))
            //set new client
            setClient(app.currentUser.mongoClient('mongodb-atlas'))
        }

        logout()
    }, [app, setClient, setUser])

    return (
        <Loading />
    )
}

export default LogOut

```

We're first checking if the user is already not logged in and we're redirecting them to homepage if that's the case. Then, we're displaying the loading component and inside `useEffect` we're logging the user out using:

```js

await app.currentUser.logOut()

```

After that, we're setting the user as anonymous user again and reinitializing the MongoDB Client:

```js
//login anon user
setUser(await app.logIn(Realm.Credentials.anonymous()))
//set new client
setClient(app.currentUser.mongoClient('mongodb-atlas'))
```

And with that, we have our log out page. We just need to add it to the routes in `src/App.js`:

```js

<Route path="/signup" render={() => renderComponent(Authentication, {type: 'create'})} />
<Route path="/signin" render={() => renderComponent(Authentication)} />
<Route path="/logout" render={() => renderComponent(LogOut)} />
<Route path="/" render={() => renderComponent(Home)} />

```

Lastly, we'll create a `src/components/Navigation.js` component to show a navigation bar with our links:

```js

import { Nav, Navbar } from "react-bootstrap"
import { Link } from "react-router-dom"
import { isAnon } from "../utils"


function Navigation ({user}) {
    const loggedIn = !isAnon(user)
    return (
        <Navbar bg="light" expand="lg">
            <Navbar.Brand href="#home">Restaurant Reviews</Navbar.Brand>
            <Navbar.Toggle aria-controls="basic-navbar-nav" />
            <Navbar.Collapse id="basic-navbar-nav">
                <Nav className="mr-auto">
                    <Link to="/" className="mx-2">Home</Link>
                    {!loggedIn && <Link to="/signup" className="mx-2">Sign Up</Link>}
                    {!loggedIn && <Link to="/signin" className="mx-2">Sign In</Link>}
                    {loggedIn && <Link to="/logout" className="mx-2">Log out</Link>}
                </Nav>
            </Navbar.Collapse>
        </Navbar>
    )
}

export default Navigation

```

We're passing it the user prop, then we're checking if the user is logged in, we'll show the log out link. If not, we'll show the sign in and sign up links.

Add the `Navigation` component in `src/App.js`:

```js

return (
    <Router>
      <Navigation user={user} />
      <MongoContext.Provider value={{app, client, user, setClient, setUser, setApp}}>
      //...
)

```

We're done! Run the server if you aren't already:

```bash
npm start
```

You'll see we have a navigation bar that shows the sign in and sign up links when we're not logged in. Try to sign up, log out, sign it, do different things. To check if the users are actually being created, on the Realm platform, click on "App Users" in the sidebar. You'll see a list of users with the type of user either Anonymous or Email/Password.

---

### Conclusion

In the next part, we'll add a form for users to create their own reviews. We'll be able to test the permissions we added earlier and see how the users are restricted based on the roles we create.

_If you would like to connect and talk more about this article or programming in general, you can find me on my twitter account [@shahednasserr](https://twitter.com/shahednasserr)_