Home > Blog > For Developers
Taking place every year at University of Ottawa, uOttaHack is an event where students, developers, and tech enthusiasts come together to collaborate on coding projects, solve real-world problems, and build innovative software or hardware solutions over the course of 36 hours. This year’s winning team recaps their award-winning project…
Motivation
Our goal coming into uOttaHack was to build a tool that pushes the boundaries of collaboration. Upon seeing the Solace challenge, we decided to take the approach of a collaborative document editor to leverage PubSub+ Event Broker.
Design
After brainstorming our idea, the next step was to choose the tools we were going to use. Since we wanted the project to be a web application, we went with SvelteKit for the full stack due to its granular reactivity with Svelte 5 runes and simple integration with a backend, PostgreSQL for document persistence and user management, and Solace PubSub+ Event Broker to synchronize changes to other users in real time.
Solace PubSub+ Cloud
To work effectively with PubSub+ Cloud, we leveraged PubSub+ Event Portal to help us define events, schemas, applications, and how they all connect together. Here’s how it all works:
Taking the extra steps to design our infrastructure from the beginning saved us from many bugs in our networking, giving us more leeway to add any extra features we could think of, all of which were built on top of this initial design.
For example, here’s our topic hierarchy for document edit subscriptions from clients:
Implementation
Our first focus was to create a functional but simple text editor with no networking. During hackathons, we focus on functionality first, then complete additional stretch goals when we feel satisfied with our initial proof of concept. Creating the document editor itself involved using the contenteditable attribute and adding some additional functionality on top, like text sizing, weight, and positioning.
<div bind:this={editorElement} contenteditable="true" class="h-full min-h-screen w-full break-words rounded border bg-white p-24 opacity-100 focus:outline-none" bind:innerHTML={editorContent} oninput={onInput} spellcheck="false" onclick={onClick} onkeydown={onKeyDown} ></div>
Once the basics were implemented, we set up our Event Broker on Solace Cloud and designed the topic hierarchy, events, and schemas that we wanted to use. Then, we used the solclientjs
library and wrapped it to easily perform the most common tasks we were going to use, such as publishing to a topic and subscribing to a topic. From there, we simply networked all of the possible changes and updated them on the other side.
As a bonus, we integrated multiple AI features like transcriptions, voice commands with document context (RAG), and image alt text generation.
Using the Client
Creating and managing the client was easy, which allowed us to focus on important problems within our application.
export const client = new Client({ url: PUBLIC_SOLACE_URL, vpnName: PUBLIC_SOLACE_VPN_NAME, userName: PUBLIC_SOLACE_USERNAME, password: PUBLIC_SOLACE_PASSWORD }); client.subscribe(‘document/{id}/update’, …);
Struggles
As with most hackathon projects, we began running into some hurdles. Properly syncing the document with all users was a major challenge, with this issue coming up multiple times whenever any large additions were made. Fortunately, after some trial and error we were able to get the syncing to a point we were content with, and that could facilitate the collaboration we were looking for.
Proximity Voice Chat
Communicating with speech is often the easiest way to get information across quickly. To support our goal of pushing the boundaries of collaboration, we implemented proximity voice chat. This required two key pieces:
- A way to determine which users should hear your voice
- Transmitting and receiving audio input in real time
We wanted proximity to be calculated based off of the line number in the document, so we networked line changes to allow users to know who is in their vicinity. Then, we transmitted PCM audio using the topic document/{documentId}/proximity
and filtered the out-of-range users client-side.
Using the broker to transmit binary was very easy, and attaching additional non-binary user data simply required us to set a User Data payload:
const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); const audioContext = new AudioContext(); const source = audioContext.createMediaStreamSource(stream); const processor = audioContext.createScriptProcessor(4096, 1, 1); source.connect(processor); processor.connect(audioContext.destination); processor.onaudioprocess = (event) => { const inputBuffer = event.inputBuffer; const rawData = inputBuffer.getChannelData(0); solace.publish( `95ers/document/${documentId}/proximity`, rawData.buffer, JSON.stringify({ userId: user.id, line }) ); };
What we Made and Learned
In the end, we made a fully functional document editor with rich content editing, real-time collaboration, proximity chat, and packed it with AI features in under 20 hours.
You can see it in action here or check it out on GitHub.
Authors
Matthew Polak is a 3rd year Computer Science student at the University of Ottawa. He is interested in networking and game development.
Raef Sarofiem is a third-year Computer Science student attending Carleton University. He’s interested in robotics and artificial intelligence.
Robert Zuchniak is currently attending the University of Ottawa and in his third year of Computer Science. He is passionate about web and game development, as well as deployment technologies.
Vasil Topalovic is a Computer Science student in his 3rd year of studies at the University of Ottawa. His interests lie in compiler and video game development.
Explore other posts from category: For Developers
The Solace Developer Community is the technical community for Solace PubSub+. It is the place where community members from all backgrounds and experiences socialize, share resources, organize projects together, and help each other. If you haven't already signed up for it, we encourage you to do so now and get involved in the action!
Subscribe to Our Blog
Get the latest trends, solutions, and insights into the event-driven future every week.
Thanks for subscribing.