Designing a Simple Blog Engine
and the Lessons Learned

01 JUNE 2013 | @ahsan_s | Software | Software | 3500 | 1408 | 4

In my last post I talked about why I set out to write yet another blog engine. Basically the whole purpose is to learn a number of technologies and tools that I planned to use for this project. I also talked a little bit about why I chose this particular set of technologies.

Just to be clear, this post is not about a comprehensive design of a perfect blog engine. It is just a journal on my feeble attempt at creating a rudimentary system that I can use to start blogging, and what I learned from the whole exercise.

Technologies & Tools

I’ll just list my technologies & tools of choice here. Where I list multiple items, I haven't developed strong preference for any particular one.

Technologies

The ORM allows me to be database agnostic. As a matter of fact, on my development system I'm using SQLite, whereas in production PostgreSQL is being used. My code doesn't see the database. DataMapper takes care of talking to the database behind the scenes.

There's a good short article on The #1 Reason to Use SASS, in case you're interested. You can also watch a screencast on Zurb Foundation at RailsCasts.

Tools

Design Goals

My high level goals for the overall structure and design of the system were as follows:

  • Textfile-based system
  • Use of database to maintain pertinent information about the blog posts, and to store user comments
  • Sidebar on the left for navigation and to display article related information and visuals
  • Main article content on the right
  • Easy insertion of images of different sizes, floated left or right of text
  • Implement code syntax highlighting
  • Implement Pull-quotes (for iPad and larger devices) in addition to Blockquotes
  • Display users’ comments at the bottom of the article
  • Implement easy to use form to enter comments
  • Fluid and responsive layout
  • Neat and consistent styling
  • Pay attention to alignments, typography & whitespace
  • Avoid using rounded corners, drop-shadows or any 3D effects as much as possible
  • Take every opportunity to learn

Some of these may sound more like implementation details, and they probably are.

High Level Structure

The beauty of Zurb Foundation is that one can easily and quickly create basic layout prototype, such as the following, with the use of little to no styling, making wireframing unnecessary.





Following haml is all it takes to create the above high level layout for a blog:

1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          
!!! 5
          %head
            %meta{:charset => "utf-8"}/
            %meta{:content => "width=device-width", :name => "viewport"}/
            %title Blog Layout using Zurb-Foundation 4
            %link{:href => "css/foundation.css", :rel => "stylesheet"}/
          
          %body
            / Banner
            .row
              .large-12.columns
                %img{:src => "http://placehold.it/1000x120&text=[banner_image]"}/
            %br/
          
            / Sidebar and Main Page Content
            .row
              / Sidebar
              %aside.large-3.columns
                %img{:src => "http://placehold.it/220x500&text=[sidebar]"}/
              / Main Blog Content
              .large-9.columns{:role => "content"}
                %img{:src => "http://placehold.it/720x500&text=[content]"}/
            %br/
          
            / Footer
            %footer.row
              .large-12.columns
                %img{:src => "http://placehold.it/1000x40&text=[footer]"}/


Notice it does not use any user supplied stylesheet, only the CSS that comes with Foundation. I am using the placeholder service placehold.it, where banner, sidebar, main content and the footer will go.

Here's the best part --- the layout is inherently fluid and responsive! Isn't that awesome? You can still use media queries to make further adjustments based on what device it is displayed on. As for these pages, on small devices I do not display the left sidebar, and display all the article info below the title in a condensed form. I also condense the footer text for small devices. If you're reading this on a device where you can resize the window (desktop or laptop), you can try reducing the width of the window to see these transitions take place.


The Banner

The banner, as of this writing, was created from the following three images:

signifying my interest in science, computers and design. I used Adobe Photoshop to blend these images in to the following:

Being new to Photoshop, it took me a while to get to a point where I liked the finished image.

Clicking or tapping on the banner image on all article pages takes you to the home page.

The Home Page

I am using two haml layouts. One for the home page, the other for individual articles. The main contents are automatically embedded in these layouts. This is a common practice in Sinatra.

Pull-quote activates the negative space and makes it participate in the design, rather than just serving as a passive background.

The two layouts are very similar, and I'm afraid I've violated the Don't Repeat Yourself (DRY) principle, which I'm determined to fix before this site is launched. The content of the home page is generated in Ruby code by gathering the first one or two paragraph(s) of each article (using the popular Nokogiri gem) and a small image (prepared exclusively for the home page), if available. I am also caching the page so I don't have to generate it every time the page is requested. After all the home page does not change until I post a new article. Needless to say, as soon as a new article is posted, the home page content is regenerated. I'm not using pagination yet, but will almost certainly have to add it at some point, when I have enough content to warrant it.


The Article

The article, that is the main content area within the layout, believe it or not was the easiest to implement in the entire project. The only tricky part was to do the code syntax highlighting. There are a number of libraries available. But as Ryan Bates shows in his Rails Casts #207, of the ones he reviewed CodeRay is by far the fastest --- about 40 times faster compared to another popular library Pygments. Another feature of the article page, the pull-quote, like the one you see (if you're using an iPad or a larger screen) on the left of the above paragraph is implemented through a few lines of Sass code in the stylesheet. I really like pull-quotes. Not only because they nicely stand out, but also, from a designer's perspective, a pull-quote activates the negative (or white) space and makes it participate in the design, rather than just serving as a passive background.

The Comment Section

Up until now everything was smooth sailing. After all it was mostly static display of information. The reader’s comments section at the bottom of the article pages was a whole another story. It is almost a mini application --- a dynamic, living, breathing entity! Following is a high-level list of items that needed to be considered just for this section:

  1. At least initially I am not allowing anonymous comments. That is, name and email are required fields.
  2. In the form where the user enters his/her comments, I needed to validate name and email fields. I am using some elaborate (but still not fool-proof) regular expression (regex) to validate email addresses. This is an area I may need to revisit.
  3. Since the user can use certain html tags, a preview of how the comment will look like when posted was necessary, I felt. I also wanted this to be seamless to the user. That is, the user shouldn’t have to make any extra effort (e.g., push a button etc.) to view the preview.
  4. Allowing the user to input html tags also has its downsides. For example, what if the user puts very large headers in to the comment, which can easily throw aesthetics out the window! To prevent this, some sites employ html escaping techniques. There's an interesting article on the subject here.
  5. Anytime you allow user input in a web application that’ll also be displayed by the site, you have to also worry about cross-site scripting (XSS) attacks by malicious users. To prevent against XSS attacks, one needs to ‘sanitize’ user’s input. Some sanitization techniques also allow either whitelist or blacklist to be used to control what tags are allowed or not allowed. I’m using one that is whitelist based.
  6. Spam is a huge problem for many blogs --- where advertisers try to use your site, not just free of charge, but also without your permission, to advertise their client’s products to your readers. I have seen blogs where user comments have been closed because of this very reason. How do you stop this and ensure your comment section contains only authentic and relevant comments? Fortunately there are a number of web services available, whose sole purpose is to scan submitted text and email addresses to detect spam. One such service that I am using is Akismet.com . Akismet, or any other service for that matter, is not 100% accurate in identifying spams. So this is what I do --- I use client side code (Coffeescript/jQuery) to handle user preview. As soon as the user submits his or her comments, on the server side (i.e., in my Ruby code) I bounce it off of Akismet web service. It’ll respond by indicating if it thinks the email and text is spam or not. If it is a spam, I quietly flag it as such and store it in the database (I also send an email to myself so I can review the comment in the database). The spammer will not know that his or her comment has been flagged (it’ll still be visible on the spammer’s screen --- gotta love client side programming!) and on other users’ web pages the questionable comment will not be displayed until I review it and clear the flag if appropriate.
  7. Just in case the technique fails miserably and my site gets badly infested with spam, as a last resort (i.e., until I figure out what to do about it) I'd like to be able to easily turn off user comment feature, preventing all users from adding additional comments. Life sure isn't fair!
  8. I also added a feature so that the readers can request to be notified via email (1) when a new article is posted and/or (2) when there’s a new comment posted on a particular article. Readers can unsubscribe through the same interface.
  9. If you post a comment on any of the articles, or make a notification request, your name, email and website information, as well as notification request, are stored on your computer, so that those fields are automatically populated for you next time you visit. As of this writing, the information is only stored (as Cookies) for a limited time, and automatically deleted when it expires.
  10. I don’t want to inadvertently spam my readers! Consider this --- you request to be notified when a new comment is posted on a particular topic of interest to you. Every time a new comment is posted by other readers, the system generates an email for you. Let’s also assume that the article turns out to be a hotly debated topic. Which means you may end up with a large number of emails in your inbox, all informing you that a new comment has been posted. Yikes! One way to solve this would be to not generate emails every time a new comment is posted, but put them in a queue to be processed later by a separate Cron like process (using Resque may be one option) that looks for pending email notifications every so many hours. This may drastically reduce the number of emails you get in the above scenario. By the time you read this, it’ll almost certainly be implemented. However, as of this writing I still have to figure out what the best way is to implement this. This article talks about this problem and a possible solution in a Ruby on Rails (RoR) environment. Finally, the system has to be smart enough to notice that while a comment notification is still pending for you, if you come back and post another comment, then there's no need to send you a notification (until someone else posts a new comment again).

All this should make you wonder, why go through all the trouble when I could easily use a service like DISQUS which is quite good and is popular on many blog sites.

Good question. I sometimes wonder! But then making shortcuts was not a goal of the project. It provided me with the opportunity to learn a few things. Needless to say, even though implementing the comment section was moderately challenging, it was also one that I enjoyed the most.

The Footer

There's nothing fancy about the footer. However, at the bottom right of the article pages, right above the footer somewhat intersecting with it, is a small image of an object (or objects) likely to be found on an office desk. There are several of these images, and I randomly pick one every time the page is requested (or refreshed), giving higher probability of being selected to some of the images I particularly like.

Even though I had decided not to use any 3D effect, or anything with a drop-shadow, I ended up breaking that rule, as you'll notice some of the objects cast a mild shadow. I could have easily removed the shadow in Photoshop, but chose not to do so, as I thought after all it didn't look so bad. There's a reason why they say rules are made to be broken!

Future Plan

There are a number of enhancements and features I'd like to work on in my spare time --- hopefully in not too distant future. These are, in no particular order:

  • Functionality to identify broken external links by pinging each link
  • Convert current text-based system to NoSQL database, preferably MongoDB
  • Support one or more standard interfaces for interacting with the server remotely
  • Make the system purely REST compliant
  • Use Backbone.js or Ember.js to add more structure to the system by providing binding between models and views
  • Add system-wide search feature, when I have enough content to necessitate this
  • Better responsive behavior on tablets and smart phones
  • [more]

But I am seriously afraid that once I move on to other things I may never come back to these!


Acknowledgements

I'd like to acknowledge two gentlemen, unbeknownst to them they have not only inspired me to take up this project, but also influenced many of my decisions.

One of them, Darren Jones of Manchester, UK, has shown me the mechanics of creating a site using Sinatra. In his article Sinatra + Heroku = Super Fast Deployment he shows how simple it is to quickly setup a site in Sinatra. If you are in to Ruby and Sinatra, you simply cannot afford not to visit Darren Jones' I Did It My Way, which is a gold-mine of Sinatra information and examples. Recently (May-Aug 2013) he wrote a three-part article on the design of A Simple Content Management System in Sinatra. He is also a regular contributor to Ruby Source, and the author of Jump Start Sinatra, designed to teach Sinatra in a weekend (highly recommended).

The other person is Steven Bradley of vanseo design. He introduced me to design. When I first visited his blog, which is really simple, but there was something about it that caught my eyes, which I couldn't quite figure out right away. There are certainly many sites that are simple, but none grabbed me like Steven's site did. As I started reading many of his posts (and thankfully there are more than quite a few of them as he has been blogging consistently since 2006), I not only began to learn design concepts --- use of grids and space, alignment, typography, color and much more, but it also became clear to me why such a seemingly simple site looked so elegant --- it was really that many of the design principles were at play. If you are interested in design and aesthetics, the information contained in Steven's site will be quite a learning experience and a sheer delight.

I must admit that I am influenced by Steven's site, and it may even show in some of the design choices I've made (at least I hope it does!). Even though I must also admit that I succumbed to the temptation of adding some fluff at the expense of simplicity.


The Lessons Learned

The lessons learned are numerous and sprinkled all over the article, and I am not going to belabor them here. But a few salient points learnt directly or indirectly are:

  • Having come from a desktop development environment, it was an eye-opener to see how many different technologies are needed to put together even a relatively simple web site.
  • Use of a suitable grid system seemed essential. Given the benefits it provides, I don't see why one would not want to use one.
  • Design concepts certainly appear to play a much bigger role in web development than they do in desktop development. Given so many options available to a user, if a site is not well designed, or easy to use and aesthetically pleasing, a user may move on to other sites. Most user will notice the design and aesthetics first, before they judge the quality of the content. Unless of course if the users do not have a choice, as in corporate websites!
  • Attention to security is an essential part of sites that accept and display user inputs, as is evident from the effort needed to do the user comments section.
  • I found it a huge challenge to write testable code in so many different languages needed to put the site together. This is an area where I most definitely need to invest time to learn more.




Of Interest: