Draftbook

A multi-platform app built to make the lives of writers easier.

Draftbook

Draftbook is a web application that I built as a side project during my first semester in university. At this point in time, I was getting more serious about seeing creative writing as a hobby. Before this, I had been using Google Docs: it was an easy, free solution with auto-save that I had been using for my entire school career. There were a few things I needed that Google Docs didn't have, however.

  • An easy way to convert my writing to HTML.
  • Faster navigation between documents in a folder or project.
  • Displaying multiple documents in one tab (without using multiple browser windows).

So when the time came for me to pick a new project to work on, I decided to build my own Google Docs alternative.

What Would It Need?

I wanted to build something I would actually use consistently, which meant I needed all the features I cared about from Google Docs and more. Some of the things I implemented that were inspired by Google Docs are:

  • Document auto-save.
  • Browser and mobile app support.
  • Basic formatting.

Of course, then I needed a few other things that would make my writing experience a little better:

  • Full screen focus mode
  • Left-side chapter navigation.
  • Right-side note navigation, with each note document put into categories.

Now, there was also a hidden extra requirement for me. Up to this point, I had about a year of mostly just building websites using the same set of tools: HTML, CSS, and Vanilla JavaScript. But now I felt confident enough with those that I wanted to branch out and try a framework.

That worked out nicely with my multi-platform deliverable: a little research uncovered Ionic, a toolkit for building mobile apps using web frameworks. Notably, it also offered support for turning a mobile app into a progressive web app compatible on desktop devices as well. I settled on using Vue as my JavaScript framework and got right to work.

Building It

I split the project into two parts: the frontend app and the backend server that it would access. In the past I built websites under one Spring Boot project umbrella. However, this new approach made it a lot simpler to focus on one component of the project at a time. Furthermore, it limited the amount of work necessary to test each component, because I could do so for each individually.

The Frontend

Though I was learning my first web framework, the frontend was relatively straightforward. The only substantial hiccup came with the menu setup. Ionic has an in-built feature, the split pane, that seemed to suit my needs. On mobile, it would stay hidden until a user pressed a button, then letting it slide into focus on the screen. On desktop, however, the menu would be visible by default, taking up only a portion of the screen.

My plan was to use two of these menus in the split pane, one for chapter navigation and one for note navigation/editing. The docs only showed examples for one menu at a time, but adapting them to work for two was only a little confusing. When it came time to implement hiding these panels on desktop to provide more screen space, however, some shenanigans were in order. There were two different ways to hide a menu, and which one I needed to use depended on which device the user was on; unfortunately, there was no mention of this in the docs, so I had to figure it out through trial and error myself!

All in all, this editor screen was the single most time-consuming component of the frontend. I knew, however, that it was also always going to be the most important, the one that users (or at least I) would spend the most time using.

The Backend

Handling everything on the server side was far more in line with what I had practice with for the last year. I was working with a simple Spring Boot setup with a relatively straightforward database. It turned out after some research that I didn't even need to manage documents as individual files: I could just store them in the database!

That did bring up a problem I had faced before when handling a precursor to this project. My early strategy was to upload the entire document to the server every time the user updated it. This worked and was quite simple, but I ran into trouble when I turned on autosave while working with documents over about 8000 words. Every few seconds I would be uploading that entire document, made larger by the fact it was in HTML format. Not ideal in situations where I'm trying to make changes on my phone and my cell reception has abandoned me.

So for this project, I decided to use Google's Diff-Match-Patch libraries. To explain how they work, let's say I keep track of two documents on the client and one on the server: the original version of a document is stored on both sides, and the client also has the new version of the document after the user has made their changes. This library makes it easy for me to take both versions of the document on the client side and calculate the differences. Then, I can just send those differences — which can be far smaller than the entire document — over to the server. On the server side, I can use these libraries to apply the set of differences to the original document, giving me a new one containing the user's changes.

With this trick, I was able to implement frequent autosaving with no annoying stutter on the client side, and making it work was honestly my favorite part of this entire project.

Now That It's Done

It took me three months almost to the day to finish Draftbook. During that time, I learned my first JavaScript framework and made my first voyage into multi-platform app development. Meanwhile, I got to apply and practice the improvements to code hygiene and style that I had already been learning in class.

But beyond all the technical learning I did, now I finally have an app to write in that comes with dark mode by default! In fact, the very article you are reading was written using Draftbook. If that isn't worth the effort, I don't know what is.