Re-making my personal website.

The last time I updated my website was when I finished upper secondary school back in 2015. Tech has changed dramatically since then and so have I. Back when the old website was made I was very into web development, facinated with all the new frontend tools and frameworks released I religiously followed all news sites and developments within the subject.

I drew wireframes for my personal portfolio page, quickly after I developed it with a mix of angular and php. Shortly after I then started to develop wordpress themes as a freelance developer. During this time I developed a broad set of sites all without really understanding much about what I was doing beyond the visuals of a developed website.

I started having that feeling in the back of my head everytime I sat down working, that I didn't know what I was doing and that there is "real" programmers out there that knows their craft and basically that I was a poser. This is more often known as Impostor syndrome.

For some reason I always thought of C to be the solution to my problems. It was a low level language that I had learned only the most elite programmers work with. Thinking back at it I really do not agree with this but I had myself convinced that if I wanted to become a good programmer and not just some poser I had to learn C.

When done working I started to sit down learning C which turned out to be super bare bones and very simple to learn. However I started learning about data structures and algorithms and had myself convinced once again that I needed to learn everything about that to even be comparable to "good" programmers. I think we can all spot a pattern here, this pattern however led me to going to university studying computer science as well as finding a great job at Zenta.

So what does this have to do with me remaking this website six years later you might ask. Well when starting the process of building this re-implementation I started looking around at different technologies thinking about what would suit me, this was a super interesting process. My requirements for the tech stack was firstly It has to have a small footprint on the web, no long load times or bloat. Second i have to in a very easy way be able to add a new article or make changes. Last but not least I have to be able to extend it to basically whatever I want, if I want to make a webshop I should be able to hack one together.

I will go through a few of the alternatives I had in mind as well as why I opted out for them before I present how this site was implemented.

Wordpress

If you want to create a good website with minimal work put into it and have great extensibility and customizability Wordpress is a great choice. Lets say you first want to just create a static site but in 3 months you'd like to start a webshop, then you'd just download some plugins and change some things up and you're set.

For someone like me who are not that great on web design you can also just buy a theme from themeforest and you'll have most things already prepared for you. Making small changes such as for example reacting to the recently announced FLoC is very simple as you can just add the following to your functions.php.

function disable_floc($headers) {
    $headers['Permissions-Policy'] = 'interest-cohort=()';
    return $headers;
  }

add_filter('wp_headers', 'disable_floc');

This is all great however I feel like going with wordpress when I know how to develop things myself is most often leading to what Joe Armstrong calls "The banana monkey jungle problem".

You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.

Basically I would get tons of functionality and things I would never use which in my eyes is bloat. So I started looking elsewhere.

Purescript

I love Haskell and functional programming so ofcourse I would look at my posibilities when it comes to working with it. However purescript itself just compiles to Javascript so I would need to extend things with something like React, Halogen or any other frontend framework. Which would be fine with me if it wasn't for the documentation and tools being so hard to find information for. If something would go wrong here my development time would be extended by insane amounts of time.

It doesn't help that compilation times memory heavy and slow. Further research make me think that Purescript is a more suitable complementary language to have within your JS project, it makes sense to have a few modules written in purescript but not my entire web application and stack. Reason I'm not using Haskell as a backend for example is just that Haskell tooling is incredibly bad in my oppinion and I often spend more time fighting the tools or external libraries than writing code with that language.

Rust / Yew

Rust is a new popular language which has some interesting ideas behind it. Using Rust would allow me to both learn a new language as well as using modern technology to build my site. I started looking at web assembly and a framework called Yew, in retrospect this might have been a mistake and something that scared me away from Rust but anyhow. When creating your first Rust Yew project you have to make a choice, which build tool do you want to use? wasm-bindgen, cargo-web or wasm-pack

One of the options they state on the documentation is not ready for a good developer experience, another of the two options they state has not been touched for 6 months on github. I chose the option that was in my first time rust user opinion the only option that is "safe" and maintaned. I Download the beginner template, don't get it to run and then I ended my Rust journey.

Rolling my own

I like programming in C (or rather a subset of C++), it is simple and I have already a workflow which I am super efficient in. I don't want to develop my own web server since I don't know enough about it and it is very time consuming and would take away my attention from the actual goal of getting my new website up and running. There are not too many alternatives when it comes to C web servers but the ones that exist are actually really good in my opinion.

I wanted a webserver that would allow for good customizability and have low friction when it comes to developing. There is Kore.io which I have never personally built anything with and there is mongoose. Worth to note is that Kore is a web platform not really a raw web server and brings more "baggage" with it.

Kore.io is well maintaned with frequent commits. It's fast, easy to write code for (based on looking at their examples). What made me go with mongoose instead of kore is that mongoose is a single header library. If I have any questions whatsoever I can just consult the source code. The applications I build with mongoose is close to any other application in the sense that my code is using mongoose and not mongoose using my code which is the case for kore.io.

In my mongoose server's event handler I for now have hardcoded routes (will be changed in the future) where I check what the user is requesting and return the correct view based on that.

if (ev == MG_EV_HTTP_MSG) {
        struct mg_http_message *hm = (struct mg_http_message *) ev_data;
        // mg_http_serve_opts opts = {s_root_dir, s_ssi_pattern };
        // mg_http_serve_dir(c, hm, &opts);
        if (mg_http_match_uri(hm, "/"))
        {
            char *Content = ParsePube("../pages/index.pube");
            size_t ContentSize = strlen(Content);

            mg_printf(c,"HTTP/1.1 200 OK\r\n"
                        "Content-Type: text/html; charset=utf-8\r\n"
                        "Content-Length: %d\r\n\r\n%s\n", ContentSize - 1, Content);
            free(Content);
        }

What stands out here is the call to "ParsePube". Pube is a templating language that I created to aid me in making this website. How it works is that it basically reads a .pube file which is the same as a html file but with some custom tags. It tokenize the file contents and then appends the contents to a buffer unless it bumps into a pube tag which can mean different things.

For now I just needed to create partials where I can re-use the same piece of code multiple times. To do this I can write @../pages/head.pube within a pube tag. What that will do is that it will through recursion read the specified file and parse it as a pube file as well. Once parsed the contents will be appended to the original buffer of the parsed pube file and when done it is sent to the user which can then view the site.

tokenizer Tokenizer = Tokenize(File, FileName);
b32 Parsing = true;
while(Parsing)
{
    token Token = GetToken(&Tokenizer);

    switch(Token.Type)
    {
        case Token_EndOfStream:
        {
            Parsing = false;
        } break;

        case Token_LessThan:
        {
            if (TokenEquals(PeekToken(&Tokenizer), "pube"))
            {
                token PubeTag = GetToken(&Tokenizer);
                if (ExpectToken(&Tokenizer, Token_GreaterThan))
                {
                    PubeTag = GetToken(&Tokenizer);
                    switch (PubeTag.Type)
                    {
                        case Token_At: // NOTE(Oskar): Include pube partial
                        {
                            token PubeContent = GetToken(&Tokenizer);

                            char *PartialFile = (char *) malloc((PubeContent.Text.Length + 1) * sizeof(char));                                
                            sprintf(PartialFile, "%.*s", PubeContent.Text.Length, PubeContent.Text.Data);
                            char *PubePartial = ParsePube(PartialFile);

I could have just written this in HTML and use a templating language there but that wouldn't fit the extensibility requirement I had because I would have to add some backend logic sooner or later. This way I can get the best of both worlds. I have my own fully customizable stack that I know every corner of which allows me to be as productive as I can be. I wonder what the younger version of me would think of this. Am I good enough?