Nhost CLI: From Zero to Production
Tags: opensource, serverless, tutorial, webdev
Published: 2022-02-18 13:20:58

In the previous tutorials, that are covered in the [documentation](https://docs.nhost.io/get-started), we tested various parts of Nhost, such as:

- Database
- GraphQL API
- Permission
- JavaScript SDK
- Authentication

All changes we did to our database and API happened directly in the production of our Nhost app.

It’s not ideal for making changes in production because you might break things, which will affect all users of your app.

Instead, it’s recommended to make changes and test your app locally before deploying those changes to production.

To do changes locally, we need to have a complete Nhost app running locally, which the Nhost CLI does.

The Nhost CLI matches your production application in a local environment, this way you can make changes and test your code before deploying your changes to production.

## Recommended workflow with Nhost

1. Develop locally using the Nhost CLI.
2. Push changes to GitHub.
3. Nhost automatically applies changes to production.

## What you’ll learn in this guide:

- Use the Nhost CLI to create a local environment
- Connect a GitHub repository with a Nhost app
- Deploy local changes to production

## Setup the recommended workflow with Nhost

What follows is a detailed tutorial on how you setup Nhost for this workflow

### Create Nhost App

Create a **new Nhost app** for this tutorial.

> It’s important that you create a **new** Nhost app for this guide instead of reusing an old Nhost app because we want to start with a clean Nhost app.
> 

![Create new app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87lkr21amfmvha0i5cdf.png)

### Create new GitHub Repository

Create a new GitHub repository for your new Nhost app. The repo can be both private or public.

![Create new repo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/28cq9yw951696ky0xzvf.png)

## Connect GitHub Repository to Nhost App

In the Nhost Console, go to the dashboard of your Nhost app and click **Connect to GitHub**.


![Connect Github Repo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lf4sjy5ul7wixlcsyk98.gif)

## Install the Nhost CLI

Install the Nhost CLI using the following command:

```sql
sudo curl -L https://raw.githubusercontent.com/nhost/cli/main/get.sh | bash
```

Initialize a new Nhost App locally:

```sql
nhost init -n "nhost-example-app" && cd nhost-example-app

```

And initialize the GitHub repository in the same folder:

```bash
echo "# nhost-example-app" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/[github-username]/nhost-example-app.git
git push -u origin main
```

Now go back to the **Nhost Console** and click **Deployments**. You just made a new deployment to your Nhost app!

![Deployments tab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w5a1vq5vdcd52vugvq9f.png)

If you click on the deployment you can see that nothing was really deployed. That’s because we just made a change to the README file.

![Deployments details](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gx59pqyd1s56m49gn33e.png)

Let’s do some backend changes!

## Local changes

Start Nhost locally:

```sql
nhost dev
```

<aside>
💡 Make sure you have [Docker](https://www.docker.com/get-started) installed on your computer. It’s required for Nhost to work.

</aside>

The `nhost dev` command will automatically start a complete Nhost environment locally on your computer using:

- Postgres
- Hasura
- Authentication
- Storage
- Serverless Functions
- Mailhog

You use this local environment to do changes and testing before you deploy your changes to production.

Running `nhost dev` also starts the Hasura Console.

<aside>
💡 It’s important that you use the Hasura Console that is started automatically when you do changes. This way, changes are automatically tracked for you.
</aside>

![Hasura Console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sw5x251plh9ix55hgs8r.png)

In the Hasura Console, create a new table `customers` with two columns:

- id
- name


![Hasura Create Customers Table](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q665cqg7tzunugmmmbn6.gif)

When we created the `customers` table there was also a migration created automatically. The migration was created at under `nhost/migrations/default`.

```bash
$ ls -la nhost/migrations/default
total 0
drwxr-xr-x  3 eli  staff   96 Feb  7 16:19 .
drwxr-xr-x  3 eli  staff   96 Feb  7 16:19 ..
drwxr-xr-x  4 eli  staff  128 Feb  7 16:19 1644247179684_create_table_public_customers
```

This database migration has only been applied locally, meaning, you created the `customers` table locally but it does not (yet) exists in production.

To apply the local change to production we need to commit the changes and push it to GitHub. Nhost will then automatically pick up the change in the repository and apply the changes.

<aside>
💡 You can commit and push files in another terminal while still having `nhost dev` running.

</aside>

```sql
git add -A
git commit -m "Initialized Nhost and added a customers table"
git push
```

Head over to the **Deployments** tab in the **Nhost console** to see the deployment.

![Deployments tab after changes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0n6r3j2n34wt2jl874jo.png)

Once the deployment finishes the `customers` table is created in production.

![Customers table in Hasura Console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b7kre000hos2nyodpagk.png)

We’ve now completed the recommended workflow with Nhost:

1. Develop locally using the Nhost CLI.
2. Push changes to GitHub.
3. Nhost deploys changes to production.

## Apply metadata and Serverless Functions

In the previous section, we only created a new table; `customers`. Using the CLI you can also do changes to other parts of your backend.

There are three things the CLI and the GitHub integration track and applies to production:

1. Database migrations
2. Hasura Metadata
3. Serverless Functions

For this section, let’s do one change to the Hasura metadata and create one serverless function

### Hasura Metadata

We’ll add permissions to the `users` table, making sure users can only see their own data. For this, go to the `auth` schema and click on the `users` table. then click on **Permissions** and enter a new role **user** and create a new **select** permission for that role**.**

Create the permission **with custom check**:

```json
{
  "id": {
    "_eq" : "X-Hasura-User-Id"
  }
}
```

Select the following columns:

- id
- created_at
- display_name
- avatar_url
- email

Then click **Save permissions**.

![Hasura User Permissions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tyvp0jolwp6qsrnc33pe.gif)

Now, let’s do a `git status` again to confirm the permission changes we did were tracked locally in your git repository.

![Git status](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9j8tb7xj4m27va7p45he.png)

We can now commit this change:

```bash
git add -A
git commit -m "added permission for uses"
```

Now let’s create a serverless function before we push all changes to GitHub so Nhost can deploy our changes.

### Serverless Function

A serverless function is a piece of code written in JavaScript or TypeScript that takes an HTTP request and returns a response.

Here’s an example:

```bash
import { Request, Response } from 'express'

export default (req: Request, res: Response) => {
  res.status(200).send(`Hello ${req.query.name}!`)
}
```

Serverless functions are placed in the `functions/` folder of your repository. Every file will become its own endpoint.

Before we create our serverless function we’ll install `express`, which is a requirement for serverless functions to work.

```bash
npm install express
# or with yarn
yarn add express
```

We’ll use TypeScript so we’ll install two type definitions too:

```bash
npm install -d @types/node @types/express
# or with yarn
yarn add -D @types/node @types/express
```

Then we’ll create a file `functions/time.ts`

In the file `time.ts` we’ll add the following code to create our serverless function:

```bash
import { Request, Response } from 'express';

export default (req: Request, res: Response) => {
  return res
    .status(200)
    .send(`Hello ${req.query.name}! It's now: ${new Date().toUTCString()}`);
};
```

We can now test the function locally. Locally, the backend URL is `http://localhost:1337`. Functions are under `/v1/functions`. And every function’s path and filename becomes an API endpoint.

This means our function `functions/time.ts` is at `http://localhost:1337/v1/functions/time`.

Let’s use curl to test our new function:

```bash
curl http://localhost:1337/v1/functions/time
Hello undefined! It's now: Sun, 06 Feb 2022 17:44:45 GMT
```

And with a query parameter with our name:

```bash
curl http://localhost:1337/v1/functions/time\?name\=Johan
Hello Johan! It's now: Sun, 06 Feb 2022 17:44:48 GMT
```

Again, let’s use `git status` to see the changes we did to create our serverless function.

Now let’s commit the changes and push them to GitHub.

```bash
git add -A
git commit -m "added serverless function"
git push
```

In the Nhost Console, click on the new deployment to see details

![Deployments details for function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/85lhjx2ldu760rchv66w.png)

After Nhost has finished deploying your changes we can test them in production. First let’s confirm that the user permissions are applied.

![Hasura Console permissions table](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0u08ql6hu7tzvrkai1j8.png)

Then, let’s confirm that the serverless function was deployed. Again, we’ll use curl:

```bash
curl https://your-backend-url.nhost.run/v1/functions/time\?name\=Johan
```

![Serverless Function test](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5t6i3f4s8o92bowcqbir.png)

## Conclusion

In this tutorial, we have installed the Nhost CLI and created a local Nhost environment to do local development and testing.

In the local environment, we’ve made changes to our database, to Hasura’s metadata, and created a serverless function.

We’ve connected a GitHub repository and pushed our changes to GitHub.

We’ve seen Nhost automatically deploying our changes and we’ve verified that the changes were applied.

In summary, we’ve set up a productive environment using the recommended Nhost workflow:

1. Develop locally using the Nhost CLI.
2. Push changes to GitHub.
3. Nhost deploys changes to production.

In addition to all that, the Nhost team is always happy to support you with any questions you might have on [Discord](https://discord.gg/dHzgYs7c97) and [Github](https://github.com/nhost/nhost)!