Create a chat app
In this tutorial you will build a browser chat application using Earthstar.
Table of contents
- Overview
- Setting up
- Writing chat messages to a Replica
- Reading messages from the replica
- Going online
- Summary
Overview
A basic knowledge of HTML, JavaScript, and using the terminal will be helpful in completing this tutorial.
Other tools you will need:
- A text editor
- A web browser
- A static file server
If you don't have a static file server yet, you can follow the instructions below.
Instructions for installing a static file server
- Install Deno.
- In your terminal, run
deno install --allow-net --allow-read https://deno.land/std@0.167.0/http/file_server.ts
Proceed once you have all of the above.
Setting up
- Create a new directory on your filesystem for this project and name it something like
chat-app
. - Inside this directory, create a new file named
index.html
. - Alongside that file, create another file named
chat.js
.
Writing the HTML
Open the index.html
file you created in your text editor, and enter the following text:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Chat App</title>
</head>
<body>
<ul id="messages"></ul>
<form id="message-form">
<input type="text" name="message-input">
<button>Send</button>
</form>
<script src="./chat.js" type="module" async></script>
</body>
</html>
Starting the JavaScript
Open the chat.js
file created earlier in your text editor, and enter the following text:
import * as Earthstar from "https://cdn.earthstar-project.org/js/earthstar.web.v10.2.2.js";
alert("Everything is set up!");
Making sure it works
Now we will verify that we have set up everything correctly.
- If you followed the static file server instructions above, you can run
file_server ./chat-app
. Otherwise, open the directory you created for this project with your static file server of choice. - Open your web browser, and navigate to http://localhost:4507 (or whichever address your static file server is running on).
- If you have followed all instructions correctly, you will see an alert with the text 'Everything is set up!'. If you do not see this, check that you have followed the instructions correctly. Check the developer tools of your browser, which may be able to help you determine what the problem is.
Writing chat messages to a Replica
We will now write some JavaScript to write the contents of the text input to an Earthstar Replica whenever the 'Send' button is pressed.
Listening for events
Firstly we will write some Javascript which listens for events on form submission, and logs a message to the console.
Modify chat.js
with the following contents:
import * as Earthstar from "https://cdn.earthstar-project.org/js/earthstar.web.v10.2.2.js";
const form = document.getElementById("message-form");
const input = document.querySelector("input");
form.addEventListener("submit", (event) => {
// This stops the page from reloading.
event.preventDefault();
console.log(input.value);
});
Reload your chat app, type something in the input, and click the send button. You will see the message you typed in the console.
Writing to a replica
Now we will take messages typed into the form and write them to an Earthstar Replica.
Modify chat.js
with the following contents:
import * as Earthstar from "https://cdn.earthstar-project.org/js/earthstar.web.v10.2.2.js";
const shareKeypair = await Earthstar.Crypto.generateShareKeypair("chatting");
const authorKeypair = await Earthstar.Crypto.generateAuthorKeypair("test");
if (Earthstar.notErr(shareKeypair) && Earthstar.notErr(authorKeypair)) {
console.group("Share keypair");
console.log(shareKeypair);
console.groupEnd();
console.group("Author keypair");
console.log(authorKeypair);
console.groupEnd();
} else if (Earthstar.isErr(shareKeypair)) {
console.error(shareKeypair);
} else if (Earthstar.isErr(authorKeypair)) {
console.error(authorKeypair);
}
const form = document.getElementById("message-form");
const input = document.querySelector("input");
form.addEventListener("submit", (event) => {
// This stops the page from reloading.
event.preventDefault();
console.log(input.value);
});
Reload the page and copy the values from the browser. We want to keep reusing them even after the page has refreshed.
With these values we can instantiate an Earthstar Replica and write data to it. Modify chat.js
again:
import * as Earthstar from "https://cdn.earthstar-project.org/js/earthstar.web.v10.2.2.js";
// Use the values for shareKeypair which were logged to your console.
const shareKeypair = {
shareAddress:
"+chatting.bffblffbnzrjeqmh3s3vnuvztfibnzuex3e5h4nthsq7dum4mnlra",
secret: "b4wghljrl4f4e7tedrggn72gyqvqyeqvlg6u5usi6nijwyrukbena",
};
// Use the values for authorKeypair which were logged to your console.
const authorKeypair = {
address: "@test.bozdi5jngr2yztz5ue6qnvqpeq5flm6gpuqajikngp3wjolabgmaa",
secret: "byrp2eqpjzdmaxllybrbrtblb54bmuwbl26n6hrfendg72zcxsduq",
};
const replica = new Earthstar.Replica({
driver: new Earthstar.ReplicaDriverWeb(shareKeypair.shareAddress),
shareSecret: shareKeypair.secret,
});
const form = document.getElementById("message-form");
const input = document.querySelector("input");
form.addEventListener("submit", async (event) => {
// This stops the page from reloading.
event.preventDefault();
// Write the contents of the message to the replica.
const result = await replica.set(authorKeypair, {
text: input.value,
path: `/chat/~${authorKeypair.address}/${Date.now()}`,
});
if (Earthstar.isErr(result)) {
console.error(result);
}
input.value = "";
});
Reading messages from the replica
We will now read data back out of the replica so that we can display the messages we've entered.
Add the following to chat.js
:
import * as Earthstar from "https://cdn.earthstar-project.org/js/earthstar.web.v10.2.2.js";
// Use the values for shareKeypair which were logged to your console.
const shareKeypair = {
shareAddress:
"+chatting.bffblffbnzrjeqmh3s3vnuvztfibnzuex3e5h4nthsq7dum4mnlra",
secret: "b4wghljrl4f4e7tedrggn72gyqvqyeqvlg6u5usi6nijwyrukbena",
};
// Use the values for authorKeypair which were logged to your console.
const authorKeypair = {
address: "@test.bozdi5jngr2yztz5ue6qnvqpeq5flm6gpuqajikngp3wjolabgmaa",
secret: "byrp2eqpjzdmaxllybrbrtblb54bmuwbl26n6hrfendg72zcxsduq",
};
const replica = new Earthstar.Replica({
driver: new Earthstar.ReplicaDriverWeb(shareKeypair.shareAddress),
shareSecret: shareKeypair.secret,
});
const form = document.getElementById("message-form");
const input = document.querySelector("input");
form.addEventListener("submit", async (event) => {
// This stops the page from reloading.
event.preventDefault();
// Write the contents of the message to the replica.
const result = await replica.set(authorKeypair, {
text: input.value,
path: `/chat/~${authorKeypair.address}/${Date.now()}`,
});
if (Earthstar.isErr(result)) {
console.error(result);
}
input.value = "";
});
// Read messages from chat.
const messages = document.getElementById("messages");
const cache = new Earthstar.ReplicaCache(replica);
function renderMessages() {
messages.innerHTML = "";
const chatDocs = cache.queryDocs({
filter: { pathStartsWith: "/chat" },
});
for (const doc of chatDocs) {
const message = document.createElement("li");
message.textContent = doc.text;
messages.append(message);
}
}
cache.onCacheUpdated(() => {
renderMessages();
});
renderMessages();
Now when you enter messages they will be rendered above the message input. The messages will also persist between browser sessions.
Going online
Our chat application works, but it only allows us to talk to ourselves. We can enable online communication by adding three lines to the end of chat.js
:
const peer = new Earthstar.Peer();
peer.addReplica(replica);
peer.sync("https://my.server", true);
This won't work because there is no Earthstar server at https://my.server
. Fortunately we have a tutorial for running an Earthstar server.
Make sure your browser allows Earthstar to save data
In your browser settings you may need to add an exception for your local Earthstar server, so that your application can access it and store data on it.
Firefox: go to "Settings -> Privacy & Security -> Cookies and Site Data -> Manage Exceptions..." and add the local Earthstar server address.
Summary
We've created a simple chat app which works in the browser, and uses Earthstar to persist and sync data.
- We imported the Earthstar module via a CDN.
- We generated a share keypair using the
Earthstar.Crypto
API. - We generated an author keypair using the
Earthstar.Crypto
API. - We used the
Replica
API to create a copy of the share's data to query from and write to. - We listened for form submission events and wrote data to the replica using the author keypair we generated.
- We subscribed to documents for a specific query using the
ReplicaCache
API and used the documents' contents to render an interface. - We learned how we could start syncing data with other users using the
Peer
API.
Further exercises
- If you've followed the tutorial for running a replica server, can you update this chat app to sync with it?
- Can you update the
renderMessages
function so that we can see who wrote which message? You may findEarthstar.parseAuthorAddress
useful. - Rather than hardcoding the share and author keypairs into the chat itself, can you refactor this app to use the
Earthstar.SharedSettings
API?