Did we just build a Netflix clone with Appwrite?
Tags: javascript, opensource, programming, webdev
Published: 2022-01-18 10:17:29

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l1qgdzaxva2blpnpfiuw.png) 

Welcome to the beginning of our 3 part series where we build a fully functional Netflix clone we like to call, Almost Netflix! Almost Netflix is a movie streaming app just like Netflix, but completely open source and built with technologies you love! We'll be using Appwrite to handle all the backend functionality and walk you through the process of creating the frontend in Web, Flutter, Android and iOS. 

Stay tuned, as we will be continuing this series in future Appwrite releases and improving our demo step by step. Today's blog post is a setup to prepare you for what's to come tomorrow. 😉 

Before jumping into the frontend, we need to prepare an Appwrite instance. This post will guide you through the installation of Appwrite, project setup, database preparation, and data insertion.

> **🤔 What is Appwrite ?** 
[Appwrite](https://appwrite.io/) is open source backend-as-a-service that abstracts all the complexity involved in building a modern application by providing you with a set of REST APIs for your core backend needs. Appwrite handles user authentication and authorization, databases, file storage, cloud functions, webhooks and much more! If there is anything missing, you can extend Appwrite using your favourite backend language.

## 🤖 Appwrite installation

Appwrite runs its services using a Docker infrastructure, so to install Appwrite, we will need Docker up and running on our machine. We will be running this project on a $10 DigitalOcean droplet with the Linux operating system. On Linux, we can installation Docker using the following command:

```bash
curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh
```

> You can skip this step if you have Docker already installed on your machine. To check that, you can run the `docker --version`, and if this command does not fail, you have Docker already installed.

With Docker installed, we can continue to install Appwrite. Installing Appwrite on any platform is as simple as running a single docker command in the terminal or command prompt. The command is tiny-bit different for each platform, so make sure to use the correct one from our [installation docs](https://appwrite.io/docs/installation). We are using the operating system Linux, so we use the insulation script:

```bash
docker run -it --rm \
    --volume /var/run/docker.sock:/var/run/docker.sock \
    --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
    --entrypoint="install" \
    appwrite/appwrite:0.12.0
```

> Make sure you use the latest Appwrite version to access all the cool features we are releasing.

Just like that ✨ we now have Appwrite installed on our machine, and when we enter the IP address into our browser, we should see Appwrite's sign-up page.

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

If you are running Docker on your computer, you can use the word `localhost` instead of the IP address. Throughout this tutorial, we will use the domain `demo.appwrite.io` to reference our server running Appwrite.

## 🛠️ New Appwrite project

We are on the sign-up page already, so let's make an account, shall we? This process is pretty straightforward. Enter your account information and click `Sign Up`. Once we create the account, the website will redirect us to a dashboard where we can see a list of our projects - an empty list.

![Projects list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/00stuxe8qyk1xcg50e6c.png)

To interact with Appwrite, we need to create a project. By clicking on the `Create Project` button, we open a modal where we can set the project's name and ID. Let's set the name to `Almost Netflix` and ID to `almostNetflix`.

> ID is auto-generated by default, but you can click on the edit icon to allow any custom string in this field. You can learn more about this process in our [custom IDs article](https://dev.to/appwrite/what-are-appwrites-new-custom-ids--5g6a).

![New project modal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uya431222zjt0e490enk.png)

The project is created within a few seconds, and we are redirected to the project dashboard. There we go, another step finished! 💪

Appwrite provides many services to make app development more accessible and joyful, but we won't be needing all these services for our Almost Netflix project. Thanks to the latest Appwrite update, we can disable specific services we don't need to prevent users from (ab)using them.

To disable a service, click `Settings` at the bottom of the sidebar. In there, we switch to the `Services` tab, and by clicking on toggles of `Locale`, `Health`, `Teams` and `Functions`, we disable these services.

![Settings services page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iyjo9ykmtn0lu7l2nkwq.png)

Perfect, services configured 👌 There's one more security feature we can enable! This time, let's click `Users` in the left menu and switch to the `Settings` tab. In this view, we can see all authentication methods allowed by Appwrite. We will only use `email/password` to disable the rest.

![Users settings page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ypegvedycecdt6rknb77.png)

Finally, we are satisfied with our project setup. Let's continue by setting up the services we will be using. Thankfully, Almost Netflix only requires one service - **database**.

## 🗄 Databases, collections, attributes, and indexes

Appwrite database consists of collections. A collection is a group of multiple documents that share the same structure and potentially the same permissions. A document is a simple key-value stored in a JSON format which can also have its own permissions. Every key in a document is called an attribute, and we can configure it to a specific type, maximum length, or default value. Finally, we have indexes to optimize specific filters and sort queries.

Now that we understand the terms and know what we need to configure for every collection, let's see what collections we will need. For the sake of simplicity, we will store all movie's data in one `movies` collection, without any relations. Alongside that, we want to support watchlists so that we will have one collection for that. Let's see how we can configure these two collections.

The process is explained step-by-step in the Appwrite console, but you can also do this programmatically! 🤩 If you want to use a programmatic setup, you can skip a few following sections and start reading from [Programming setup](#programming-setup) section.

### Movies collection

We start by clicking on `Database` in the sidebar. We should see an empty database without any collections, so let's make one! We click on `Add collection`, set `name` to `Movies` and `Collection ID` to `movies`.

![New movies collection](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rwboyaw01736lgc2gzvz.png)

After creating the collection, we will be redirected to the settings page of our collection. We should set up permissions here because by default, Appwrite would not allow anyone to `read` from our new collection. First, we need to decide if we should be using `collection-level` or `document-level` permission. Our Almost Netflix use case does not call for document specific permissions, so we'll stick to `Collection Level` permissions in our settings page. This option opens up some more customization and allows us to specify who can read documents in this collection and who can create new ones. We want logged-in users to see all movies, and we don't need to allow anyone to create new movies because every user is just a viewer. To write this into the Appwrite permission system, we set `read` permissions to `role:member` and keep `write` permissions empty. Last but not least, we click `Update` to apply these changes.

![Movies collection settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4na7tgo1383mis6rp7i.png)

Perfect, permissions configured! 💪 Next step, let's configure attributes. We click on the `Attributes` tab to see that we don't have any attributes yet.

![Movies collection attributes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6hs1dxsw6l6tvvn0is88.png)

We will need to add a bunch of attributes, so let's make a list with all settings:

String attributes:

| key              | size | required | array |
|------------------|------|----------|-------|
| name             | 255  | true     | false |
| description      | 5000 | false    | false |
| thumbnailImageId | 255  | true     | false |
| cast             | 255  | true     | true  |
| tags             | 255  | true     | true  |
| genres           | 255  | true     | true  |

Integer attributes:

| key                | min | max  | required |
|--------------------|-----|------|----------|
| durationMinutes    | 1   | 1000 | true     |
| netflixReleaseDate | 1   | -    | false    |
| releaseDate        | 1   | -    | false    |

Float attributes:

| key           | min | max | required |
|---------------|-----|-----|----------|
| trendingIndex | -   | -   | true     |

Boolean attributes:

| key        | required |
|------------|----------|
| isOriginal | true     |

Enum attributes:

| key            | required | elements              |
|----------------|----------|-----------------------|
| ageRestriction | true     | AR7, AR13, AR16, AR18 |

When we click on `Add Attribute` and select the type of attribute we want to add, a modal will be opened, and we can configure data from the list above. Once configured, we click `Create` to create one attribute. We repeat these steps for all the attributes until we have the list complete.

![Movies collection with all attributes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nfxqupijiqfoed01qls7.png)

Woah, that took quite some time. Good thing we played with so many different types and configurations. Now we can call ourselves experts of Appwrite attributes 😎

To finish the setup of the movies collection, let's switch to the indexes tab. Again, we are presented with an empty list since we didn't add anything yet. We will need multiple indexes for different filters and sorting we will do in our application in the future, so let's prepare the list again:

| key                 | type     | attributes            |
|---------------------|----------|-----------------------|
| trendingIndexDESC   | key      | trendingIndex(DESC)   |
| isOriginalDESC      | key      | isOriginal(DESC)      |
| durationMinutesDESC | key      | durationMinutes(DESC) |
| releaseDateDESC     | key      | releaseDate(DESC)     |
| nameFULLTEXT        | fulltext | name(ASC)             |
| genresFULLTEXT      | fulltext | genres(ASC)           |
| castFULLTEXT        | fulltext | cast(ASC)             |
| tagsFULLTEXT        | fulltext | tags(ASC)             |

Similarly to attributes, we now click on `Add Index` and fill the form with information from our list. We repeat until we have all indexes added.

![Movies collection with all indexes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2s84qvkrnmh9xj9gusro.png)

Believe it or not, the movies collection is ready! 🥳 By making this huge collection, we learned a lot of concepts and got really confident with the Appwrite interface. Here is cookie 🍪 for your effort if you followed along this far! If you ever meet me, you can trade this for a real cookie 😉 

### Watchlists collection

Let's do the same for the watchlist collection, but since we already understand the process, let's speed it up a little 😏

We create a new collection with name `Watchlists` and ID `watchlists`. We keep permissions on `document-level`, since users should only see their documents. We add the following attributes:

String attributes:

| key              | size | required | array |
|------------------|------|----------|-------|
| userId           | 255  | true     | false |
| movieId          | 255  | true     | false |

Integer attributes:

| key                | min | max  | required |
|--------------------|-----|------|----------|
| createdAt          | 1   | -    | true     |

We also add the following indexes:

| key                 | type     | attributes                |
|---------------------|----------|---------------------------|
| createdAtDESC       | key      | createdAt(DESC)           |
| userIdASCmovieIdASC | key      | userId(ASC), movieId(ASC) |

Voilà, watchlist collection setup finished ✨ There's one final step though. We need to add documents into our collections.

## 🌎 Programming setup <a name="programming-setup"></a>

We need to create hundreds of documents, which we don't want to do manually, of course. We also don't have any data, so we will need to use some 3rd party API... What do we do now? 🤔

Thanks to Appwrite server-side SDKs, we can pick any coding language and write a programmatic setup of Appwrite documents using it. I decided to pick JavaScript for this example because this language is easy to follow along and understand when reading, in my opinion. You can also find the complete source code of the project setup in [this GitHub repository](https://github.com/Meldiron/almost-netflix-project-setup).

First, let's clone the programmatic setup GitHub repository to download all the source code. Then, let's enter the folder and install all NPM libraries needed for the script to work properly:

```bash
$ git clone https://github.com/Meldiron/almost-netflix-project-setup.git
$ cd almost-netflix-project-setup
$ npm install
```

We need to set up some secrets for the script to work correctly. Let's create `.env` file and put this information in there:

```
APPWRITE_ENDPOINT=
APPWRITE_PROJECT_ID=
APPWRITE_API_KEY=
MDB_API_KEY=
```

- You can find the Appwrite endpoint and project ID in the settings of your project
- You can create an API key in the `API Keys` section of your Appwrite project. You can give it all permissions to make sure it has access to all services we might need to use
- You can get your MDB API key by signing up to TMDB. Learn more in [TMDB docs](https://www.themoviedb.org/documentation/api).

We are set! 😎 Let's now use this script.

If you set up the database manually, you can ignore the following paragraph and command.

If you didn't follow previous sections to set up movies and watchlists collections, now it's a great time to use a programmatic setup for that. I personally prefer using a programmatic setup to create collections, attributes, and indexes. This way, I keep the setup in a file that can be pushed to version control (Git). To run the script that creates all of that, we run:

```bash
$ node src/migrations.js
```

The final step is to insert documents. Thankfully, we have a script for downloading the movie list and their images from TMDB, so all we need to do is to run the script and wait until it's finished:

```bash
$ node src/seeds.js
```

If everything goes well, we can see documents in our movies collections and many movie covers in our storage.

![Movies collection documents](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7efw054t5tsa5ix96k74.png)
 
![Storage with images](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mqdqfghzfzq6guqapfa0.png)

## ✨️ Conclusion

That's it! We successfully prepared our Appwrite project for Almost Netflix, and we are ready to use it in a frontend application. In the next tutorial, we'll build a Netflix Clone using Nuxt ( or Vue ) and walk you through the process of building apps with Appwrite! As always, we can't wait to see what you will build with Appwrite! You can also join our [Discord server](https://appwrite.io/discord) to become part of the friendly and supportive Appwrite community.

Here are some handy links and resources:

- [Almost Netflix programmatic setup GitHub](https://github.com/Meldiron/almost-netflix-project-setup)
- [Appwrite Github](https://github.com/appwrite)
- [Appwrite Documentation](https://appwrite.io/docs)

## 🔗 Learn more

You can use the following resources to learn more and get help regarding Appwrite and its services.

- 🚀 [Appwrite Github](https://github.com/appwrite)
- 📜 [Appwrite Docs](https://appwrite.io/docs)
- 💬 [Discord Community](https://appwrite.io/discord)