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 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:
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. We are using the operating system Linux, so we use the insulation script:
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.
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.
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.
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.
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.
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 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
.
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.
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.
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.
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.
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
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.
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:
$ 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.
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:
$ 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:
$ node src/seeds.js
If everything goes well, we can see documents in our movies collections and many movie covers in our storage.
โจ๏ธ 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 to become part of the friendly and supportive Appwrite community.
Here are some handy links and resources:
๐ Learn more
You can use the following resources to learn more and get help regarding Appwrite and its services.
- ๐ Appwrite Github
- ๐ Appwrite Docs
- ๐ฌ Discord Community
Top comments (16)
I finished this part. Not everything went smooth. I had to change a lot of things to make it run. In case of problems you can text me.
hi bro, as a learner I am making a Netflix clone app using appwrite as a backend for first time but I am stuck, a error occurred ('Storage bucket with the requested ID could not be found.') so in your development time what you change to make it run ? plz give me a to z details about it :)
Like what?
Migrations and seeds scripts do not execute correctly. It seems like there is a 'bucket' required, which was not indicated to setup in this tutorial.
Migration:
๏ฟฝ Could not finish migration:
AppwriteException [Error]: Bucket not found
at Client.call (D:\Websites\almost-netflix-project-setup\node_modules\node-appwrite\lib\client.js:160:31)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async Storage.listFiles (D:\Websites\almost-netflix-project-setup\node_modules\node-appwrite\lib\services\storage.js:50:16)
at async D:\Websites\almost-netflix-project-setup\src\migrations.js:87:25 {
code: 404,
response: { message: 'Bucket not found', code: 404, version: '0.13.4' }
}
Seeds:
๏ฟฝ [1/25] Downloading +20 movies ...
AppwriteException [Error]: Bucket not found
at Client.call (D:\Websites\almost-netflix-project-setup\node_modules\node-appwrite\lib\client.js:160:31)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async Storage.createFile (D:\Websites\almost-netflix-project-setup\node_modules\node-appwrite\lib\services\storage.js:97:16)
at async intiniteRequest (D:\Websites\almost-netflix-project-setup\src\seeds.js:21:15)
at async downloadMovies (D:\Websites\almost-netflix-project-setup\src\seeds.js:82:17)
at async D:\Websites\almost-netflix-project-setup\src\seeds.js:137:3 {
code: 404,
response: { message: 'Bucket not found', code: 404, version: '0.13.4' }
same error on my side, do you have any workaround, I'm a newbie on appwrite
Hi , I faced the same issue now , is there any workaround ?
what is the workaround did you make? thanks, can you share
you find the solution ?
Wow! This is really detailed ๐
I hope that its just a first big project created by team :) Great to see some good tutorial. Last time I was following reactBits on youtube but it was outdated. Its really nice to see that you can build something similar to Netflix with Appwrite.
Great idea. Please show how to use it with Flutter in details
Stay tuned, we will be releasing Flutter Almost Netflix soon ๐
Flutter version is available here: dev.to/appwrite/almost-netflix-a-n...
Part 2: Introducing Almost Netflix: Netflix clone built with Vue and Appwrite
I cant create Boolean attribute. Can someone help?
dev-to-uploads.s3.amazonaws.com/up...
I believe an issue has been created for this and the PR is pending merge.