How Did I Build My Website?

Published on March 25, 2025. Last updated on June 24, 2025.

Motivation

In the past, I built some portfolios to mainly showcase my small projects when I was learning programming and job hunting. These portfolios were unnecessarily complex, as they were built with React.js or Next.js. After landing my first programming job, I neglected the portfolio, neither updating it nor writing any blog posts. At the beginning of 2025, I decided to make a “fresh start” by rebuilding my website with a simpler UI and without any JavaScript front-end frameworks or libraries.

As I have grown in my programming career, I have become more interested in understanding how technologies work under the hood and sharing my thoughts on topics that intrigue me. This new website will become a space for exploration, experiment and writing.

The source code of my new website can be found at namvnngu/namvnngu.github.io.

↑ Back to top

Tech stack

Here are the major technologies I have used to build my website:

↑ Back to top

Styling

I have been using only pure CSS to style my website.

CSS methodology

There are many CSS methodologies to architect, manage and maintain a website's styling, such as BEM, OOCSS, SMACSS, Atomic CSS, ITCSS or CUBE CSS. Eventually, I chose CUBE CSS. CUBE stands for Composition Utility Block Exception, and obviously, CSS stands for Cascading Style Sheets. I knew this methodology thanks to Kevin Powell's amazing video, A look at the CUBE CSS methodology in action.

The reason why I chose CUBE CSS is because its website mentions:

Those made me want to explore and experiment it.

It turns out that using CUBE CSS has been a fun experience, even though I initially had a hard time to understand what Block is and when Block should be used.

I am not entirely confident that I am applying CUBE CSS correctly, but at least I find it fun to work with.

↑ Back to top

CSS Reset

I referenced Josh Comeau's CSS Reset. His CSS reset is solid, simple, and sufficient in most cases. If you get a chance, I highly recommend checking it out. He explains it in great detail.

↑ Back to top

Code syntax highlighting

I use a single color for code syntax highlighting. I hope that my choice is not too disappointing for you.

For example:

#include <stdio.h>

int main(void) {
  printf("Hello world!");
}
const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

↑ Back to top

Content

How is page content managed?

I have been using HTML directly to create and update pages. However, there is a slight exception when creating a writing page, which will be explained in more detail in the below section How is a writing like this created?.

Writing pages in HTML directly introduces one issue. Some areas in all pages are identical such as navigation bar and footer. If the number of pages grows into the hundreds (due to the number of writing pages), keeping these areas consistent and updated in all pages becomes a daunting and time-consuming task. Therefore, I created Block built on top of GNU sed to solve this issue. A block is similar to a component in popular front-end frameworks/libraries. It is a reusable group of HTML elements.

Block declaration syntax:

<!-- block-start: block-name -->
<!-- block-end: block-name -->

Let's see Block in action with the example below.

  1. Create files as the following tree.
scripts/
└── block.sh
src/
├── blocks/
│   └── header.html
├── home.html
├── index.html
└── projects.html
  1. Define the header block. Note that while the indentation is expected to be formatted properly when the header block is placed in HTML page files, indentation does not matter in my case as I do not preserve it.
    <header>
      <nav>
        <a href="/home.html">Home</a>
        <a href="/projects.html">Projects</a>
      </nav>
    </header>
  1. Define the Home page with header's start and end block tag.
<!DOCTYPE html>
<html lang="en">
  <head>
  <title>Home</title>
  </head>
  <body>
    <!-- block-start: header -->
    <!-- block-end: header -->
  </body>
</html>
  1. Define the Projects page with header's start and end block tag.
<!DOCTYPE html>
<html lang="en">
  <head>
  <title>Projects</title>
  </head>
  <body>
    <!-- block-start: header -->
    <!-- block-end: header -->
  </body>
</html>
  1. Run scripts/block.sh with the block name (i.e. header). The script can be found in scripts/block.sh.
./scripts/block.sh header
  1. As a result, the Home page and the Projects page are updated as follows.
<!DOCTYPE html>
<html lang="en">
  <head>
  <title>Home</title>
  </head>
  <body>
    <!-- block-start: header -->
    <header>
      <nav>
        <a href="/home.html">Home</a>
        <a href="/projects.html">Projects</a>
      </nav>
    </header>
    <!-- block-end: header -->
  </body>
</html>
<!DOCTYPE html>
<html lang="en">
  <head>
  <title>Projects</title>
  </head>
  <body>
    <!-- block-start: header -->
    <header>
      <nav>
        <a href="/home.html">Home</a>
        <a href="/projects.html">Projects</a>
      </nav>
    </header>
    <!-- block-end: header -->
  </body>
</html>
  1. Whenever src/blocks/header.html is updated, simply run the script in the step 5 to update the header block across all pages.

↑ Back to top

How is a writing like this created?

A writing is created through the following steps:

  1. Create a Markdown file, e.g. writing.md.
  2. Compose content in writing.md.
  3. Run the following Pandoc command to convert Markdown to HTML, i.e. writing.md to writing.html.
pandoc writing.md \
       --toc \
       --standalone \
       --wrap=preserve \
       --highlight-style=kate \
       --output=writing.html
  1. Copy content line by line from writing.html to the actual HTML page, making adjustments to align with my website's styling.

As you can see, writing pages are first written in Markdown and then converted to HTML. This is the only exception to not using HTML directly to create pages, which is mentioned in the section How is page content managed?.

↑ Back to top

Interesting points during development

↑ Back to top

Cheers,
Nam Nguyen

$ cd ~/writing