Constructing a blog engine using Ember - Part 1

8 min read • 25th February 2020
Building blog using Ember - Construction site

Link to this sectionWhere it all began

I used to write my articles in Medium. And then, I decided to host my own blog content in Wordpress - for a simple reason that I wanted control over the layers, UI elements, improve SEO, etc. Though I am still a huge fan of Wordpress, being a Frontend engineer, I wanted to build my own Static Site Generator (hereby called as SSG) 😃.

Also, keeping my content in Wordpress, I felt the control of the webpage was not fully with me - for example, for improving page speeds I had to dig deep into the core PHP codebase. Some of my posts are rich media content and uploading numerous images were being limited to few uploads because I had troubles with my Webspace hosting provided as well. This started falling like a house of cards. Some of the changes like optimising for page speed required me to work on PHP codebase and this seemed way too complicated for me and preferred to write my own HTML+CSS pages. After ending up with multiple discussions with my Hosting provider and Wordpress support, my patience was being tested a bit higher. Ofcourse, I could have pushed all my images in 3rd part services like Cloudinary, or the Wordpress supported plugins, but I was slightly paranoid about the images being on other services. Well, even now they aren't - I've convinced myself it is Ok 😂.

Since I had decided to build my own SSG or use something that is highly Frontend dev friendly, I had tweeted about it asking folks, if there was a better blogging platform that they know off. All I wanted was something light weight, easy to use like Wordpress, yet with more control. Few suggested, "write your own" and a few leaned over "GatsbyJS" and "Empress-blog". Gatsby being a React blog engine and a lot of GraphQL stuff, I was naturally uninclined towards it. Not because I don't like React, but because I wanted to quickly move my content from Wordpress and use something that I already know off. (A part of me was not favouring React 😂).

I was left with 2 options, either to choose ember's empress-blog by Chris Manson, or to build my own SSG. empress-blog got me a bit interested, but since I already knew EmberJS, I thought I should build my own blog-engine just to learn how empress and other SSGs works behind the scenes. Along the way, I also wanted to achieve best practices and build a super fast blog using EmberJS.

This post is about how I built my own blog engine using:

  1. EmberJS
  2. Data storage using ember-cli-mirage and broccoli-static-site-json
  3. Fastboot
  4. Prember
  5. Best practices - Accessibility, Caching, and Image optimisations

Link to this sectionWhere should I start

Ember tomster

This was the primary question for me. Where do I begin? Since I was a bit clueless where I wanted to start, I knew I definitely needed to do create an ember app. So I did:

ember new my-own-blog

Now that I have my basic boilerplate of Ember app ready, I wanted to start looking for Lighthouse metrics to make sure my app was 100% performant, 100% SEO optimised, 100% pertaining to Best practices and partially PWA friendly. Remember, I wanted to build a ground up blog engine that is performant and easy to write content into.

ember s --prod

and then navigated to Lighthouse tab on the Chrome Console to measure the metrics. Almost green as it turned out to be, a few things like <html lang="en"> needed attention and I had to fix it manually. I left fixing other performance for future and moved on to building the blog engine.

Note
Adding lang on the html Node is manual at the moment until ember-cli brings it out of the box.

Link to this sectionStyling

HTML and CSS

I knew that building such apps could potentially make your CSS go unmaintainable in the long run. So I decided to use SASS as the preprocessor since I have used that before. So hello ember-cli-sass 👋. To install it, simply ran:

ember install ember-cli-sass

Now that my blog engine was able to use SASS to writing scalable CSS, the natural problem of how to structure my blog's folder came into picture. Having worked with SASS for almost 5 years, I wanted to choose something scalable in terms of writing the CSS as well as maintaining them. I'm strongly opinionated against using so many classes on a DOM Node as against maintaining them into proper folder structure. Well, SASS has a 7:1 convention for folder structure maintainence and it has been quite effective for me ever since. This naturally kept my CSS neat and clean.

Link to this sectionData

Link to this sectionEmber-CLI-Mirage

To start off with setting up my base blog page, I used ember-cli-mirage to build a static set of json data and configured a basic API endpoints in mirage/config.js. This got me quickly started into working with my UI than worry about my JSON or the way I would be using it or the structure of my JSON. To install ember-cli-mirage, I did

ember install ember-cli-mirage

Then I added up a few factories for my blog model with author relationship. That was extremely quick to get started on my UI. I wasn't concerned about whether I should use MySQL or MongoDB for my blog engine.

Since I was almost done with most of the UI that I wanted to build, it was time for real data. Enter broccoli-static-site-json.

Link to this sectionBroccoli-static-site-json

I knew empress-blog used *.md files to build blog pages. This was done by a broccoli addon called broccoli-static-site-json which uses showdown npm package to compile a set of md files to json. All I had to do was add some configuration and ensure that the right md files were picked and compiled to json. In order to install broccoli-static-site-json, I ran the following command:

npm install broccoli-static-site-json

The follow-up question was how do I ensure that the required files will be converted and from where.

I didn't want to tie this up with my blog engine too tight. So ended up creating an in-repo-addon called content-source which contains contents (folder), package.json and index.js. The index.js would funnel the md files from contents path and compile them to json. I simply had to use the treeForPublic hook of the index.js file.

Also, the contents folder would contain posts, authors, tags, etc which are the source of data for the blog engine.

treeForPublic() {
  return MergeTrees([tree1, tree2, ...]);
}

where tree(n) is a static JSON compilation tree which looks like this

const tree1 = new StaticSiteJson('lib/content-source/contents/posts', {
  attributes: [
    'created_at', 'title', 'updated_at', 'tags',
    'author', 'hero', 'is-published', 'is-page'
  ],
  collate: true,
  contentTypes: ['html', 'description'],
  references: ['authors'],
  type: 'blog',
  contentFolder: '/api/blogs'
});

The above snippet takes the *.md files from lib/content-source/contents/posts during build time and converts them to JSON into /dist/api/blogs. Under this output path, there are all.json and individual blog JSON files. As per broccoli-static-site-json, all.json is created since I had set collate: true flag. It contains all the md files of lib/content-source/contents/posts collated into one single JSON.

Using this data in the blog engine is a simple route model hook implementation. I created a blogs/show.js route which contains the following snippet:

model({ id }) { // params.id
  return this.store.findRecord('blog', id);
}

And for the index page that lists a series of blogs, I created a blogs/index.js which is similar to the above snippet. In place of findRecord simply replace with findAll.

This was about how I got started building my own SSG that powers this blog engine. With regards to optimising the performance for this blog engine, I wrote another post that you can read here.