Shubham Shekhar
Posted on July 21, 2021
Code-Pair/Collaborative Coding is a trending topic in the landscape of remote-working/remote-hiring. In this post, We will discuss how we can build such a system on our own in less than 20 minutes.
What is Code-Pairing?
In Code-Pairing there are more than one users sharing the same code and editing it in real-time. Code-Pairing has lots of use-cases like helping a teammate, instructing interns/students, real time interviews etc. Possibilities are endless.
System Architecture
Lets take a look how the system architecture of such simplified system might look.
Tech Stack
Today we will talk about how we can build such a system, using some of the most popular tools in the current tech world. We are going to build this project in ReactJs but keep in mind end product can be achieved through any framework.
We will be using Monaco-Editor as our code editor. If you don't already know, Monaco-Editor is the same Editor which powers VSCode. Developed by Microsoft, is currently one of the most powerful opensource editor in market.
We will also be using Firebase's Realtime Database as backend.
We will be using an amazing library @hackerrank/firepad, This library will automatically take care of managing editor-state in Firebase automatically for us. Not only that but it also automatically highlight the cursor of each user and where exactly other users are typing.
Code it Out
Lets get started with the setup.
1. Create a new React Project.
npx create-react-app collaboratory
2. Install Dependencies
yarn add @hackerrank/firepad firebase@8.8.1 @monaco-editor/react monaco-editor
3. Add Editor
Lets add editor by modifying our App.js and lets start the developement server by npm start
.
import Editor from "@monaco-editor/react";
import {useRef,useState} from 'react';
function App() {
const editorRef = useRef(null);
const [editorLoaded,setEditorLoaded] = useState(false);
function handleEditorDidMount(editor, monaco) {
editorRef.current = editor;
setEditorLoaded(true);
}
return (
<div>
<Editor
height="90vh"
defaultLanguage="javascript"
theme="vs-dark"
defaultValue="// Welcome to My Editor"
onMount={handleEditorDidMount}
/>
</div>
);
}
export default App;
4. Setup Firebase.
If you already have firebase set up skip to next step.
Go to https://console.firebase.google.com/u/2/.
i. Create Firebase App
ii. Create Realtime Database
iii. Select Region 'United States',
Other regions can be choose as per your targeted region.
iv. Select 'Start in Test Mode'
v. Go to Project Settings
vi. Create an app.
Create an app from the bottom of General project settings.
vii. Register Firebase App Name
viii. Copy Firebase Configuration
Copy object next to firebaseConfig
5. Create a file firebaseConfig.js
and Paste copied Firebase config.
Create firebaseConfig.js
file in src
folder.
const firebaseConfig = {
apiKey: "#####################################", // important
authDomain: "############.firebaseapp.com", // important
databaseURL: "https://########.firebaseio.com", // important
projectId: "###########",
storageBucket: "#########.appspot.com",
messagingSenderId: "############3",
appId: "#############",
measurementId: "G-########"
};
export default firebaseConfig;
6. Initialize Firebase SDK
Import firebase sdk
import firebase from "firebase";
import firebaseConfig from './firebaseConfig';
Inside App.js, We do a initialization of firebase sdk
useEffect(() => {
if(!firebase.apps.length){
// Make sure initialization happens only once
firebase.initializeApp(firebaseConfig);
}
else{
firebase.app();
}
}, []);
7. Instantiate Firepad
Import Firepad Monaco Adapter
import {fromMonaco} from '@hackerrank/firepad';
We initialize firepad adapter for monaco
useEffect(() => {
if(!editorLoaded){
// If editor is not loaded return
return;
}
const dbRef = firebase.database().ref().child(`pair001`); // Can be anything in param, use unique string for unique code session
const firepad = fromMonaco(dbRef,editorRef.current);
const name = prompt("Enter your Name :"); // Name to highlight who is editing where in the code
if(name){
firepad.setUserName(name);
}
},[editorLoaded]);
That's It. We should be good to go. Open project localhost:3000 in two separate tabs/window and start typing in one. Other should update as well.
Final Code should look like the following.
import React {useRef,useEffect,useState} from 'react';
import Editor from "@monaco-editor/react";
import firebaseConfig from './firebaseConfig';
import firebase from "firebase";
import {fromMonaco} from '@hackerrank/firepad';
function App() {
const editorRef = useRef(null);
const [editorLoaded, setEditorLoaded] = useState(false);
function handleEditorDidMount(editor, monaco) {
editorRef.current = editor;
setEditorLoaded(true);
}
useEffect(() => {
if(!firebase.app.length){
firebase.initializeApp(firebaseConfig);
}
else{
firebase.app();
}
}, []);
useEffect(() => {
if(!editorLoaded){
return;
}
const dbRef = firebase.database().ref().child(`pair001`);
const firepad = fromMonaco(dbRef,editorRef.current);
const name = prompt("Enter your Name :");
firepad.setUserName(name);
},[editorLoaded]);
return (
<div>
<Editor
height="90vh"
defaultLanguage="javascript"
theme="vs-dark"
defaultValue="// Welcome to My Editor"
onMount={handleEditorDidMount}
/>
</div>
);
}
export default App;
Thank You have a nice day
About me
My name is Shubham Shekhar, I am a Software Developer, I have experience in ReactJs, Redux, NextJs, Material Ui, Bootstrap, Testing-Library, Jest, NodeJs, etc. I am highly focused towards learning new things and improving my way up. Feel free to contact me.
Github : https://github.com/Shubham567
Contact Me: shubhamshekhar567@gmail.com
Posted on July 21, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.