Regardless of the aspect of education you’re involved in, there’s no doubt that everyone’s busy. From deadlines for applications, assignments, and grades to campus events and program coordination — it’s a lot to manage. In response, many schools are choosing to offer live chat support. Using synchronous support channels allows schools to answer questions and quickly deliver information to their communities.
This tutorial demonstrates how to use Appwrite’s Pink Design feature to create a real-time classroom chat with Next.js.
GitHub
Check out the complete source code here.
Prerequisites
The following are required to follow along:
- Knowledge of JavaScript and React.js.
- A Docker Desktop installation; run the
docker -v
command to verify the installation. If not, install it from the Get Docker documentation site. - An Appwrite instance running on our computer. Check out this article to create a local Appwrite instance; we will use Appwrite’s robust database and Realtime service to manage our application.
- Experience with Next.js is advantageous but not required.
Creating a Next.js project
To create a Next.js project, perform the following steps:
- Open a terminal and run this command line to scaffold a Next.js app:
npx create-next-app classroom-chat
- Go to the project directory and start the development server on
localhost:3000
with this command:
cd classroom-chat && npm run dev
Getting started with Pink Design
Pink Design is an open-source system from Appwrite used to build consistent and reusable user interfaces. It enhances collaboration, development experience, and accessibility.
We can integrate Pink Design into a project via a content delivery network (CDN) or Node Package Manager (NPM). In this tutorial, we’ll use NPM.
To install Pink Design, open a terminal in the project directory and run the following command:
npm install @appwrite.io/pink
To use Pink Design in our project, import it into your project’s JavaScript files like this:
import "@appwrite.io/pink";
Installing dependencies
Installing unique-username-generator
This package helps generate a unique username from randomly selected nouns and adjectives. To install the unique-username-generator in our project, we run these terminal commands.
npm install unique-username-generator --save
Installing Appwrite
Appwrite is a development platform that provides a powerful API and management console for building backend servers for web and mobile applications. To install it, run the command below:
npm install appwrite
Setting up Appwrite
To get started, we need to log in to our Appwrite cloud console, click the Create project button, input realtime-chat
as the name, and then click Create.
Create a database, collection, and add attributes
With our project created, we can set up our application database. First, navigate to the Database tab, click the Create database button, input classroom-chat
as the name, and then click Create.
Secondly, we need to create a collection for storing our products. To do this, click the Create collection button, input chat_collection
as the name, and then click Create.
Thirdly, we need to create attributes to represent our database fields. To do this, we need to navigate to the Attributes tab and create attributes for each of the values shown below:
Attribute key | Attribute type | Size | Required |
---|---|---|---|
username | String | 500 | YES |
messages | String[] | 500 | YES |
Lastly, we need to update our database permission to manage them accordingly. Navigate to the Settings tab, scroll to the Update Permissions section, select Any
, mark accordingly, and then click Update.
Building the chat interface
Our chat application will have one page: a mobile-sized chat app with a video, top menu, message, and input where the user will type. Create this chat application with the GitHub gist below:
From the gist below, we have the src/pages/index.js
.
In the index.js
, we did the following:
- Imported required dependencies and components
- Added a video at the top of the chat app
- Implemented state variables that store (1) the messages, which contain a list of all messages sent and received, and (2) usernames, which is the array holding the user typing in the document
- Top Menu: This contains the application title and a section to show who is currently typing
- Input: This contains the text field to input messages and the send button
At this point, our application should look like so:
Creating an anonymous user session
Appwrite requires a user to sign in before reading or writing to a database to enable safety in the application. However, we can create an anonymous session that we'll use in this project. We'll do so in the web-init.js
file.
// Init your Web SDK
import { Client, Account, Databases } from "appwrite";
export const client = new Client();
client
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("641858468a39ef152488");
const account = new Account(client);
const database = new Databases(client);
export const createAnonymousSession = async () => {
try {
await account.createAnonymousSession();
} catch (err) {
console.log(err);
}
};
Generating random username
Next, we need to generate a random username for each user typing the message input using our installed unique-username-generator
package. First, import the dependency into the src/pages/index.js
file.
import { generateUsername } from "unique-username-generator";
Then write a conditional statement to check for the current “user” on the mount of our application using the React useEffect()
Hook.
useEffect(() => {
if (!username) {
const _username = localStorage.getItem("username") || generateUsername();
localStorage.setItem("username", _username);
setUsername(_username);
}
}, [username]);
The code snippet above checks that the username does not already exist, and it should generate a username and store the username in localStorage
.
Creating database documents
Next, we need to create a chat document that stores our list of users in the username
attribute. In the src/page/index.js
file, write a createChatIfNotExist()
function to create the document if it does not exist. For simplicity, we'll keep the id
as general chat.
const createChatIfNotExist = async (e) => {
console.log("Adding user", message);
const promise = databases.createDocument(
"6418bf5a278b4799614b",
"6418bf6c38a6c826cc21",
"general-chat",
{
username: username,
messages:[...messages,message]
}
);
promise.then(function (response) {
console.log("runnner", response); // Success
}, function (error) {
console.log(error); // Failure
databases.updateDocument(
"6418bf5a278b4799614b",
"6418bf6c38a6c826cc21",
"general-chat",
{
username: username,
messages:[...messages,message],
}
);
});
};
The createChatIfNotExist
function above does the following:
- The
createDocument()
method creates a document using the collection ID and data fields to be stored. This collection ID is the same ID we copied from our Permissions page earlier. - Uses the Appwrite
updateDocument()
method to update thegeneral-chat
document ID.
Subscribing to updates on the document
When the user sends a message from the input field, the page sends a real-time request to listen to any events on the server side. This is broadcast to everyone as an event in real-time using the subscribe method.
useEffect(() => {
const _subscribe = client.subscribe(
"databases.6418bf5a278b4799614b.collections.6418bf6c38a6c826cc21.documents",
(response) => {
console.log("iiiii",response);
const { payload } = response;
if (payload?.$id === "general-chat") {
setMessages(payload.messages);
}
}
);
return () => {
_subscribe();
};
}, []);
In the code snippet above, we did the following:
- Subscribed to a channel using Appwrite's subscribe method, which receives two parameters: the channel we subscribe to and a callback function. To learn more about the various channels we can subscribe to, check out Appwrite's Realtime Channels.
Our chat app should look like this by now:
Conclusion
This article discussed using Appwrite’s Pink Design and a real-time feature to subscribe to application events on a classroom chat application.