Making of this website

May 01 2019

It seems like most of the creators who respect theirselves have a personal website. This makes sense - your website acts as a central point to learn about you and what you do. Making my own one seemed inevitable, but I didn't expect it'd happen this soon.

I had doubts if I should make it right now: perhaps I don't have enough things to showoff, it also seemed to be a waste of time, but like most of my other projects, it happened spontaneously.

The original inspiration

Weirdly enough, I consider playing Hitman the first thing that led to creation of this website: I loved it's menus. While today you can't impress anyone by using tiles, the way they were arranged and presented felt very straightforward and on-point. Somehow they made me think that the game has a lot to offer: what's this? and what is that? I keep occasionally checking these menus over and over again even after I moved onto Hitman 2.

Hitman Menu

Hitman Menu

Hitman Menu

I was job hunting during this period, and I realised that despite understanding how fancy HTML / CSS work, I had nothing to prove it: my past projects were more focused on do rather than see, the latter dominating every website which is supposed to present you, your projects or business. Compared to these, my approach to design always seemed bland, and I don't even care minimalism, it just always felt right to go that way.

To prove myself that I'm also capable of doing fancy stuff, I decided to recreate a portion from Hitman menu.

It's not very faithful but does have the feel. I didn't really expand on it afterwards: I've got myself a much better exercise later instead. Still, whatever that was done had a future impact on what you see here.

Domain motivational kick

If I were to make a website, what about domain name? Staying on suxinjke.github.io was fine but doesn't follow the rule of cool. I decided to check the availability of suxin and was met with a hot very cheap one year deal for suxin.space. I liked this one instantly, I wanted to buy it and do something with it. While space domain extension could be considered novel by today's standards and maybe less credible because of that, I didn't care because it's simple, it's easy to remember, it reflects the website purpose perfectly and a couple of my projects are related to a space game.

Just like that, my desire to acquire the domain name naturally led me to the decision of making a personal website.

Focusing on why and how

Now I'm here with some design inspiration and domain name at bay. With all intrusive thoughts mentioned at the beginning, I had to put them aside and outline what do I want to show, and why:

Why

How

While I knew what I wanted to show and how is already dictated by Hitman menu inspiration, I had to convince myself why it was the right way. This made me check plenty of similar websites and portfolios.

I think they are often overdesigned, sometimes downright pretentious. I absolutely despise any website that would scrolljack. It seems that some of these are focused on showing off the design skills that would be more valuable on any (video) advertisement rather than website, which should be focused on delivering information as quick and easy as possible. I do believe in show don't tell rule, but I often feel the focus is set on showing unrelated things to distract and impress you with that alone.

Frustrated with some of the designs encountered, I decided I want to keep straightforward approach that suits me while retaining some of personal style, which can be only seen in my choice of colors below and making the whole thing act smooth. The front page is just a ton of grouped tiles that are supposed to make you ask the same question as I did in Hitman menus: what's this and what is that? In that case you just click and it shows or redirects you to relevant info. And the most important thing: it's only one click and potential scrolling away, which suits the straightforward approach.

Fonts

Since I'm using Hitman as my inspiration I'm also in love with Helvetica like fonts. Despite it's wide usage., I like these because they make everything look professional. I'm not sure what exact font is used in Hitman but whatever they used in 2016 does suit the professional attitude of Agent 47.

Helvetica

The problem is: Helvetica isn't free, you have to buy it, and default alternatives like Arial suck.

This led me to questioning if I could find a free alternative, most of the stuff people have suggested on internet doesn't have that Helvetica feel I'm looking for, but I did find two fonts worth it.

Neue Montreal

Made by The Pangram Pangram Foundry, this font hits the exact spot for me, I'd use it here if not for one problem: It's not free as it may seem. The website says it's free for personal use, but attempt to get free font pack via email only got me Light and Bold variants, which is obviously not sufficient and I don't even need Light.

Neue Montreal

Neue Montreal

Aileron

This one is made by TipoType, while some of the letters seem more thin and off, I still get the Helvetica professional feel from it. And this font is truly free for personal use. What you're reading right now on this website is powered by Aileron.

Aileron

Aileron

Colors

I'm no professional designer, and yet I understand the importance of picking the right colors. I didn't want to have a huge palette to manage, so I ended up with five colors which seems to be a standard. Some people get away even with four or three colors.

One of the rules I've heard often: never go full black or full white - it burns eyes. While I never really noticed the problem with this, I can agree adding/removing some shade of gray makes it more comfortable to read, it makes text feel more warm?

It didn't take me long to pick the actual colors - these represent European Robin bird that I've been putting on myself since 2012.

#333333
#e0e0e0
#f3f3f3
#ff8f02
#816949

Content management

The last technical problem I had to deal with is managing content on this website, I had next requirements:

Because I've been recently using Vue - the most straightforward framework I've ever worked with, I wanted to keep it as a base. This led me to pick Nuxt as static website generator.

I've been also considering Vuepress but I failed to setup it properly last time, and it felt like I will have less control with it compared to Nuxt.

I started out with prototyping as usual, mostly interested in making a basic layout for items, which feature something and either link somewhere or show additional info. Sometimes I want these to rotate between several images and headers.

While I had those above requirements in mind, I hesitated with actually meeting those regarding content management. I'd rather get something online quickly and fix it later instead of doing it the right way.

<section class="item-section">
    <div class="item-section__header">
        <HeaderText icon="user" header="ABOUT" />
    </div>
    <div class="item-collection item-section__item-collection">
        <Item image="/robin_1.jpg" style="flex: 3">
            <template v-slot:modal_description>
                ...description
            </template>
            <HeaderText icon="user" header="suXin" header_secondary="GENERALIST DEVELOPER"/>
        </Item>
        <Item image="/twitter.png" href="https://twitter.com/suxinjke">
            <HeaderText icon="at" header="TWITTER" header_secondary="CONTACT"/>
        </Item>
        <div class="item-collection__section" >
            <Item background_position="0% 0%" image="/code.png" href="/notes/test">
                <HeaderText icon="file-code" header="GITHUB" header_secondary="PROJECTS"/>
            </Item>
            <SlideShow>
                <Item image="https://i.ytimg.com/vi/THA0e61Abc4/hqdefault.jpg" href="https://www.youtube.com/watch?v=THA0e61Abc4">
                    <HeaderText icon="video" header="YOUTUBE" header_secondary="VIDEOS"/>
                </Item>
                <Item image="https://i.ytimg.com/vi/gxt2cd9rjT4/hqdefault.jpg" href="https://www.youtube.com/watch?v=gxt2cd9rjT4">
                    <HeaderText icon="video" header="YOUTUBE" header_secondary="VIDEOS"/>
                </Item>
            </SlideShow>
        </div>
    </div>
</section>

This one sucks. Especially the <SlideShow> component that switches between included children elements. Now imagine a case when I have a very long description and I would like to slideshow my images, this will require me to duplicate that giant Item only with a different image. Several days later I'd also encounter a typo that I'd forget to fix in one of those duplicated elements. Several months later I'd like to make another page where I'd put these items too, and I'd have to duplicate descriptions and everything else again. This was unacceptable. I had to do things correctly straight from the beginning.

And I'm not even talking about forgetting mobile first design, whatever I had at that point was completely unusable on my small Blackberry screen, all because I was very focused getting the bare minimum.

Frustrated, I decided to start over from scratch with whatever design scraps already made. I remembered the approach of making reusable components that should not depend on parents when it comes to layout. It's the parent elements that should be responsible for modifying these components.

I was moving towards declaring my items as Markdown documents. Solely using Markdown is not enough, there must be some meta info that could be used when generating a list of pages, or be able to sort them by date, or pass that meta info to meta tags.

Front matter provides exactly that, it has YAML meta section that can be parsed into JSON, and a regular Markdown section. By following my own schema, I can make whatever components that will consume and render this differently.

---
title: DELTA SHAKEDOWN
subtitle: IDEA
icon: stopwatch
image: /img/stopwatch.jpg
---
...description...

Some items don't have descriptions and may focus on slideshow presentation. I decided to move slideshow logic to Item component instead. This component also has a logic that gets an element from showcase and overrides default values with the showcase element contents. In the example below I could also override subtitle, icon and link too if I need it.

---
title: YOUTUBE
subtitle: VIDEOS
icon: video
showcase:
    -   image: https://i.ytimg.com/vi/THA0e61Abc4/hqdefault.jpg
        link: https://www.youtube.com/watch?v=THA0e61Abc4
    -   image: https://i.ytimg.com/vi/gxt2cd9rjT4/hqdefault.jpg
        link: https://www.youtube.com/watch?v=gxt2cd9rjT4
---

Right now, the previously convoluted section is mostly focused on layout. Item became ItemClickable here and accepts the name of Markdown document which gets resolved and parsed internally.

<section class="home__section">
    <HeaderText class="section-header" icon="user" header="ABOUT" />
    <div class="collection">
        <ItemClickable class="collection__item collection__item_expanded" name="suxin"/>
        <div class="collection__item collection collection_sub">
            <ItemClickable class="collection__item" name="suxin-twitter"/>
            <ItemClickable class="collection__item" name="suxin-email"/>
        </div>
        <div class="collection__item collection collection_sub">
            <ItemClickable class="collection__item" name="suxin-github" />
            <ItemClickable class="collection__item" name="suxin-youtube"/>
        </div>
    </div>
</section>

What I love about Nuxt is the fact that it automatically maps your directories and files in pages directory to routes. But there's no such luxury when it comes to my case where I only want to focus on making markdown files.

Of course I could make page files instead, but it doesn't meet my requirement of being able to present one markdown file in several ways, and it's also less pleasant to work with in VS Code, the latter having neat Markdown preview and highlighting.

Nuxt does server rendering first before all routing and whatever management goes to the client. While on server, I'm available to use require function, which automatically uses one of the webpack loaders to parse the Front Matter Markdown file for me. I can both render parsed file and provide meta information to the component.

When I'm fetching a certain note, it's easy to render it because route name matches the file name, but it's not that easy when I want to automatically list all my notes.

The problem can be narrowed down to: where do I get a list of pages from? I could certainly get it by fetching directory contents with fs, just like I did in the nuxt config, but it only works reliably on the first server render. If you go to this page via nuxt-link, which is preferred, the data won't be fetched again because you have no access to the directory on the client.

A hacky solution was found: before setting up the dev environment or generating files, a notes.json file is generated in Nuxt's before build hook, this file is then fetched in the Note list page, and all of the files are then parsed the same way as before and then rendered.

I don't like this solution, but it doesn't really matter right now. After all, I'm only dealing with a simple static website.

// nuxt.config.js
const note_file_names = fs.readdirSync( './assets/notes' )
const note_routes = note_file_names.map( file => `/notes/${file.replace( /\.md$/, '' )}` )

// ...
    hooks: {
        build: {
            before() {
                // Make a json file with a list of notes, that will be used later for rendering
                fs.writeFileSync( './static/notes.json', JSON.stringify( note_file_names ) )
            }
        }
    },

    generate: {
        routes: function( callback ) {
            callback( null, note_routes )
        }
    },
// ...

// /pages/notes/_note.vue
// ...
computed: {
    parsedPage: function() {
        const routeName = this.$nuxt.$route.params.note
        return require( `@/assets/notes/${routeName}.md` )
    }
// ...

// /pages/notes/index.vue
// ...
export default {
    asyncData: ( ctx ) => {
        // Can't use fs here, grab the list of notes from json file
        const page_list = require( '@/static/notes.json' )

        const pages = page_list.map( file => {
            const note = require( `@/assets/notes/${file}` )
            return {
                /* Whatever meta info I need */
            }
        } )

        // These can be rendered now
        return { pages }
    }
// ...

There's one problem left with rendering Markdown note: relative links are not considered nuxt-link.

What

So far I was focusing on how I came to making this website and some technical challenges I've encountered. What's next?

I don't know, and I love it, I don't want to restrict myself:

All of this on entirely different topics, it doesn't have to stay 100% technical.

Bonus weird early layout tests

Layout test

Layout test