Building a Google Docs Clone with Firebase and Vanilla JavaScript
Structuring a Firestore Database
To begin, let’s structure a Cloud Firestore Database. We’ll create a new Firebase project and configure Google Analytics. Then, we’ll create a collection called “Docs” with fields for the user’s name, content, created timestamp, and updated timestamp. Each document will have a unique identifier generated from an authenticated user.
// Create a new Firestore collection
firebase.firestore().collection("Docs").doc().set({
userName: "",
content: "",
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
updatedAt: firebase.firestore.FieldValue.serverTimestamp()
});
Enabling Firebase Google Authentication
Next, we’ll enable Firebase Google Authentication in our Firebase project. This will allow users to sign in with their Google accounts. We’ll add Firebase to our project, register the app, and copy the project config.
// Initialize Firebase
var config = {
apiKey: '',
authDomain: '',
projectId: ''
};
firebase.initializeApp(config);
Project Setup
Now, let’s set up our project files. We’ll create files for signup.html
, signup.css
, firebase.js
, and code.auth.js
. We’ll add Firebase to our project and implement Google authentication.
Creating a Basic Text Editor
We’ll create a basic text editor that allows users to type and edit text. We’ll use the contenteditable
attribute to turn a div into an editable text field.
Implementing Text Formatting
We’ll create functions to implement text formatting features. For example, the bold function will format highlighted text as bold.
// Bold function
function bold() {
document.execCommand("bold");
}
// Italic function
function italic() {
document.execCommand("italic");
}
// Unordered list function
function unorderedList() {
document.execCommand("insertUnorderedList");
}
// Ordered list function
function orderedList() {
document.execCommand("insertOrderedList");
}
Saving a User Document to Cloud Firestore
When a user creates a document, we’ll save it to Cloud Firestore. We’ll listen to the editable div and get the value as the user types. Then, we’ll use the Firebase set()
method to save the document to Cloud Firestore.
// Get the editable div
const editor = document.getElementById("editor");
// Listen to changes in the editor
editor.addEventListener("input", () => {
const content = editor.innerHTML;
// Save the document to Cloud Firestore
firebase.firestore().collection("Docs").doc().set({
content: content,
updatedAt: firebase.firestore.FieldValue.serverTimestamp()
});
});
Retrieving a User’s Document from Cloud Firestore
To retrieve a user’s document, we’ll implement a dashboard page with a button that takes the user to the editor page. We’ll query Firestore using a collection reference and loop through the object to display the actual data.
// Get the dashboard button
const dashboardBtn = document.getElementById("dashboard-btn");
// Add event listener to the button
dashboardBtn.addEventListener("click", () => {
// Query Firestore for the user's documents
firebase.firestore().collection("Docs")
.where("userName", "==", firebase.auth().currentUser.displayName)
.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
console.log(doc.data());
});
});
});
Online and Offline Editing
Finally, we’ll implement online and offline editing. We’ll use the navigator.online
property to check if the user is online or offline. If the user is online, we’ll send the document to Cloud Firestore. If the user is offline, we’ll save the document to local storage.
// Check if the user is online or offline
if (navigator.onLine) {
// Send the document to Cloud Firestore
firebase.firestore().collection("Docs").doc().set({
content: editor.innerHTML,
updatedAt: firebase.firestore.FieldValue.serverTimestamp()
});
} else {
// Save the document to local storage
localStorage.setItem("document", editor.innerHTML);
}