API's/Backends are difficult and we need websockets. You will be using VS Code as your editor, Parcel.js, Chakra-ui, React, React Icons, and Appwrite. By the end of this workshop, you will have the knowledge to build a real-time app using Appwrite and zero API development. Follow along and you'll have an awesome chat app to show off!
Build a chat room with Appwrite and React
AI Generated Video Summary
AppRight is an open-source backend as a service that simplifies server setup and API design. It offers features like authentication, user management, database storage, cloud functions, and real-time image manipulation. The AppRight dashboard is customizable and can be used to manage the backend using its API. The workshop focuses on building a chat app using AppRight's backend services and frontend frameworks like React and Chakra UI.
1. Introduction to Chat App Development with AppRight
I am Wes Cope, a software engineer at AppRight. We're building a chat app using AppRight's backend as a service. It's written in TypeScript using React and the Chakra UI framework. Join us on Tessa talk to chat during the presentation.
So first of all, I'd like to say thank you to everybody for joining. I am Wes Cope. I guess I can use the slides. So hello. I am Wes Cope, a software engineer, full stack at AppRight, working from everything from database drivers to whatever else I can get my hands on. You can follow me on Twitter. It's WesCope as the slide presents, or you can go to github.com and find me there and the various works and things that I've done.
During this presentation, I will work my best to make sure that I give you guys all the information that you need. Sometimes I do tend to talk fast. So just raise your hand and call me out. I'm good with it. And I will make sure to slow down or if I miss anything, jump into the chat message, ask your question there. And I have it sitting right in front of my face to allow me to answer the questions as quick and soon as possible.
So what will we go over? Well, of course, we're building a chat app. And by chat, I mean you register, you sign in and you start talking just like any chat app that you've seen. It's like a very slim down minimalist version of Slack with no emojis, nothing fancy, just you, text and a conversation.
2. Introduction to AppWrite and Project Layout
I use VS code. The projects layout inside the source folder includes data, forms, pages, providers, router, theme, index.html, index.ts, custom types, PNG and SVG images, and package.json. If you want to join the chat and try the app, visit tesla.talk, appwrite.vercel.app. The source code is available on github.com/WestTeslaTalk. AppWrite is a 100% open-source backend as a service.
Here's the projects layout inside of the source folder. We have a data. This is where I put all the data stuff, database handling, local storage wrappers, anything that makes it nice for me to do that. The forms folder is where I put all of your forms, whether it's the chat input window, your log in your register onboarding. This is not by any stretch of the imagination, anything other than my opinion of the way that I set things up. So everybody does a little different layouts, various layouts. I have a layout for whenever you're onboarding and I have a layout for wherever in the application and I do some magic to check which one and automatically load that for me.
Pages, I guess, all the places where you'll go. The providers, this is a neat thing that React is introduced, I used to be a Redux man, and then I moved on to providers. But some of the work that I did with flutter and dart, I got used to the provider pattern and really started to enjoy how it's working. So I kind of used flutter inspired architecture to use the provider pattern here using React context. And then the router, of course, gets us around in our application. The theme, and yes, I do support dark mode and no, I didn't add a button to do it. And then the index.html is where we render this guy. Index.ts is the entry point for our application, some custom types, and it's PNG and SVG, just so that I could have images there if I decided to. This is kind of a boilerplate setup and then everybody knows what package.json is.
Now, here's the magic. If you guys want to join over on the chat and actually give this thing a try, and you see some of the AppWrite folks have already been a couple of words have been presented there. You could join us at HTTPS, tesla.talk, appwrite.vercel.app. That's a dash. And then you can also view the source code it github.com. West Tesla Talk, and this, the source code that you see it in this repository is exactly what's running on Tesla Talk on Vercel. And also what I'll be going over today. So what is AppWrite? So I encourage everybody to visit appwrite.io. And see exactly what we do. We're a back end as a service. We are open source 100%.
3. Introduction to AppWrite Features
AppWrite is an end-to-end backend server that offers secure APIs, nicely created SDKs, and a user-friendly package. It eliminates the complexities of setting up servers, designing APIs, and writing SDKs for authentication and image upload services. With AppWrite, developers can focus on building applications without worrying about the painful side of development. It offers easy deployment, supports multiple package managers, and is built by developers who prioritize user feedback. AppWrite provides features like authentication, user management, database storage, cloud functions, webhooks, built-in security, geolocation, and real-time image manipulation. These features can be enabled or disabled based on individual requirements.
There's nothing closed source about it. It is secure, we have a focus on security. It's end-to-end back end server. As you can see right here we can do. It's got APIs for rest, socket, well web sockets, etc. It's also got some really nicely created SDKs. And everything is well-documented and put in a very pink package.
So why AppWrite? So developers face problems. We all face problems. Developers have to know quite a few things or in our case we know a lot. A few things in quotes, because sarcasm and all. But we have to do everything from setting up a server to writing in the language, to designing the APIs, to then writing the SDKs to interact rest or and then we use all validation. And then we do all of these pieces and all of these things that we put together over and over again, and I can't tell you how many times because I lost count have I created an authentication service or a image upload service. And so by having to do these over and over again, we also have all these complexities.
4. AppRight Transparency, Deployment, and Dashboard
We're fully transparent and open source. Our community's trust and support have been invaluable in finding bugs and improving the platform. AppRight is plug and play, Docker-based, and fits into your developer experience. It's easy to deploy, whether locally or on DigitalOcean. The dashboard is powered by AppRight and manages AppRight using its API.
We're fully transparent, everything's open source, everything that you see, the website, the SDKs, you can go and look at anything that you want to, we didn't hide anything like other folks did. We wanted to make sure that our community had 100% trust in us and they could see everything because maybe we know that we're going to miss things as well and our community has been very grateful in helping us find bugs and helping us to iterate on things and to make it better and we couldn't do that without a community if any part of our application or any part of our tools or any SDKs if they were closed source, if any part of it was at all. So we have opened everything 100%.
It's plug and play. This kind of fits, it's Docker-based. Everybody's kind of familiar with that. I'm just familiar enough to be very lethal. You have a lot of control of what you're doing. It fits into your developer experiences. Now, these are kind of generic bullet points, but when I say your developer experience, we know how to write apps, we know how to build these APIs, but it's so nice when we don't have to do the API part because it's redundant. And so it fits into our flow of things. We drop an SDK in, the SDK is documented and we can very easily start working on it and we can deploy it and right away, like I said. One click DigitalOcean and you're off to the races. Installing AppRight, if you're going to do it local, or like I said, you can go to DigitalOcean, they do have a one click app. It's really nice. Or you can run one Docker command. And again, appright.io has all the details. This just makes it simple and pretty, but it's a simple Docker run command. It'll install, it'll pull everything down. It does all the magic things that Docker likes to do. And then you can just go to the dashboard.
So, the fun part. First off, I want to show you guys the dashboard. So here's the AppRight homepage. I will jump back and forth between screens. And if you miss something, let me know and I'll swipe back to it. So in our case, so when you log into your AppRight instance, when you first get it, you'll sign up for an account, pretty standard. And a phrase that I've often used as a developer is eating your own dog food. Well, we use that. AppRight dashboard is powered by AppRight and it manages AppRight using AppRight's API.
5. Introduction to AppRight Features and Dashboard
We're transparent and user-focused. I have another project called Almost Netflix using Flutter and Dart. When you log in, you get stats and platforms to add. You can create collections with auto-generated or custom names. Messages give you existing records and attributes. The activity log shows what's happening. Settings include collection ID, enable/disable options, and permissions. I built Tessa Talks in a day, spending more time on slides and setup.
So that should tell you like how transparent we are trying to be. Because we're not just the creators, we're also users. So test the talks. Yeah, I also have one called Almost Netflix, which I can link to later, which is using Flutter and Dart to create a Netflix clone using AppRight. But we're focused on test the talks today.
And when you log in, it gives you some stats and basics. It also gives you some platforms if you want to add to it. If I want to add to the platform, for example, just click here, and there you go. Flutter, Apple, Android, web, coming soon, unity, among other things. Once I create my platform, then I can go up here and then I would go to my database to create my collections.
Well, if you're looking at our chat window, which I just discovered my own bug, which is doesn't say scroll to the bottom, left it out. So on your collections there, you can create a new collection, I can add a collection. I can either auto generate the name of the collection, which would give it a new ID, or I can give it a name. And then just have to be sure that I don't name other collections the same thing. I usually just go with the default auto generated because I'm used to that, it's just what I'm always done or what I always get. Messages is when you click on it, it's going to give you all of the existing messages that are there, all the records, attributes, add and remove attributes, string types, base database types. Think of it kind of like an ORME type feel with validation, with good validation, and with a little bit of that document store with an SQL back structure. So it gives you some of that stability that you would expect from an SQL engine, or SQL, while giving you some of that, I can do this, I can put anything I want to in there. I can develop this entire collection without much work. I just define it here, and then the API is there ready to go. The activity, you can see what's happening there. And when things are happening, course it's a log, your usage is spiking right now. And then your settings right here, this is important, your collection ID. So that's either the one you created or the one that's generated for you, you can get it right here. And then you also have whether I wanna enable it or disable it, and of course permissions. Now for this demonstration, I made everything all, which is not safe and I suggest not doing that, but I wanted to make everything as simple as possible. And I did this, I built Tessa Talks in a day. It took me longer to do the slides and prepare for this presentation than it did for me to actually write the application that we're talking about. It actually probably took me more time to set up the project. So that's kind of where we're at.
6. Introduction to AppWrite Features and Dashboard
I'm not doing any uploading images, so we didn't need to use storage. We have a plethora of OAuth2 providers, including Stripe, Amazon, Apple, and alt zero. The dashboard is customizable with light and dark mode. Let's create that chat room. Everyone has their own style in programming, and I love hearing about different styles. I use Versal to deploy and have configured TypeScript for my project. I have simple modules to import SEG and PNG files into React directly.
And now I'm going to go back, that's the gist. I'm not doing any uploading images, so we didn't need to use storage. If we go to users, I have settings here, I can turn on many features. So we've got magic URL, we've got phone coming soon, which I'm excited about. We have an anonymous type, we have JWT, we have all the things that you expect from an authentication service, such as your alt zeros, octa and those, built right into this one platform so you don't have to use yet another service to provide yet another thing that you have to integrate with. It's all here. And they're all running in their own little worlds.
So OAuth2 providers, we have a plethora of them. There's tons that we can use from Stripe all the way up to Amazon, even a little Apple in there, alt zero as well, we just added. And I came in here, I clicked on the features that I wanted, we can even allocate teams if you wanna do groupings, and then it shows your usage as well. So this dashboard is, I have it in dark mode. It's also, you see our magical pink behind it, but you can switch it to light mode, dark mode. It's very pretty.
So now let's get back to it. Let's go to the, let's create that chat room. So here's my project. Again, the way I set things up or the way I put things together, it's my style. And one thing that I love about engineering and programming, and I've always loved is that everyone has their own style. I don't expect two musicians to sound the same, just like I don't expect two programmers to write the same. So this is my style. If anybody forks the project, I would love to hear from you and see what your style would be. Like I love learning other people's styles and I love engaging on that level. So please, please let me know and any suggestions that you have, I also like to listen to.
So as we go through here, like I said, I use Versal to deploy. So you can see that everyone knows the package JSON file, TS config is for configuring TypeScript to do what we want it to do, and how we wanna do it and what features we need it to do. And then types, these are my types. I just named it index.d because apparently TSC when somebody told me somewhere somehow that it automatically detects it and it seems to work. So off to the races. So these are just simple modules to allow me to import SEG and PNG files into my React directly. Now, data, a lot of people ask about this.
7. App-Rite Client Setup and Provider Configuration
It's a simple wrapper to local storage that allows me to prefix any key I add. Local storage lives in the user's browser. Preferences, session, and settings are not used yet. I use Formik for forms and React hooks to set up providers. The main important provider is the App-Rite client, which I added to my package. Inside the provider, I create the client and add the endpoint and project ID. The project ID and API endpoint are set in the dashboard settings for Tessa Talks.
It's a simple wrapper to local storage is really all it is. I have a, again, style, but I have a little private function here that lives just in this file that allows me to basically prefix any key that I add. And then from then on now, it's just a key value store.
Let's see, local storage is right there. So this lives in the user's browser. Preferences is not used. Session is an extension just for naming sake and just for continuity, for lack of a better term. I imported the models and I export models.session into session just so that I can use session from inside my application that makes me feel scope happy. Settings also not used yet, but kind of the same thing. Well, it could be.
Next is your forms. Like I said, I use Formik. It's worked well for me, works nice. And it does the things that I needed to do. And here you're going to see some hooks. If you're not a familiar with hooks, I will also put links to everything that I'm using here from React Chakra Typescript, all those, I will put these links in the readme file for, after this for the project on the repositories that you can also see them. I use GitHub, I mean, I use React hooks. And that's what I've done. So these are all little hook things, and we're going to jump over there real fast to show you how I set up providers.
So inside of providers, the main important one is our App-Rite client. So what I did here was I created a hook or a provider, and that provider allows me to give my components who are the children of this component or to this provider, access to use application or an instance of the SDK. Like I said, you can see more on that on reactjs.org. But here's the main thing. I create, go down here, there it is right there. So I've added App-Rite to my package. So that guy is in here and ready to go. Go back to my provider that is API. And inside of here, and because I'm using it as a component, I named it TSX instead of TS, I create the client, and then I add the endpoint that I want to use and the project ID. Now, stopping right here to move back over to our dashboard, if I go here and I go to my settings for Tessa Talks, there's my project ID and there's my API endpoint. That's where I want my API to hit.
8. AppRite Project Configuration and Session Handling
We added apps for security purposes and to ensure requests are coming from trusted sources. The project ID and endpoint are essential for the SDKs to know where to go. I create a context and component to handle various functionalities like flash messages and navigation. The session provider determines if the user is logged in and directs them to the appropriate page. AppRite provides a well-structured data format, making it easy to access user information without additional encoding or decoding.
That's where, and that's also why when we go back to the project, we also added apps because for security sake, we want to make sure that it's coming from Localhost or it's coming from Vercel, or if it's coming from mycat.com or something. So it's part of the security and you can read more about that on appwrite.io, but project ID and the endpoint that you're going, you're telling the client that you want to hit because remember we're open source and we can live anywhere. So we got to know, so the SDKs have to know where to go.
Then I create a context. I create a component for that context and all it does is take children and put it there. Now I do this across quite a few things. Flash is just a pretty message that pops up at the top of your window. Navigation is just to set what page we're going to and where we're going to. And it's just to keep track of these things. Session is one that we actually use. And again, this is some of my boilerplate. So all of this may not be used. If I was going to put this into production and I wasn't, I would delete these things, but I just put, left them in there.
Session provider, so this is going to let us know if our user is logged in or not. And by letting the user be logged in or not logged in, will tell us what page they're going to go to and what layout to use, which we will get to next. So we have set session and session, but if you look here, if you've ever worked with Hooks or if you've ever worked with UState, you'll know that it usually just gives you the session and set session back zero as the variable that you're working with. And the second one is the function to set that variable of the state. But I made it with a little underscore under here. And the reason that I did that is because I wanted to use my own set session. And the reason I do that is because if the session is null, I want to go to that data wrapper for local host, and I want to delete it if it's null, because that means the user went away, either he logged out or what have you. And then I'm clearing it all out because if the user's not there, why do I need to keep his data? Or I want to set it to the session value.
One thing that AppRite does really well is the structure of the data that is returned. I don't have to do anything crazy to get it back. In fact, if we come over to the documentation, and then I go to account, then I create a session. There's the code, almost looks completely identical. I come over here to the session object and everything here is something that I can use right out of the box. There's no encoding. There's no having to use Stringify or decoding JSON scripts. It's all set up in a nice structure for us. So we very easily can get to the things that we want from client type to the user's name, device, all the good things.
9. Session and Provider Setup in index.tsx
In the current session, multiple ways and things can be authenticated across multiple devices. The index.tsx file contains all the necessary providers, including the session provider and the preferences provider. Preferences provide metadata for user accounts. Hooks provide a convenient way to access all these functionalities. The session is important for the index page to determine whether the user is logged in or not. If the session is null, the landing page is displayed; otherwise, the user page is shown.
In the current session, because you could be in multiple sessions, right? Maybe I also wanna link my Facebook account and maybe I wanna do this. So there's multiple ways and multiple things that could be authenticated across multiple devices. So if I'm on my iPhone for Tesla Talks and I'm also on the web, I should have multiple sessions and whichever one I'm currently interacting with or making this request should be the one that comes back with, hey, your website.
One cool thing that I really like about accounts is metadata. So preferences is already on this guy, we have preferences on a user. So if I wanted to use a user, let me get back up to it, this is also part of account, have prefs, preferences, which is a key value store, it's metadata to think about it. So I was wrapping that if you wanted to take the API, if you wanted to take the chat client a step further, then you would already have that, settings could also be a part of preferences or they're redundant. In this case, they're kind of redundant. So Hooks is just a convenience way for me to get to all of those from one single file. This is just pure developer laziness or my laziness and also because I liked the way it looks when it imports with curly braces and multiple things and a whole bunch of import lines.
So now the session, first off, let's go through why session was important to me. So here's index. So index can load one of two things. The flash message at the top is pretty, which is what you see here, but our main focus here is getting the user to log in, register, and then getting them to the application itself so that they can start chatting on Tessa Talk. So what we do here is we're using the hook that we wrapped everything in that provider to say, hey, session, and use session. So this should give us back the value of the current session based on the context that I created and wrapped everything in. Now, if that session is null, obviously the user's not logged in, so we're gonna use the landing page and then we're just gonna pass the rest of the props to it. If the user is logged in, then, of course, they're gonna want the user page and all good. And so all we're doing is returning this. The landing page looks just like a landing page.
10. Navigation and Login Page Layout
Navigation is easy. The login page is the same as the landing page, but with different content. The layout is automatically determined based on user authentication, simplifying the process and avoiding repetition.
There's not much to it. Navigation, easy enough. And then the login page is the exact same thing. There's your children, user to talk, and so on and so forth. And this the wrapper. So this is the, whenever you go to a landing page, say anywhere, and they have the pretty, why we're awesome, and then they have the little login box. They have the menu about us, contact us, and all that. You don't have the same thing when you log into a dashboard. So what I did was make it so I didn't have to worry about, if as long as the user is authenticated, it'll automatically use the layout for an authenticated user. And if they're not, they're automatically gonna use that. So that way I didn't have to copy and paste over and over again the same thing, or do a bunch of routing includes, just made it a little simpler.
11. Pages, Indexes, and Routes with AppRite
Pages, indexes, re-export. Register and login routes. No verification for quick access. Developer's choice with AppRite.
Now pages. Pages, indexes, simple re-export. Just like I said, curly brace pretties. Index itself inside of landing, there's your sub-router for register and your default route, which is login. So if you go to TessaTalks, you can register, will register and then automatically login. I didn't do verification, which absolutely can enable, I can send you an email link and we can make sure that you're you, but I wanted everybody to get in quick and I didn't want to collect email addresses. So, and that's me as a developer, I can make that choice with AppRite.
12. Introduction to Form Submission and API Calls
Now, let's talk about navigating between routes, forms, and API calls. The first API call is for creating a session when submitting the login form. AppRite provides a structured response that can be stored in local storage. The login page redirects back to itself, following a common practice. We've only made one API call so far, but now let's introduce the second API goal.
Now, simple stack layouts, let's get to talking. It's pretty, it's a thing. And then right away, it goes into, like I said, navigating between routes of register and logging in. Which takes us to our forms.
So first off, forgot passwords in there. So, so far we've made no API calls, one API call. But it's not really an API call, we were checking in sessions and local storage, but it's not. So we haven't technically made a full blown API call yet. So, here's our first. And it could be your first or your second, depending on the rhythm in which you walk.
So, here is the beauty of this. So I'll, I have a submit command here. If you're on the login form and you click submit, here's my first API call. API call, create session for the account, passing in the email and the password. And then I take and I set session the response. Remember when I showed you the response of what comes back that, AppRite does a phenomenal job of giving you a very nice structured piece of data. So that you know, I don't have to do any parsing out, I don't have to do anything else, I can put it right into my local storage, and then I'm gonna navigate right on over to, and there's the navigate hook, right on over to, Why can I do that slash?
So I come from a, I am a old man, I've been developing computers since I was eight years old in 1988 and some of the first websites in the late nineties, and whenever you submitted a form, you submitted it to yourself. And why did you do that? Because if there were errors, you wanted to display them. And so this became habit. So if you always redirect back to where you're at, well, this is the login page. So log in is going to redirect back to itself because remember what I did in the router and what I did in the layouts, for example, and they also in the router. So if we go to the router, you can see I did the exact same thing here. You use session, sessions equal to null. I'm gonna give you the landing page. Sessions equal to chat, all the things, and then we're just gonna pass it all to destination and call it a day. Easy peasy. And so far, we've still only really made one API goal and that's logging.
Now, let's, I'm not a registered user, so let's introduce our second API goal. So now, your art could be your first and logging would be your second depending on your flow. So now, and flash, like I said, it's the pretty thing at the top.
13. Account Creation and Chat Page
We're going to create your account with your email, password, and name. If there are any validation issues, a message will be displayed. After registration, the page will redirect to the home page, and any flash messages will be shown. We're focusing on building interfaces and user interactions, not servers and setup. The user is now logged in and ready to go to the chat page.
If you did Rails in the early 2000s and stuff, or even now, or even Express has a middleware for it and stuff, you'll know what flash is. Sometimes I still think of flash as an animation engine and sadness comes over me.
So, now what we're going to do is we're going to create your account. So you're gonna fill out your application, if there's any validation issues, if it's not valid, then it's going to present a little pretty message up at the top. And here we're going to do account, API.account.create. We're gonna create your account with your email, your password, and your name.
Now, for Test to Talk, your name is important because that's what's gonna show up on the side to say who's talking, but it's completely optional. This is just something I decided to do. And then I'm going to set a little message that says, hey, good job, your account's created. Or, if there was an error that came back, I'm gonna set error to e.message. And what that's going to do is it's going to display an error message over the form itself using hooks. Again, reactjs.org, if, and you can find out more about hooks if you haven't used them, but it's a simplified, more functional way of doing state management for various pieces of state. And that's it, so I register. It's gonna redirect me to the slash, and because I redirected the slash for everything, it automatically checks for the layout in the page, the destination that it's going to through the router and through the layout, hey, I need to share this one because there's no session, and I need to share this one because there's no session. And the layout says, oh, by the way, I have a message, a flash message, boom, I'm gonna show that. And this is all still React. This is all still web-based. This is, yeah, we've barely even done anything with the app right now, and that's a good thing because that means we are focusing on building the interfaces, building the user interactions. It's not focusing on building servers and setting up things.
So, so far, we're at two API calls, which is pretty impressive considering the amount of code that you've seen, the amount of setup, and all the weird style that I have. We have a valid authentication logging in and register system with two API calls. Third would be forgot password, but I didn't put that in there. So up next, the user is now presented. They've logged in, and they are ready to go. So we know what layout does, and now we're gonna head over to our chat page. So our chat page is a nice stack layout, as you can see at tesla.talks-app-write.vercells.app and say a message there. There's that message ID for the messages we have right over, boop, boop, boop, boop, right there. That's the messages ID. So that's the collection ID. Again, I could have given it any name I want to, but I just used unique because I didn't feel like filling in the box.
14. Session Hook and Message Sending
Now we use our session hook to check if there's a session available and set it if it's not. We have a user set user. Messages are the ones shown on the screen. Pending message records what you type until you hit enter. The API hook gives us access to the App-Write SDK. The third API call is to get the current user. If there's an error or the user is invalid, the session is set to null. We also have a function to send messages by creating a document with a unique ID.
It was really that simple. Now we use our session hook. So we know, we can check if there's a session available. We can set that session if it's not. We have a user set user. This is kind of a locally type thing.
Messages, these are all the messages we're gonna show on the screen. Pending message means, hey, you're typing stuff in and as you're typing, it's recording it to pending message. That's it. I just needed a temporary place to hold it until I could send it while you're continuously typing. So pending message is accruing your characters until you hit enter.
And then there's that guy again, number 32. API. Use API. So that's that hook that gives us access to an instance of the App-Write SDK. Now we're gonna have a quick little function called Get Users, an asynchronous function, and all this is going to do is make our, let's see, register, login, get user, or our third API call. That's it so far.
So third API call is we're gonna get the current user. So the account user. So the current session's user. And with that user, that's what I need to be able to present your message because I did this very easy. And I said, okay, now I'm gonna set the user as user.name because we get back this pretty formatted stuff. If it can't get an account, if there's an error, then there's something wrong because I don't have a user. That means that user's invalid or is no longer exists on the server, then that means maybe an admin deleted them because they were saying some not so nice things. Then I want to set that session to null, which if you remember in the hook, deletes the session, and it clears out all the data related to it.
Then I'm gonna have a second function, which is we're gonna send that message. In this message, we're gonna take the message out of that pending message state, we're going to then clear it so that your text box gets cleared again because you just hit enter, and that's what we expect. And then we're gonna create a document for the collection based on the message id or the collection message. And we're gonna make a unique id. You could also make this what you wanted, but I like unique because, well, it's unique.
15. Message Creation and Subscription
We have three attributes: user, message, and date. I made an API call for register, login, get user, and send a message. No backend or server code needed. Now, let's talk about Subscribe. It listens for every message created and calls get messages. It's simple and beautiful. We make an API call to get the messages using the SDK.
And then user, the user who is saying it, the message, the message that they're saying, and then the date in which it was created on. So let's go check out this real fast. So here's your messages, here's your attributes. And there's all three of them right there. Boom, that's it, I came over here, I created these three attributes. And over here, all I did was make this API call.
Now, we're at register, login, get user, send a message, that's four, so far, we're at four. So four API calls, no backends code, no server code, nothing. We clicked one time at DigitalOcean and we have this instance running. We ran one command line, we got Docker, we have a run local, and we're ready to go.
Here's where my favorite part is, and Torsten, who is also one of the members of Vaprite, is one of the masterminds behind this, and is one of the most beautiful APIs that I enjoy, and that is Subscribe. So now what I'm going to do is, I'm going to remember send messages in its own function, but Subscribe is not. What I'm going to do right now, is I wanna listen to every time a message is created. So every time a message is saved to my collection, I wanna call get messages. And then, that's all I wanna do. I made it as simple as possible.
So, here's my message ID again. Here's the documents of that message. And then here's the collections. This is the message collection, and then the documents of that collection. And then every time something happens to those documents, I'm gonna call get messages. So now, get messages. So, let's see, register, login, get user. What was the other one, send. So, we're at five. So, six, if you wanna call subscribing a function or an API call, let's do it, that's six. And then, seven is getting the messages themselves. So, I make an API call, and you don't see any HTTP, you don't see any REST, you're not using Axios or any of those main crazy things. We're just using the SDK right here, right now. And so, I'm going to call and get a list of documents based on that message ID that we set up top.
16. Building the Chat Service with AppWrite
I'm setting the user and message using a map function. The magic happens when effects are triggered for the first time. I added a loading screen for when there's no user. The form allows users to type and records their input. I can now run this chat service with minimal setup. AppWrite fits into my UI seamlessly, allowing me to focus on the frontend. I spent more time explaining UI development than AppWrite integration. It's that simple.
And then, I'm gonna set them, but then I'm gonna run this cool little map function because all I need out of there is the name, or the user, which is their name, and the message in which they're, what they said. So, that's all that we're doing right now. And then, if you know what effects are, presumably for everything to happen, then we're gonna trigger them the first time. So, this is the first time that this magic's gonna happen. I know you don't have to do it like this, but I did it like this.
Now, if there's no user, I just wanted to throw a little piece of clever in there and say, hey, there's a loading screen. But even on my DigitalOcean instance or our demo instance for AppRite, I've never seen it. So, it's been pretty cool. And then down here, we're displaying it. Now, topic was a thing of, I was trying to be more IRC-ish. Here's your form. It's literally prevent it and calling that function. And then we're binding the text field to the value of pending message. And every time there's a change on that text field, we're setting that message to the new value of that message. So, that allows the person to type and it's recording it. If they had delete, it removes it. And that's kinda it. Like, I can now run this with such a little setup. And I have a chat service. Like I said, you can see it at on testthetalk-apprite.versell.app. And I spent more time explaining in this workshop or in this presentation, I spent more time explaining how to write the UI, more about React and routing, and session handling, and storage, local storage, than I did AppWrite. And that's the point, is it fit into what I was already doing. So, I didn't have to think about how I was gonna authenticate a user, how I was gonna store a token, how I was gonna do OAuth2, or any of that stuff. All I had to do was write my UI and AppWrite fit into my UI like I wanted it to. And I wish there was, I wish it was easy. Like, there's really not much more to it. I wanted to sit down and have this big, grandiose talk about all the architecture, like that, but then I started building this, and I realized, again, that it was that simple. When I wrote the Flutter version, it's almost the exact same. I spent more time concentrating on building the UI, and building the interactions, and the animations, and the pretty, because I didn't have to worry about the backend anymore. And that's kind of the gist of it.
17. Logout Button and AppWrite Function
Now, what it is missing is a log out button. We could also have an app write function added to our provider. I can get sessions by ID and delete user sessions. I can make changes without managing migration files. We offer a command line tool that helps out.
Now, what it is missing is a log out button, which you would just call session set null, and it deletes it all. And what we could also do is have an app write function added to our provider, because this is, again, my style, but in here, whenever you set this to null, instead of just doing these two things, I could also jump over to my documentation, count. I can get sessions by ID. I can delete my user session, so I could delete that session as well, so it's no longer valid if the user comes back, and very easily add that. I can make changes without having to worry about managing migration files, because if you've ever done any Django or Rails or anybody else migration files and managing migrations and making sure that there's no collisions and so on and so forth, so that's kind of taking care of us for, if I wanted to write this all in Express, then I could use the Node.js SDK. We offer a command line tool that also helps out. And that's kind of it.