In their first week with Commit, each new Engineering Partner takes on a hackathon onboarding project. They build a project, present it to the Commit community, and write a short summary of their experience. There are no restrictions, no limits.
For my hackathon onboarding project I took the opportunity to develop an app that I could use myself, while learning technologies that I’d been wanting to try out for ages. You can check out the result on my GitHub.
My partner and I share a Notion page for our grocery list that we both update throughout the week on our desktop PCs, then check on our phones while we’re out grocery shopping. Notion is great for organizing notes and real-time collaboration, but I find myself cursing its sluggish mobile app when I’m standing in the middle of the grocery store waiting for it to load.
I wanted to create a simple, blazing-fast “Notion-lite” that would let you make easily shareable notes and collaborate in real time, with no account required. Of course, the experience also had to be seamless between web and mobile. Thus, Sharenotes was born.
I used React and Next.js on the front end. I’m pretty experienced with React, but I’ve always used Create React App instead of Next.js to bootstrap my React projects. I’d always heard good things about Next.js, and its server-side rendering was handy for fetching the latest data before rendering the note. Next.js also provides an easy way to make your project into a progressive web app (PWA). That took care of the mobile version fairly easily.
For the back end, I used the classic Node.js + Express.js combo, along with a MongoDB database. I chose MongoDB because I needed the schema to be flexible. Right now, the notes can only hold text content, but they might later contain checklists, images, links, etc. This was also my first time working directly with a database, so the fact that the data is stored as JSON objects made it frictionless for me to pick up.
For real-time collaboration, I usedSocket.io. I initially started with normal WebSockets, but managing a WebSocket connection for each note became cumbersome. Socket.io’s “rooms” feature was perfect for this, with one room per note. The auto-reconnect feature was useful for possible disconnects on mobile.
Here’s how Sharenotes works:
When you open the app, you’re presented with a button to create a new note.
When you click the button, you are taken to the new note, and the URL will include that note’s unique ID.
You can now start typing in the note!
Anyone can go to that URL to start collaborating on the note, and all users will be able to see everyone’s edits to the note in real time.
When all users on a note exit the app, the note’s contents are written to the database.
I got the PWA part of it working enough to add the app to my homescreen on my phone. But when you open the app, it goes to the root URL, which isn’t that useful since all it contains is the “create note” button. Ideally, the app would open the last note you visited, or have a list of previously visited notes on the homepage.
At this point, I hadn’t deployed the back end. I was running the server on localhost and using ngrok to create a public URL that led to my localhost server. The front end was deployed on Vercel, and every time I ran the back end and ngrok, I had to take the new public URL and set it in an environment variable in Vercel to get the front end to connect successfully.
There are a few things I need to do before I can actually use Sharenotes:
Merging conflicts: Right now, any time you make a change to a note, it sends the note’s content to the server, overwrites whatever is stored for that note, and broadcasts it to everyone who is editing the same note. So in the scenario where your internet disconnects and you make changes to the note, your version of the note differs from another user’s version of that note. When your internet reconnects, the client will send its updated note content and overwrite the other user’s note. There’s an operational transformation library that looks promising for this.
A homepage that shows previous notes: As I mentioned earlier, the homepage only contains a “create note” button. To make this app feel like a native mobile app, the user needs to be able to get to their notes without constantly finding and entering URLs.
Deploying the back end: This one needs no explanation!
And there are a few more things to add before releasing Sharenotes to the world:
A cache to hold note content: In my initial version, Sharenotes only saves a note to the database when all users exit the note. This means that the content for each note is stored in the server’s memory until that happens. If too many notes are open, or the notes’ contents get too big, the server will run out of memory. I need to integrate some kind of cache that can hold all this data without overloading the server. I haven’t looked into this much so I’m not sure what the best solution would be yet.
More note content types: All you can do in a note is type text. It would be nice to be able to insert checklists, images, links, etc.
Optional accounts: You might want to create notes that are private, instead of letting anyone with the note’s URL edit the note. In this case, you and your collaborators would need to sign into your accounts to view these notes.
This project was not only a lot of fun to work on but also a very practical start to the Commit experience. I can now add MongoDB, Next.js and Socket.io to my programming tool belt, and I have a project that’s fresh in my mind to bring up in interviews.
We hire Software Engineers to build their careers with promising early-stage startups. Join the waitlist today!
Robyn Choi is a front end engineer (inching closer to full-stack) who loves building products that improve the lives of individuals. In her spare time, she enjoys bouldering and working on her ongoing game project.