What is Appwrite?
Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps packaged as a set of Docker microservices. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster.
How will this post be help to you?
This post is for the beginners who are trying to get started with Appwrite. This post teaches you how you can use Appwrite user services in your Appwrite project.
What are we going to use?
We will be using:
What we will do
We will be creating a simple login / signup form using Appwrite's users services. The registered user can see other users who are registered and check their username , email verification status , registeration date etc.
Installing dependencies
Now we will install all the required dependencies for out project
package.json should look like this:
{
"name": "appwrite-toturial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "electron ."
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"appwrite": "^4.0.4",
"dotenv": "^10.0.0",
"electron": "^15.3.0",
"moment": "^2.29.1",
"node-appwrite": "^2.5.1"
}
}
Now, run npm install
to install the dependencies!
Template
Create three files - index.html , styles.css and app.js
The code for the frontend (html and css) in the github repository.
app.js should be like this:
const notyf = new Notyf()
const loginText = document.querySelector(".title-text .login");
const loginForm = document.querySelector("form.login");
const loginBtn = document.querySelector("label.login");
const signupBtn = document.querySelector("label.signup");
const signupLink = document.querySelector("form .signup-link a");
signupBtn.onclick = ((e) => {
loginForm.style.marginLeft = "-50%";
loginText.style.marginLeft = "-50%";
});
loginBtn.onclick = (() => {
loginForm.style.marginLeft = "0%";
loginText.style.marginLeft = "0%";
});
signupLink.onclick = (() => {
signupBtn.click();
return false;
});
index.js:
This file will be our entrypoint for this application. We will initialize electron here.
const { app , BrowserWindow } = require("electron")
const path = require("path")
app.on("ready", () => {
const window = new BrowserWindow({
"width": 500,
"height": 500,
"webPreferences": {
"nodeIntegration": true,
"contextIsolation": false,
}
})
window.loadFile(path.join(__dirname, "index.html"))
})
Now, run npm run start
and you should see a login / signup form.
Starting the application
- Gather all the input and buttons for getting the data from user
We will use JavaScript's .querySelector
method for selecting both the buttons and listen for each of them
In app.js:
const loginText = document.querySelector(".title-text .login");
const loginForm = document.querySelector("form.login");
const loginBtn = document.querySelector("label.login");
const signupBtn = document.querySelector("label.signup");
const signupLink = document.querySelector("form .signup-link a");
signupBtn.onclick = (() => {
loginForm.style.marginLeft = "-50%";
loginText.style.marginLeft = "-50%";
signUp()
});
loginBtn.onclick = (() => {
loginForm.style.marginLeft = "0%";
loginText.style.marginLeft = "0%";
signIn()
});
signupLink.onclick = (() => {
signupBtn.click();
return false;
});
document.addEventListener("keydown" , (e) => {
if(e.keyCode === 27){
const target = document.querySelector(".userInfo")
if(target.style.opacity == 1){
target.classList.add("fade")
target.style.display = "block"
setTimeout(() => {
target.classList.remove("fade")
target.style.opacity = 0
target.style.display = "none"
} , 599)
notyf.success("Press ESC to close")
}
}
})
Now we will first start by creating a new user.
To create a new user, firstly we will have to initialize all the required classes from appwrite.
Gather projectId , endPoint and api Key from appwrite's dashboard and use them here.
const sdk = require("node-appwrite")
const client = new sdk.Client()
client.setEndpoint(apiEndPoint)
.setProject(projectId)
.setKey(projectAPiKey)
const users = new sdk.Users(client)
Next, we will listen for the click and add user to database
document.querySelector(".signUp_button").addEventListener("click" , (e) => {
e.preventDefault()
const username = document.querySelector(".sign_up_username").value
const email = document.querySelector(".sign_up_email").value
const password = document.querySelector(".sign_up_password").value
if(password.length < 6){
notyf.error("Password must be at least 6 characters")
return
}
users.create(email , password , username).then((res) => {
notyf.success("Successfully Created A New User!")
})
.catch((err) => {
console.error(err)
notyf.error("Error while creating a new user!")
})
})
Now, this is the function which will run on click of the sign up button
The first line is pretty simple, it prevents the default behaviour. The next three lines are for the user's credentials. Next, we are checking if the length of the password is not less than 6. Note: Appwrite raises an error if the password length is less that 6
. Finally, creating users is pretty simple. The User class which we initiated, will be used to create the user. Now run the file and enter username , email address and password.
Now, move to the appwrite's dashboard and click the Users button under Develop in left panel.
Now, you will see that a new user is created and it should look somewhat like this:
Great! We have successfully created sign up form!
- Making login form
Now, making login form is as simple as creating user. Instead, it is done using a different module named appwrite
.
Here is how you would do it:
// Import the appwrite module
const { Appwrite } = require("appwrite")
const server = new Appwrite()
server.setEndpoint(endPoint)
.setProject(projectID)
document.querySelector(".login_button").addEventListener("click" , (e) => {
e.preventDefault()
const email = document.querySelector(".signin_email").value;
const password = document.querySelector(".signin_password").value
server.account.createSession(email, password).then((res) => {
notyf.success("Successfully logged in!")
})
.catch((err) => {
notyf.error("Username or password is incorrect!")
})
})
So, firstly we are listening for the click. On click, we are gathering username and password from input element in DOM. Next, we are creating a session for the user login. This session can be used for the next time whenever the users opens the app (The session is stored inside of the user's system and can be retrived any time). It would directly take them to dashboard instead to again doing login. So, if the account email and password are correct, we would send a message saying that there was a successful login. If the login email / password is incorrect, we will display invalid credentials message.
Now, we have successfully created a working login / signup system!
Showing a list of users available
Now that our login / signup system is complete, we will show the users, the names of all the other users registered.
...
users.list().then((users) => {
const parent = document.querySelector(".users")
for(let user of users.users) {
const card = document.createElement("div");
card.addEventListener("click" , parseFunction(showUser , [user["$id"]]));
card.classList.add("user-card")
card.innerHTML = user.name;
parent.appendChild(card);
}
})
.catch((err) => {})
const parseFunction = (name , args) => {
return () => name(...args)
}
So, here, firstly, we are requesting to the appwrite to send a list of all the users registered. users.list
returns a object with the list of users. name
gives the name of that specific user. There are other properties too which can be used. You can see them here
When you run this function, you will see a list of users logged in (even though at first, you will see your own username if you are the only one registered, you can try to sign up with multiple emails and test that out).
Next, we are just creating a card for showing the user's name.
Show user's profile
So, when we will click on a specific user's card, we should see his/her name, when they signed up , and their status.
const showUser = (userId) => {
users.get(userId).then((user) => {
document.querySelector(".userName").innerHTML = "Username: " + user.name
document.querySelector(".userVerified").innerHTML = "Email Verified: " + (user.emailVerification ? "Verified" : "Not verified")
document.querySelector(".userRegistration").innerHTML = "Registration: " + moment(user.registration).format("DD/MM/YYYY")
document.querySelector(".userStatus").innerHTML = "Status: " + (user.status === 0 ? "Unactivated" : user.status === 1 ? "Activated" : "Blocked")
const target = document.querySelector(".userInfo")
if(target.style.opacity == 0){
target.classList.add("unfade")
target.style.display = "block"
setTimeout(() => {
target.classList.remove("unfade")
target.style.opacity = 1
} , 599)
notyf.success("Press ESC to close")
}
})
}
So, this function fetchs the user according to the user id. Then, we can use the data to show the user's name , whether their email is verified , the date when they registered and their status (whether thay are active, inactive or blocked). Here is the list of the data that appwrite returns. Next lines are for animation. The block appears with a unfading animation.
Updating user's credentials
Now that we have created a system for user sign up, we should also allow users to edit their crendentials.
document.querySelector(".update").addEventListener("click", (e) => {
e.stopImmediatePropagation()
var f = false
users.updateEmail(currentUserId , document.querySelector(".editEmail").value).then((res) => {})
.catch((err) => {
notyf.error("Invalid email")
f = true
})
if(f){
return
}
f = false
users.updateName(currentUserId , document.querySelector(".editName").value).then((res) => {})
.catch((err) => {
notyf.error("Invalid email")
f = true
})
if(f){
return
}
f = false
users.updatePassword(currentUserId , document.querySelector(".editPassword").value).then((res) => {})
.catch((err) => {
notyf.error("Invalid email")
f = true
})
if(f){
return
}
notyf.success("Successfully changed the credentials")
})
So, here firstly we are listening for the update button click. On click, we would do the following things:
- Update the email - Get the new email from the input and check if there wasnt any error while updating. If there was, send a toast notification
- Update the username - Get the new username from the input and check if there wasnt any error while updating. If there was, send a toast notification
- Update the password - Get the new password from the input and check if there wasnt any error while updating. If there was, send a toast notification
Creating logouts
Now, the user should be able to logout. This should go like this:
document.querySelector(".logout").addEventListener("click", (e) => {
server.account.deleteSession("current")
const target = document.querySelector('.wrapper')
const secondtarget = document.querySelector(".dashboard")
secondtarget.classList.add("fade")
target.classList.add("unfade")
target.style.display = "block"
setTimeout(() => {
target.classList.remove("unfade")
target.style.opacity = 1
secondtarget.classList.remove("fade")
secondtarget.style.opacity = 0
} , 599)
notyf.success("Successfully logged out")
})
So, we are listening for the click on the logout button. Whenever the user clicks the button, we will delete the session that we have created during login. "current" deletes the current session saved in the user's system. As the session is deleted, next time we open up the app, it will redirect to the login / signup page.
Next lines are for fading and unfading effect for the dashboard and authentication page, respectively.
Deleting account
Now that we have created all the elements, we will now allow users to delete their account.
The code should go like this:
document.querySelector(".delete").addEventListener("click" , (e) => {
users.delete(currentUserId)
const target = document.querySelector('.wrapper')
const secondtarget = document.querySelector(".dashboard")
secondtarget.classList.add("fade")
target.classList.add("unfade")
target.style.display = "block"
setTimeout(() => {
target.classList.remove("unfade")
target.style.opacity = 1
secondtarget.classList.remove("fade")
secondtarget.style.opacity = 0
} , 599)
})
Finally, we will listen for the click on the delete button. Whenever the user clicks it, we will run the function.
The first line of the function deletes the user from the databse. The next lines are just for the animations just like we did in logout.
Conclusion
I hope that you will have understood how to use Appwrite's Users Services. This tutorial uses all the services that appwrite provides and bundles them into a project.
I found out about Appwrite from the Hacktoberfest event. I really love this project. Its simple, easy and most of all - secure and fast. It has a good UI for seeing the requests count, database collections and users. I would really recommend using Appwrite while creating a database application.
Github repository
Here is the full source code for this project:
Top comments (0)