Insights into my blogging platform and its implementation.
Divij Bhatia
|
March 22nd, 2022
Background
This dates back to the summer of 2020. Almost 2 months into the pandemic, all my summer travel plans had cancelled and I still had a month before my internship started. What could have been a better way to utilize the pandemic than to learn something new?
So, like everybody else, I started thinking about finding a new hobby. For some time now, I had this little inclination and sudden urge to write things. So, I decided to start a blog; a bit more personalized and customizable than the one I already had on Medium.
After exploring many existing UI based solutions, I finally ended up starting to build a blogging platform from scratch. Initial plan was to wrap it up in a few months but due to school and work-related commitments, and increase in the initial scope it took me one and a half years and almost 24,000 lines of code to complete and launch.
Let's dive deep into how I built it. The article might get a bit technical but I'll try my best to keep it simple and understandable by everyone.
The Problem
The problem was to build an end-to-end workflow for someone to set up their own personalized blog with top-notch UI giving both the author and the reader a delightful and seamless experience while reading, writing and managing articles.
Based on this initial idea, I formulated the requirements/features which are listed below:
1. The platform should not target just the tech community and so the creation of an article shouldn't require any programming knowledge or experience.
2. The platform should be easily extendable to new bloggers if needed i.e. The platform should support multiple users and their onboarding and setup process should be minimal.
3. Content should not be static. Everything had to be dynamic so that the content could be created, updated and deleted in real time without any new service deployment.
The Solution
The workflow of a blogger has two different sides to it. One is the managing side where the blogger creates a blog, writes articles and manages them and the other is the public facing side where the readers read those articles.
To avoid bugging the reader by exposing irrelevant admin login and blog management features on the UI, I decided to keep both the use cases of managing and accessing the blog separate.
The idea here was to develop two platforms:
1. The Admin Console - The console that allows the blogger to manage the blog, write, and manage articles.
2. The User Console - The console where readers will read articles. This website where you are reading this article is the user console of my blog.
Let's discuss the use case and tech behind a few important components of both the platforms in detail.
The Admin Console
Use case:
This console supports the following use cases:
1. Blog management - The ability to update the blog name, description, blog logo/icon, adding author and its details etc. comes under this use case. As I mentioned earlier, everything on the user console is dynamic like the heading "Blog by Divij Bhatia" and the description "Thoughts on life, work and everything in between" and can be updated in real time. All such updates count in this use case.
2. Article creation and management - This is the primary use case of this console which allows the author to write articles and manage them. I'll discuss some of the most important components of this console that serve this use case below:
2.1 Types of articles & their management:
To simplify the management of articles, they are categorized into three types; Draft, Published and Unlisted. Draft as the name suggests are those articles which are either not published or the published/unlisted articles which are being edited. Published articles are the ones that are complete and are visible on the user console. Unlisted articles are the ones that were taken down after publishing.
A published article can also be updated without it being taken down. For this, an edit copy of the published article is created which is like a new draft created using an existing article's contents. When this edit copy is published, it replaces the original published article and creates a seamless experience for the author where their article is never taken down and is updated.
2.2 Article creation and the Article Editor:
Based on the requirement #1, the idea was to avoid using any programming/markdown language or directly updating the database for writing an article. So, for that I created a What You See Is What You Get (WYSIWYG) web based rich text editor. This allows an author to write articles as if they were writing it in a Word document and see how it will actually look on the blog simultaneously.
Article Editor is the heart of this project and creating it was actually the most complex part. Before explaining the tech behind it let me first list down the features supported by it:
1. Supports different types of text layouts like headings, paragraphs, blockquotes, quotations etc.
2. Allows changing text alignment of the text layouts. (Left, right center and justify)
3. Allows adding images that scale based on the device's screen resolution and supports 6 different sizes (XS to XL and full screen width).
4. Supports link previews where a snippet of a link can be inserted just like how it looks when you share a link on Signal, FB, WhatsApp etc.
5. Supports GitHub Gists which enables the addition of ASCII tables, and code snippets.
6. Supports three types of paragraph separators. (Dot, line and blank)
7. Provides auto-save functionality.
8. Allows text formatting features like Bold, Italic, Underline, Strike Through, Highlight, Subscript, Superscript, Hyperlink etc.
9. Supports adding YouTube videos.
2.2.1 Technically what is an Article?
The inspiration of the tech behind the article editor comes from the game I used to play in my childhood - LEGO. For those who don't know, LEGO is a game where the player is given a set of blocks which they use to create a masterpiece.
Likewise, here the article is conceptualized as an ordered list of blocks. Similar to LEGO, a block is nothing but an object that has some characteristics and a look & feel to it. In this project, there are different types of blocks like Heading Block, Paragraph Block, Quotation Block, Image Block etc. All of them have some properties attached to them and an ordered combination of these becomes an article.
Implementation wise, it is a JSON object with an id, type and properties. The web app uses the id to maintain the block order and the type & properties to render it on the website.
This is how a block looks internally. And yes, this is a GistBlock.
Along with this, the article also carries some metadata like thumbnail, author(s), published on & modified on timestamps, URL etc.
2.2.2 Internal working of the Article Editor:
The Article Editor has 4 functions i.e. to fetch the current copy of the article from the remote datastore which has to be edited, render it on the webpage, allow the author to make changes to it and save it silently in real time. Let's look at the diagram below which will help you to visualize how the editor performs these tasks. The real scenario has been simplified by hiding some of the components in the diagram.
Internal working of the article editor
When an article is opened for editing, control comes to the ArticleEditor component. It first fetches the article from the remote datastore and then saves it to the local datastore. As soon as an update is made to the local datastore, the article renderer kicks in. It fetches the article from the local datastore and starts rendering it. The renderer does it by iterating over the list of blocks, identifying the block type and then rendering the corresponding block component. Once the article is rendered it is ready to be edited.
The author then starts adding new blocks or updating the existing ones. After every 300 milliseconds of inactivity, the auto save routine is triggered which updates the remote copy of the article with the local one. And this process is continued until the author has finished editing the article.
2.2.3 Image delivery service:
These days, websites are built in a way that they adapt based on the device you are surfing it from. These are called responsive websites. Along with the content the image has to scale for the best user experience and minimal load time. To achieve this, I made the following optimizations:
a. Image resolution is determined at real-time based on the device resolution and the pixel density of the screen the article is being viewed on.
b. Parallel and lazy loading of images. The image loading doesn't start until the content on the page is fully loaded. Once that's done, all the images are fetched parallelly using separate threads hence reducing the overall image load time.
c. Utilizing Content Delivery Network for delivering images from the fastest network route.
d. Using webp extension for lossless compression of images. It helps in reducing the size of the image without compromising on the quality.
e. Utilizing transient signed URLs for delivering images from a non-public file storage solution without exposing the entire disk to load a single image.
Here is how the service looks like in real-time.
Image Delivery Service
Let's say there's an article which has 4 images. Once the content of the article has loaded, all the image blocks create their own threads to load the images. The request which has information about the resolution of the image that is best for the current device first goes to the backend service which then forwards it to the Image Optimizer over a CDN. Image Optimizer checks if the image is already present in the cache. If not, it will get the image from the File Storage Solution, resize it, and save it to the cache. A transient signed URL is generated for this cached optimized image and returned as the response. The image is then rendered on the page using this signed URL. Currently, I use a 3rd party CDN + Image Optimizer service but eventually it will be replaced with my own implementation of it.
2.2.5 Nitpicks:
Typography - Fonts and typefaces are the most important parts of the User Interface. The typography of a project sets the theme and is one of the primary ways to retain users on the website. In my case, typography plays a very important role because of the nature of this project. The fonts had to be clear, readable and soothing to the reader's eyes so as to create a delightful experience for them.
Admin Console Demo:
The User Console
Use Case:
This console supports only one-use case which is to list all the articles and open them up for the reader to read.
Most of the components like the Article Renderer and the Image Delivery Service are shared between both the Admin and User consoles. Moreover, the experience of reading an article across both the platforms is mostly consistent.
Opening Up Platform for More Bloggers
Reiterating the requirement #2, the platform should be extendable to more bloggers if need be. I created this platform by keeping this in mind and it was designed that way. Currently, there's some more work left to do as part of polishing the product before it is opened up for more users.
Now you may ask, how is it different from Medium, if it supports multiple bloggers? Medium, is a platform where writers write articles which are then commonly indexed on the entire website. But here, every blogger gets their own platform. There is no central place for listing articles which allows the bloggers to write personalized content which might not be suitable for a commonly indexed platform.
⬤⬤⬤
I hope this article gave you a good insight into my project. Until next time...