
No Comments Yet
Be the first to share your thoughts and start the conversation.
Be the first to share your thoughts and start the conversation.
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
In this lesson, we explore how to implement a backend system using AppWrite within a React application. The focus is on setting up environment variables, initializing the AppWrite client, and implementing authentication functionality, including Google login.
npm install app-write
..env
as VITE_APPWRITE_API_ENDPOINT
.client.ts
, including export configuration like endpoint URL, project ID, and API key.auth.ts
for logging in, logging out, fetching user data, and storing user information in the database.00:00:02 To get started implementing our backend system, I'll head over into our terminal and just run one simple command, npm install app-write.
00:00:12 We'll use it to handle our backend.
00:00:14 It got installed in a couple of seconds.
00:00:16 And now I'll head over into our .env just to add one more environment variable.
00:00:22 which I'll call Vite AppWrite API endpoint.
00:00:27 We can add it right here at the end.
00:00:29 And this is something that is the same for every single AppWrite project, so I'll set it to https://cloud.appwrite.io/.v1.
00:00:41 This is where the cloud version of AppWrite is hosted, so our app needs to know it so you can hit those proper endpoints.
00:00:47 Now we'll need to set it up.
00:00:49 So I'll check out this documentation that is very simple.
00:00:53 It guides you through everything we have done so far, but then it asks you to set it up from within the code.
00:00:58 So to get to this page, you can just head over to AppWrite documentation, quick start for React, and scroll down to the part where we have the code.
00:01:08 Perfect.
00:01:09 So it says to create a new file under lib app-write.js and add the following code to it.
00:01:15 But instead of just copy pasting what we have here, we're going to write it together from scratch.
00:01:20 That's what you're watching this video for anyway, right?
00:01:23 To learn how to do things properly from scratch.
00:01:25 So back within the code, let's head over into our file explorer and head into app, create a new folder within it called app-write,
00:01:36 and within the app-write folder, create a new client.ts file.
00:01:42 where we'll set up the AppWrite client.
00:01:44 Here, we'll first get access to all of the AppWrite variables coming from constants, and then we'll export them so we can use them from within the rest
00:01:53 of our application.
00:01:54 So export const AppWrite config is equal to an object where we're going to have the endpoint URL, set to import.meta.env.vete.appride.api.endpoint and
00:02:15 now we can duplicate this a couple of times because we'll need to change it for different things.
00:02:20 The second one will be the project ID and then of course we'll have to change it to vete.appride.projectID.
00:02:29 After that, we'll need the API key, which will be Veed AppRide, you can guess it, API key.
00:02:37 After that, we have a database ID, and then we'll point it to database ID.
00:02:43 After that, we have the user collection ID, pointing to Veed AppRide users collection ID.
00:02:53 And finally, we have the trip collection ID pointing to Veed AppRide trip collection ID.
00:03:02 Let's just make sure that we have called them properly.
00:03:05 Trips, trips, user, user.
00:03:07 It has to be the same.
00:03:09 So if you open up your ENVs, you might want to compare them.
00:03:13 I used users plural as well as trips plural as well.
00:03:17 So make sure to spell it properly.
00:03:20 Otherwise, the app will not work.
00:03:22 So you have to do this very carefully.
00:03:24 What you can do is maybe a global search for the entire thing.
00:03:28 You can do that with Ctrl or Command Shift F, and it should search it across the entire code base.
00:03:33 So I can immediately see that this one matches.
00:03:36 This one matches as well.
00:03:38 Database ID is here as well.
00:03:40 I can see it here.
00:03:41 This one matches as well.
00:03:43 AppWrite API key is there.
00:03:45 Project ID is here.
00:03:47 And API endpoint is here as well.
00:03:49 I think I should be good.
00:03:51 Now that we have this entire configuration, we can say const client is equal to new client coming from AppRite.
00:04:02 So new AppRite client.
00:04:04 And on it, we can call a method called setEndpoint to which we can pass over the AppRite config dot endpoint URL.
00:04:13 And I'll also call the setProject to which I'll pass the AppRite config dot project ID.
00:04:21 So this way, this AppRite client knows exactly which project and endpoint we're working on.
00:04:27 After that, we'll have to set up additional AppRite functionalities, such as const account to manage user accounts.
00:04:34 We'll be equal to new account.
00:04:37 Make sure to automatically import it from AppRite at the top, account and client from AppRite.
00:04:44 To which we'll pass this client that we have above.
00:04:48 I'll do the same thing for the database.
00:04:51 So cons database is new databases coming from AppRite and to it we'll pass the client.
00:04:59 And cons storage is equal to new storage also coming from AppRite.
00:05:05 Make sure to import it at the top.
00:05:09 and I'll pass the client.
00:05:11 So now that we have the general AppRight client, as well as these three additional functionalities, we can just export them from this file so we can use
00:05:20 it within other files.
00:05:22 Client, account, database, and storage.
00:05:28 Perfect.
00:05:29 So now that this implementation is done, the next step will be to implement authentication.
00:05:34 There are two different approaches we can take right here.
00:05:37 The first one would be to focus on the layout or the UI first, like what we have been doing before.
00:05:43 And the second one would be to first implement the functionality.
00:05:47 In this case, we have Google Auth connected to AppWrite Auth, and then later on, we can very easily do the UI.
00:05:54 So, what do you say?
00:05:56 Let's do the harder thing first.
00:05:59 Back within our codebase, I'll create a new file within the AppWrite folder, which I'll call auth.ts.
00:06:08 Here, we'll create all sorts of different methods that allow us to handle authentication, starting with, of course, the login.
00:06:17 So all of these different methods will start with export, const, because these functions will be used from within our frontend.
00:06:27 So I'll say export, const, login with Google.
00:06:32 It'll be equal to an asynchronous callback function.
00:06:36 that'll have a try and catch block.
00:06:40 In the catch, we will simply console.log that error, and that's going to be it.
00:06:45 Now, we'll have all sorts of different functions that'll follow this same exact structure.
00:06:51 Export const async function with a try and a catch block where we console.log something.
00:06:58 So what do you say that we automatically duplicate it a few times and then rename it for all sorts of different functions that we'll need?
00:07:06 I'll do it a couple of times and then we can start renaming them.
00:07:10 So we have login with Google, Of course, we'll also need a logout user to log them out.
00:07:18 Next, we'll need to get the user.
00:07:21 This is to get the user profile.
00:07:23 We'll also need one to get the Google picture.
00:07:28 their profile photo, and we'll also need one to store the user data into the database once they first log in.
00:07:35 So store user data.
00:07:38 And if I'm not mistaken, we'll also need one to get the existing user, if they existed before, right?
00:07:46 Now, how did I know that we'll need all sorts of these different functions?
00:07:50 Or the other question is, how can you know when you're just approaching this project?
00:07:54 The answer is, you can't.
00:07:56 I actually took the time to build this application beforehand so I can teach it to you properly.
00:08:01 If you were building this for the first time, you would just start with one massive big function and you would start noticing that that function actually
00:08:10 is getting too big and it's doing too many different things.
00:08:14 With proper code, one function should have one job.
00:08:18 So as soon as you start noticing that it's starting to get more jobs, you separate it into other functions.
00:08:24 Okay, but with this in mind, we can start implementing these one by one, starting with the login with Google functionality.
00:08:32 Here, we want to leverage AppWrite's functionalities that we have exported from the AppWrite client file.
00:08:38 such as for login with Google, we want to leverage the account functionality coming from AppWrite Client.
00:08:46 Specifically, the create OAuth2Session method that accepts a couple of different parameters.
00:08:55 The first one is the OAuthProvider.
00:08:57 So I'll say OAuthProvider.
00:09:01 That's going to look like this.
00:09:04 And as the second parameter, we have to provide the success URL.
00:09:08 And as the third one, the failure URL.
00:09:10 But all of these are optional.
00:09:12 So I think if we just leave them empty for now, we should be good.
00:09:15 OAuthProvider.google.
00:09:18 And you might need to import this OAuthProvider coming from AppRite.
00:09:23 Perfect.
00:09:23 Believe it or not, this is it to log in the user.
00:09:26 Now for each one of these errors, in case you want to make them a bit more descriptive, you can say before the error itself,
00:09:32 you can render a string with the same name as the function.
00:09:35 So you know exactly where that error is coming from.
00:09:39 Great.
00:09:40 So login with Google is done, but once we actually log the user in, we might want to focus on getting that user's information.
00:09:48 Okay.
00:09:49 So we'll leverage the same account functionalities, but this time not to create a new OAuth session, but rather to get that user that we have just created.
00:10:00 So I'll say const user is equal to await account.get.
00:10:08 Then, if we don't have access to a user, so if no user, I'll simply return a redirect to forward slash sign in.
00:10:18 Something obviously went wrong.
00:10:20 But where is this redirect coming from?
00:10:22 Well, it's going to come directly from React Router.
00:10:26 Pretty simple way to do it.
00:10:27 But in case we do actually get back the user, we want to extract something out of it.
00:10:33 So I'll say const, destructure the documents, and say that is equal to await database.listDocuments.
00:10:43 And here, you're basically telling it, hey, extract some documents from the database for me.
00:10:49 But you have to actually say exactly from where in the database you want to extract them.
00:10:55 So you have to provide the ID of the database, the ID of the collection, and then finally the query with which you want to query that database.
00:11:03 So thankfully, we have stored all of those pieces of data within our AppRite configuration.
00:11:08 So as the first parameter, I'll provide a database ID.
00:11:13 And this is coming from AppRite config.
00:11:17 So make sure to import this AppRite config right here at the top.
00:11:21 And then we have to provide the collection ID.
00:11:24 So that's AppRite config dot user collection ID.
00:11:28 And as the third parameter, you have to provide the actual query that you want to use to query these documents.
00:11:34 So I'll use AppWrite's query functionality, which we'll need to import from AppWrite.equal, so we want to return documents where the account ID equals
00:11:47 to the user So we're only returning the data for the user that is currently logged in.
00:11:56 Then I want to run the query.select to tell it which fields do we need, such as the name, email, image URL, when did the user joined,
00:12:07 so joined ad, and the account ID.
00:12:09 Perfect.
00:12:10 And of course, make sure to import this database coming from AppPri client.
00:12:16 Great.
00:12:17 So this function should give us back our logged in user.
00:12:20 So I'll shift it above, right above our logout user, because we might not need that functionality for some time yet.
00:12:28 But what we will need is a Google picture.
00:12:31 So extracting this seems like a perfect thing for an AI to do, as we don't have to necessarily write all the code ourselves,
00:12:39 especially repetitive or boring code, which doesn't really deal with any logic.
00:12:43 So this might be a perfect chance to give Juni a try.
00:12:47 See, Juni is JetBrains or WebStorm's new smart coding agent for productivity.
00:12:53 and I wanted to test it out a bit to see whether it can help us with this.
00:12:57 I started using it recently and I'll link it in the description in case you want to test it out too.
00:13:01 But let me give it a shot and see what it comes up with.
00:13:04 So I'll open it up by pressing Command-Shift-P and then typing Juni, which will open it up right here on the right side.
00:13:11 Now I'll give it a task to fetch the profile photo from the Google People API and return its URL.
00:13:23 Okay, I really wasn't descriptive enough, so let's see if it can actually do it based on this limited amount of information.
00:13:30 Okay, it created a plan which it will use to do that.
00:13:34 It actually checked out the ENVs and it's opening the odd file.
00:13:39 and now it should actually write some code.
00:13:41 After some thinking, it looks like the getGooglePicture function has been implemented to fetch the user's profile photo from the Google People API using
00:13:50 the OAuth token.
00:13:51 It's also changing the store user data and getExistingUser.
00:13:55 Oh, it also implemented the logout function.
00:13:57 This is pretty cool.
00:13:58 So it seems like it actually did a lot of stuff right here.
00:14:03 It stored the user data into AppRite by fully understanding how AppRite actually works, creating a new user document, and it even fetched the existing
00:14:13 user from AppRite.
00:14:14 All of this is super amazing.
00:14:17 But did it do what we asked it to do?
00:14:20 Well, let's check it out.
00:14:22 First things first, it is getting the current session and it's getting the OAuth token from that session.
00:14:28 Then it's checking whether it got that access token.
00:14:32 And by the way, if you don't have Juni, you can just pause right here and write out this code as well.
00:14:37 Then, it's actually making a request to the Google People API to get the profile photo, so it actually scouted the web and found the right endpoint.
00:14:47 People, googleapis.com, v1people, me, personfields, photos.
00:14:53 This is exactly how it should be.
00:14:55 and it passed the headers with the authorization bearer OAuth token.
00:14:59 If it failed, it console logs it.
00:15:02 Else, it extracts the data, gets the photo URL, and returns it.
00:15:07 This is pretty crazy.
00:15:08 This is the exact implementation that I had in mind.
00:15:12 So, I can now collapse it, and they just told me getGooglePicture function was implemented.
00:15:18 The implementation is error-free and all the related functions were updated accordingly.
00:15:24 I gotta say, this is amazing.
00:15:26 And it even tackled the logout user functionality, where it simply deleted the current session and returned true.
00:15:34 So feel free to pause and implement this as well.
00:15:37 And if we look into the store user data, here it's getting the user, it's checking whether the user already exists in the database,
00:15:46 and by trying to list that document, if it does exist, we simply return it.
00:15:51 Else, we get access to the Google photo, and then we create a new user.
00:15:56 Await database.createDocument within this database, the user collection, we make it unique, I think here we can do a bit better by saying id coming from AppRight.unique.
00:16:13 So here we can really use a unique ID, and then it passed over the account ID, the email, the name, the image URL, and the date we joined that.
00:16:26 Finally, it returned the new user.
00:16:28 This is the perfect implementation of this function, and I gotta say, I am amazed.
00:16:34 It did everything I asked it to, and even more.
00:16:38 It's even checking for the existing user and returning it if it exists.
00:16:41 But with such a great implementation of the getUser function, it's even checking for that here.
00:16:47 So that additional function might even be redundant.
00:16:50 Okay, since Juni coded this for me, it's possible that while trying to replicate it, you maybe have some typos.
00:16:56 So for that reason, I'll provide this auth.ts file within the video kit as well, so you can copy it and ensure that you have the same exact implementation
00:17:05 that I have.
00:17:05 Even I'll do it right here by deleting it and putting it here, just to ensure that everything is exactly the same.
00:17:12 And with this in mind, I'll also push this over to GitHub by running git add dot git commit dash M.
00:17:21 And I think I forgot to push for the last couple of lessons.
00:17:24 So since then we have implemented, routing, dashboard layout.
00:17:33 dashboard UI as well, so dashboard layout and UI, and now even the auth functionality.
00:17:41 So I'll commit it and push it.
00:17:43 And in the next lesson, we can focus on implementing the UI of this great authentication page.