Code sharing is an essential aspect of . programming With the rise of remote work and virtual collaboration, developers need reliable tools for code sharing that offer real-time communication, video and audio conferencing, and a friendly user interface. is one such example. Codeshare.io But today, we're going to roll up our sleeves and build our very own code-sharing playground using . Buckle up! 🎢 Dyte is a developer-friendly platform that offers powerful SDKs to build live experiences within our product. In this blog, we will walk you through the process of building a code-sharing platform with Dyte.io and ReactJs. Let’s start! 🏃 Dyte.io Step 0: Setting up Dyte account Before anything, we would need to set up a Dyte account. For this, first visit Dyte.io and then hit Start Building. On the next page, Sign in with Google or GitHub account to get your free Dyte account 🎉. You will find your API keys under the API Keys tab on the left sidebar. Keep your API keys secure and don’t share them with anyone. Step 1: Setting up the environment Hitting one more checkpoint before we dive into coding. We will be using Node.js, a popular JavaScript runtime environment, and create-react-app, a tool that generates a React project with a pre-configured setup. To get started, we will create three folders , , and . client server plugin Note: 🧑💻 If you are on Mac, you should turn off “AirPlay Receiver” in System Settings as it occupied Port 5000 by default. Just for reference, this is how our would look like at the end of this blog. final folder structure We will go ahead and install CLI using the command below. Dyte $ npm install -g @dytesdk/cli Going ahead with the authorization part and selecting the organization with the following commands. $ dyte auth login $ dyte auth org For more information, visit . Dyte CLI Docs Step 2: Setting up a new Custom Plugin To start building a custom Dyte Plugin we will clone using the following command. Plugin template allows us to get started quicker. Dyte Plugin Template $ git clone https://github.com/dyte-in/react-plugin-template.git This template uses and allows us to create our own real-time plugins that work seamlessly with Dyte meetings. It has many interesting features to help us solve complex problems in minutes. Now, we will install the dependencies using the “npm install” command. @dytesdk/plugin-sdk $ npm install Next, we will add a couple of dependencies by running the following command. $ npm i @uiw/react-codemirror @codemirror/lang-javascript uuid Here, we are adding , which provides a pre-built Code Editor with language support. We are also installing UUID that will help us in generating UUIDs with just a function call. This will come in handy soon. react-codemirror Now that we have everything set up, we can use this command to start and test our Custom Plugin Setup. $ npm start Step 3: Trying out our new Custom Plugin To try using our new custom plugin, we will have to visit http://staging.dyte.io Here, we will be prompted to create a new meeting. It is super simple, just add your name and a meeting name and hit . On the next page, it will ask you to the meeting. Click on join and you’re in. Create join Find the button in the bottom-right corner, and click on it to reveal all existing plugins. We are interested in a plugin named, click on and it will reveal your plugin inside the meeting itself 🤯. Plugins launch We have everything ready with us. Now, we can get started with writing some actual code! Let’s begin with our Code Editor component. Step 4: Creating our Code Editor Let’s get started with creating our own code editor 🧑💻. For this we are going to first create a component and then use the package that we installed earlier. First, create a new in a file named inside and paste the following code. CodeMirror React Functional Component CodeEditor.js src/containers <CodeMirror style={{ fontSize: "32px", textAlign: "left" }} value={code} onChange={handleCodeChange} height="100vh" width="100vw" theme={'dark'} extensions={[javascript({ jsx: true })]}/> CodeMirror component provides a pre-built Code Editor. It comes with various syntax highlighting features. Step 5: Handling Code Changes To work on handling the live code changes, let's first create a new state named code import { useEffect, useState, useRef } from "react"; const [code, setCode] = useState("function add(a, b) { return a + b;}"); Now, we will create a function that will emit events whenever there is a change in our code in using function. handleCodeChange CodeMirror plugin.emit() Here, we are emitting an object, that has two properties. The first one is a randomly generated and the second one is our whole code. user id import { useEffect, useState, useRef } from "react"; import CodeMirror from '@uiw/react-codemirror'; import { javascript } from '@codemirror/lang-javascript'; const CodeEditor = ({ plugin }) => { const [code, setCode] = useState("function add(a, b) {return a + b;}"); const [userId, setUserId] = useState() const handleCodeChange = async (code) => { plugin.emit(`CODE_CHANGE`, { code, user }) } return ( <> <CodeMirror style={{ fontSize: "32px", textAlign: "left" }} value={code} onChange={handleCodeChange} height="100vh" width="100vw" theme={'dark'} extensions={[javascript({ jsx: true })]} /> </> ); } export default CodeEditor; Step 6: Listening to Code Change Events We need to listen to the event when other people change the code. For this, we will use the function as shown below. The function accepts as a parameter and receives the code changes. plugin.on() event name One more thing to note here is that we have to update our current code only if it is sent by other users. For this we need to put a simple conditional statement if(data.user != userId){} import { useEffect, useState, useRef } from "react"; import CodeMirror from '@uiw/react-codemirror'; import { javascript } from '@codemirror/lang-javascript'; import {v4} from 'uuid'; const user = v4() const CodeEditor = ({ plugin }) => { const [code, setCode] = useState("function add(a, b) {\n return a + b;\n}"); const [userId, setUserId] = useState() useEffect(() => { if (plugin) { const startListening = async () => { plugin.on(`CODE_CHANGE`, (data) => { if(data.user != user) { setCode(data.code) } }); } startListening() } }, [plugin]) const handleCodeChange = async (code) => { plugin.emit(`CODE_CHANGE`, { code, user }) } return ( <> <CodeMirror style={{ fontSize: "32px", textAlign: "left" }} value={code} onChange={handleCodeChange} height="100vh" width="100vw" theme={'dark'} extensions={[javascript({ jsx: true })]} /> </> ); } export default CodeEditor; In this component, we are creating a Code Editor using CodeMirror. Any changes to the editor emit an event to all users in the meeting, using function call. function takes and as arguments. CODE_CHANGE plugin.emit() emit eventName data In the next step, we need to import the CodeEditor component to file. Your file should look something like this. 👇 Main.tsx import { useDytePlugin } from '../context' import CodeEditor from './CodeEditor'; const Main = () => { const plugin = useDytePlugin(); return ( <div style={{ height: "100%" }}> <CodeEditor plugin={plugin} /> </div> ) } export default Main Code for our “Collaborative Code Editor Plugin” 😉 is now ready. How did someone write the first code editor without a code editor 😂? Jokes aside, we are ready with our Plugin 🎉. To checkout, open up and follow along. Enter your name and meeting title to get in. Hit join meeting. Open up the plugin and you are good to go. staging.dyte.io Localhost Dev Step 7: Publishing our Component 🧑💻 Now, it’s time to publish our content, this is a simple process with . For this we have to first build our plugin then run command. Dyte CLI dyte plugins publish $ dyte plugins create $ npm run build $ cp dyte-config.json ./build/dyte-config.json $ cd build $ dyte plugins publish Step 8: Getting started with our Code Sharing Platform Now that we have built the plugin which will help us collaborate on code, we can get started with building the platform to use this plugin on. Let's start with client side. Inside the folder, we will setup a new project using and create our react app using the following command. client ReactJS create-react-app $ npx create-react-app . Next, let us install the dependencies of and by running the following command: Dyte code-editor $ npm i @dytesdk/react-ui-kit @dytesdk/react-web-core react-simple-code-editor 🎬 Now, let’s start our development server with npm start: $ npm start Step 9: Building the Layout Let us open file inside the folder. We will remove the contents of this file and add the following code snippet 👇. app.js src import Layout from './components/Layout' function App() { return ( <Layout /> ); } export default App; Next, we will write the component, we will be creating a layout with our logo, title and meeting UI. Layout We will use several libraries, including and PrismJS, for building a collaborative code editor and meeting UI. DyteMeeting import Meet from "./Meeting" const Layout = () => { return ( <> <div style={{ padding: "30px", display: "flex", justifyContent: "space-between", alignItems: "center" }}> <img src="https://dyte.io/blog/content/images/2021/09/Dyte-Logo.svg" height={"70px"}/> <span style={{ fontSize: "30px", color: "#3e75fd" }}>Collaborative Code Editor</span> <img style={{ opacity: "0"}} src="https://dyte.io/blog/content/images/2021/09/Dyte-Logo.svg" height={"80px"}/> </div> <div style={{ height: "88vh" }} ><Meet /></div> </> ) } export default Layout Step 10: The Meeting Component 🧑💻 First, we need to create a few utility functions in a file client/src/utils/api.js const createMeeting = async () => { const resp = await fetch("http://localhost:3000/meetings", { method: "POST", body: JSON.stringify({ title: "New Code pair" }), headers: { "Content-Type": "application/json" } }) const data = await resp.json() console.log(data) return data.data.id; } const joinMeeting = async (id) => { const resp = await fetch(`http://localhost:3000/meetings/${id}/participants`, { method: "POST", body: JSON.stringify({ name: "new user", preset_name: "group_call_host" }), headers: { "Content-Type": "application/json" } }) const data = await resp.json() console.log(data) return data.data.token; } export { createMeeting, joinMeeting } These functions talk to our backend to create meetings and add participants. For meeting creation, we pass as an optional parameter. title And for adding participants, we pass parameter (optional), parameter (optional), and parameter (required) along with . name picture preset_name meetingId Time for our Meeting component. For this, we will use Dyte UI kit ✨ which makes it super easy to integrate live Audio/Video sharing in your application. Yes, these 10-15 lines of code do all the heavy lifting 🏋🏼♂️. import { useState, useEffect, useRef } from "react"; import { DyteMeeting, provideDyteDesignSystem } from "@dytesdk/react-ui-kit"; import { useDyteClient } from "@dytesdk/react-web-core"; import { createMeeting, joinMeeting } from "../utils/api"; const Meet = () => { const meetingEl = useRef(); const [meeting, initMeeting] = useDyteClient(); const [userToken, setUserToken] = useState(); const [meetingId, setMeetingId] = useState(); const createMeetingId = async () => { const newMeetingId = await createMeeting(); setMeetingId(newMeetingId); }; useEffect(() => { const id = window.location.pathname.split("/")[2]; if (!id) { createMeetingId(); } else { setMeetingId(id); } }, []); const joinMeetingId = async () => { if (meetingId) { const authToken = await joinMeeting(meetingId); await initMeeting({ authToken, modules: { plugin: true, devTools: { logs: true, plugins: [ { name: "Collaborative-code-editor", port: "5000", id: "<your-plugin-id>", }, ], }, }, }); setUserToken(authToken); } }; useEffect(() => { if (meetingId && !userToken) joinMeetingId(); }, [meetingId]); useEffect(() => { if (userToken) { provideDyteDesignSystem(meetingEl.current, { theme: "dark", }); } }, [userToken]); return ( <> {userToken && meetingId ? ( <DyteMeeting mode="fill" meeting={meeting} ref={meetingEl} /> ) : ( <div>Loading...</div> )} </> ); }; export default Meet; We are ready with our Code Sharing Platform's UI now 🎉 Step 11: Getting the Backend Ready 🧑💻 Dyte provides a variety of powerful APIs that enhance the developer experience and meet a wide range of developer requirements. We can manage Dyte’s organizations, sessions, meetings, recordings, webhooks, live streaming, analytics, and much more. To simplify the process, we will use Express with Node to create a backend which will help with authentication, meeting creation, and adding participants. ✨ To get started in the project folder, follow the following steps: $ mkdir server && cd server We’ll start with installing a couple of dependencies, cd into the 'server' directory, and use the following command. $ npm init -y $ npm install express cors axios dotenv $ npm install -g nodemon First, let's create a file to store our API key in . You can find these keys on Dyte Dashboard. .env server/src DYTE_ORG_ID=<ID> DYTE_API_KEY=<KEY> Let’s also add a few scripts ✍️ that will help us run our application. Add the below lines in your file inside the tag. server package.json scripts "start": "node dist/index.js", "dev": "nodemon src/index.js" Let's create our files and folders now. All our code will live inside the folder. Inside create another folder . server/src src utils Initialize a file inside and inside . Now let’s add our file in , which will hold our API secrets. index.js src dyte-api.js utils .env src Open up file and add the following lines to it. Replace the placeholder values with the API secrets from the Dyte Dashboard. src/.env DYTE_ORG_ID=<YOUR-DYTE-ORG-ID> DYTE_API_KEY=<YOUR-DYTE-API-KEY> We can start writing code now. Let’s start with creating config for accessing Dyte APIs. axios Open up and put in the following code. utils/dyte-api.js This code will help to communicate with Dyte APIs and authentication. const axios = require('axios'); require('dotenv').config(); const DYTE_API_KEY = process.env.DYTE_API_KEY; const DYTE_ORG_ID = process.env.DYTE_ORG_ID; const API_HASH = Buffer.from( `${DYTE_ORG_ID}:${DYTE_API_KEY}`, 'utf-8' ).toString('base64'); const DyteAPI = axios.create({ baseURL: 'https://api.cluster.dyte.in/v2', headers: { Authorization: `Basic ${API_HASH}`, }, }); module.exports = DyteAPI; Next, we will write the routes. Our front end will communicate on these routes to create meetings and add participants to meetings. Let's open up and add the following code snippet.👇 index.js const express = require('express'); const cors = require('cors'); const DyteAPI = require('./utils/dyte-api') const PORT = process.env.PORT || 3000; const app = express(); app.use(cors("http://localhost:3001")); app.use(express.json()); app.post('/meetings', async (req, res) => { const { title } = req.body const response = await DyteAPI.post('/meetings', { title, }); return res.status(response.status).json(response.data); }); app.post('/meetings/:meetingId/participants', async (req, res) => { const meetingId = req.params.meetingId const { name, picture, preset_name } = req.body const client_specific_id = `react-samples::${name.replaceAll(' ', '-')}-${Math.random().toString(36).substring(2, 7)}`; const response = await DyteAPI.post(`/meetings/${meetingId}/participants`, { name, picture, preset_name, client_specific_id, }); return res.status(response.status).json(response.data); }); app.listen(PORT, () => { console.log(`Started listening on ${PORT}...`) }); Ta-da! 🎩✨ We did it! Now, we'll finally try out our code-sharing platform to collaborate while coding with our friends and teammates. With our shiny new Code editor and Dyte meeting all setup, we’ll finally try out our platform! To run the whole application locally: Inside client type PORT=3001 npm start Inside plugin type npm start Inside server type PORT=3000 npm run dev And there you have it, in-app video conferencing and collaboration with our own “Code Collaboration Plugin”. 🧑💻 You can try out the code-sharing platform . here Conclusion 🎉 Woohoo! You've made it to the end, my friend! I hope you've learned a thing or two today and had a good time following along the way. Together, we've built up a snazzy live pair programming and code-sharing platform, complete with in-app meetings, all with just a pinch of React and a dollop of Dyte. Talk about a recipe for success! We’ve got your back with our plugin templates and powerful SDKs, making it a breeze to jump right in and build your own collaborative masterpieces, just like the one we cooked up together today. So what are you waiting for? Head on over to and let your creative juices flow! Start building your own collaborative applications and you might just create the next big thing! 🚀 Dyte.io