This website; concept, design, development, iteration.

1 Jan 2018

How fucking brilliant I was Baby-steps in Blogging

My blogging started back in 2010, when my uncle suggested creating one after he realized how much of a nerd I was (or rather, he saw the value in a naive kid trying out a whole bunch of things). This resulted in imnotbermuda.com. My goal back then was simple - write stuff to gain more cookie points in my university applications - and it did work! I had successfully received interview invites from big universities around the world.

But there was more than that, something more valuable.

My Dota-related posts took off and gained a fan base (where, I've met really cool people.. You know who you are). I started posting for an audience rather than for myself. It was motivating to get feedback and suggestions, and it made me enjoy sharing information and perspectives. This, may not be the best brag-able fact but I have learnt much more maintaining my Dota post and config codes compared to a couple of interviews.

I genuinely enjoy blogging. I also think ownership of a blog makes you someone who might be featured on Hacker News, separating you out from those with no chance in doing so. But the old blog had finished serving its purpose and revamping it would just take too tedious (plus, I was never happy with Wordpress hosting my things and carrying my old content over). But wait, I do web development!


Website design principles and concepts

There were a couple of core ideas that were the pillars of this website from the beginning.

Minimal JS and CSS

There were three goals to meet from the start - simple, elegant and fast (just like any other modern web development company aims for). This meant, in my head, liberating myself from all other web frameworks and writing things dedicated for my website. There was no need to hack up a wacky, unstable super jet engine on a clumsy bloated body when it could be as light as a feather with.. er.. I can't make feathers go fast. You get my point.

The challenge I could immediately think of was writing replacement for frameworks that I got so used to, such as Bootstrap CSS or some npm packages, and at the same time keeping the modern websites' "responsiveness".

Easy to Update

I knew I would never be bothered to update the website if the updating process was anything more than a single line of command. Easy-to-update also makes small incremental updates practical. Iterative and Agile development.. Am I right?

I aimed for a reproducible and easy-setup solution, since I was not willing to document a twenty-one-step process on how to setup after investing two decades of my life. The whole idea was to give the developer more time to do more important stuff: writing code that is delivered to the end-user.

The 'Wow' Factor - Multiplayer Game

My roots of programming sprouted from game development and I wanted my blog to reflect my passion. Plus, creating workarounds on the absence of UDP connection in client browsers sounded like a lot of potential learning. Spoiler alert, this never went as planned :)

Readers First

My old blog was an absolute bitch to read anything. I wanted a clean and elegant website where readers could focus on the content, without any distractions or ads.

Free Hosting

I had just finished being a student which meant that I was still as poor as a student. It was either free or go home.

Hidden Content

Because, it would be boring and exactly the same otherwise. It would be great if I could provide an unique, personalized experience for every readers out there. I believe the pinnacle of art is bringing the audience to the stage and let one discover the true meanings and purpose of the art, rather than flowing down the scripted path like normal books and movies.

We live in a world where the interactive medium - video games - has gone mainstream. It is about time for other content channels to learn and adopt the advantages of video games as an entertainment and art medium.

Hidden content also means 'reward' for the player reader. There is nothing more satisfying than finding a well-hidden content after a long intended search. There is nothing more refreshing than finding a randomly-stumbled-upon content that might be tailored for you. Either way, it adds some personalized experience to you, the reader.

No, it's not a gimmick. It may hinder some "Readability", but I am sure you will figure it out.


Development

And this is why some commerce kids hate me. Anyone can talk shit and come up with pretty words and idealistic phrases. How did I actually deliver them?

Liberating myself from Frameworks and Packages

Normally, I won't be bothered researching and immediately utilize mainstream frameworks like Rails or Meteor for any website. Not that they are great, I just got used to them. This was not going to work - they were too heavy to host for free and was too much of an overkill for a simple blog.

I was not a huge fan of creating dependencies on other packages either. This was no big project that required a huge black box that could potentially lead to a bloated (in both size and speed) solution.

Anyhow, I liked the idea of transpiling CSS and JS to minify or optimize the code for production. This did not mean that I was a huge fan of Gulp, Browserify or Grunt. They were all, in my eyes, a pile of shit over-engineered tools that would never be touched again for my projects, both personal and work.

An elegant solution appeared after a short research. Brunch was super easy to setup, had a simple config and most importantly, had incremental builds. Yes, it is still a pile of dependencies to worry about but it is purely a build tool - none of these packages will actually make it to the end-users. Using it was great, just look at my config file:

exports.files = {
    javascripts: {
        joinTo: {
            'vendor.js': /^(?!app)/,
            'app-blog.js': [
                'app/mss/*.js',
            ],
            'app-game.js': [
                'app/mss/*.js',
                'app/mss-game/*.js',
            ],
        }
    },
    stylesheets: {
        joinTo: {
            'app-blog.css': [
                'app/css/font.css',
                'app/css/blog.css',
            ],
            'app-game.css': [
                'app/css/font.css',
                'app/css/game.css',
            ],
        }
    },
};

exports.plugins = {
    babel: {
        presets: ['latest']
    },
    cssnano: {
        autoprefixer: {
            add: true
        }
    },
    uglify: {
        mangle: true,
        compress: {
            global_defs: {
                DEBUG: false
            }
        }
    }
};

It could have been simplified and made shorter but I was already happy with the above and concluded sinking time further on optimizing the config file was not worth compared to writing code that could actually be delivered to the end-user. Besides, this was already heavenly compared to convoluted syntax and semantics in other tools.

Anyway, this was the best choice I had made in the project. Writing my own things to do simple things was unbelievably faster than searching then learning random npm packages or frameworks.  (some packages were clearly made by web developers)

Design

I took a lot of inspiration* from Justin O'Beirne. I enjoyed the clean, professional look of the blog which was informative and readable. I took the core principles of that website and added a bit of my flavour ;)

Along with some handy text effects, a little bit of interactivity was added, as demonstrated in the about page. If I were to pitch this design concept with my business top hat, it would be "More information delivery by showing Less".

A lot of design principles and philosophy were heavily referenced from this blog post regarding Stripe's design by Lee Robinson. CSS tricks, font choice and utilization of minimal tools for maximum effect were the key things.

Instead of using PNG files everywhere and bloating my website, I decided to use SVGs wherever possible - taking the advice from Lee Robinson. I got my hands dirty and made the logo with this beautiful Chinese font. I created the Greek mu symbol by hacking up "y" and "l" in Illustrator and generated an outline vector for the header image.

Hosting

Initial obvious choice was hosting on AWS - static website hosting on S3 storage.

However, this would cost roughly $1-3 per month, and this not even close to ideal. I hunted for a truly cost-free solution. GitHub pages - it was completely free to host my 'static' website. This also meant updating the website was just updating my GitHub repository - already configured! Less tedious tasks! No setup process is the best setup process.

Cloudflare was setup to allow HTTPS connection with the end user as a work-around since GitHub pages only supports HTTPS for non-custom domains. Note that this is truly is a work-around, as the encryption only happens between Cloudflare servers and the user, not between Cloudflare and GitHub. But, who cares. HTTPS was already an overkill for a blog. Caching service from Cloudflare significantly boosted website's load performance. So in the end, it was worth the time reading through random SO posts.

The Game

The original plan was to use some existing package for rendering and core game components. Then, mainly work on the networking of the game. However, my nerdy gamer inside wanted to build things from scratch and I ended up writing my own game-framework layer (and I wanted to stay away from hosting problems for now). Currently, it is no where near complete now but it sure does basic things like rendering and user input.

Initial PoC and current version

Here is a quick summary of how it works.

Here is an event listener that updates an object upon key down and up. By this way, we can detect multiple key downs and ups every frame:

const KEYDOWN = 'keydown';
let keyInputs = {};

document.addEventListener('DOMContentLoaded', () => {
    onkeydown = onkeyup = function (e) {
        keyInputs[e.keyCode] = e.type === KEYDOWN;
    };
});

This object is utilized every frame. To render a frame, stepFrame function is called every interval (note that waitTime is idle time between frames and is calculated against target framerate):

document.addEventListener('DOMContentLoaded', () => {
    ...

    setInterval(stepFrame, waitTime);

    ...
});

So.. what happens every frame?

function stepFrame() {
    const currTime = performance.now();
    const diff = currTime - prevTime;
    let fps = 1000 / diff;

    handleInput();
    for (let k in entityInfo) {
        handleMovement(entityInfo[k], diff);
    }
    render(renderCanvas, ctx, player, mapinfo, mapdeco, fps, entityInfo);

    prevTime = currTime;
    prevFps = fps;
}

handleInput is just a function which checks keyInputs for buttons pressed. Note that having just event listeners for keyup or keydown is not going to work - the input processing will run independently from framerate, which is not ideal. Keep in mind that by utilizing diff - the time passed since previous frame, will allow us to move our entities independent of the framerate (not not go faster in higher framerate).

As of now, stepFrame runs a specific helper function handleMovement to run all the movement steps for entities in game (player inclusive). However, this is not ideal. I much prefer Unity's way of handling object's frame updates. My current plan is to switch to objects having update method tied into it, which will be run by stepFrame.

So, how does rendering the map work? The main challenge was calculating which pixels to render then scale it to the screen size. In a nutshell, camera coordinate is the same as player coordinate (easily changeable), measure the offset of the screen width and cut off the part we do not need to render, measure the number of pixels to render, render on canvas and adjust the size appropriately. The code is too much of a tl;dr, check it out on the repository (link below).


Iterations

These were a few of some changes and features that naturally got developed with multiple iterations.

'Module' System

It is just a fancy word for my simple JS code that dynamically loads content to an empty div. There are many utilization around this, such as mimicking React behaviours, dynamic header and footers, and even proper templating. I ended up only using it in header and footers since I wanted to reduce JS code as much as possible and further complications felt unnecessary.

Readability

I played around with different fonts, container size, font size, width, height and other weird CSS things. Feedback from "beta testers" were taken into account. Result is this, I hope you feel comfortable reading my blog.

The Header Menu

"About", "Blog", "Game" were the original tags, and they were boring. Then I thought about following the same convention as "mallocsizeof.me". The domain name was intended to make the user feel like entering my website by mallocing oneself in the memory (what a nerd) . So, I made the header read out in the reader's perspective. I know it sounds like something trivial but it was bullshit. important.


The Outcome

This blog was initially planned a year ago and I finally got some time off to work on it. Although the game part did not end up as I wanted it to be (it is way too far from complete, only went through two iterations), it sure was heck of lot of fun. I will definitely work on it to make it a multiplayer game.

We also learnt an important theorem, that might possibly change the world:

$$ \forall x \ \exists y \ (npm_{package}(x) \wedge size_{of}(x) < 100 \text{kB}) \Rightarrow \\ ( (features_{used}(y) = features_{used}(x)) \wedge \\ (time_{learning}(x) \ge time_{writing}(y)) ) $$ fucking nerd..

You can check out this website code (production code) at bermuda-ut.github.io repository . If you are interested in the source code and how the project is set up, check it out at stay-hungry repository .