About this site

A minimal, fast, fully static site focused on readability, performance, and maintainability.

Goals

  • Ship static HTML for instant loads and reliable hosting
  • Keep JS to zero for robustness and accessibility
  • Use components for reuse, consistency, and easy iteration

The journey

I started with handwritten HTML and a lightweight CSS framework. As content grew, copy‑pasting layouts and keeping design consistent became a tax on iteration.

Moving to a component model solved that: I could compose pages from small, reusable pieces and keep typography and spacing consistent without fighting the markup.

I work daily with .NET across apps, services, and websites, so building with a familiar stack made sense—as long as it could stay static.

Static generation

The site is pre-rendered to static HTML at build time. That delivers:

  • Fast first paint and predictable SEO
  • Simple, cache‑friendly hosting on a CDN
  • No client bootstrapping or runtime dependencies

Build pipeline

Every commit triggers a build that generates the static site and publishes it to the host. The process is fast, reproducible, and easy to roll back.

Shiki failed: 122 |             brackets: 0,
123 |             doubleApostrophe: 0,
124 |             singleApostrophe: 0
125 |         };
126 |         const name = this.scope.nodeType === NodeTypeEnum.documentNode ? 'Document' : 'Element';
127 |         const error = new this.window.SyntaxError(`Failed to execute 'querySelectorAll' on '${name}': '${selector}' is not a valid selector.`);
                            ^
TypeError: undefined is not a constructor (evaluating 'new this.window.SyntaxError(`Failed to execute 'querySelectorAll' on '${name}': '${selector}' is not a valid selector.`)')
      at getSelectorGroups (/home/runner/work/personal-site/personal-site/node_modules/happy-dom/lib/query-selector/SelectorParser.js:127:23)
      at querySelector (/home/runner/work/personal-site/personal-site/node_modules/happy-dom/lib/query-selector/QuerySelector.js:130:67)
      at main (/home/runner/work/personal-site/personal-site/tools/shiki-render.ts:72:28)

Code presentation

Code snippets are rendered at build time for zero‑JS syntax highlighting and consistent theming. A small component runs a CLI highlighter during the build and inlines the result into the page.

Shiki failed: 122 |             brackets: 0,
123 |             doubleApostrophe: 0,
124 |             singleApostrophe: 0
125 |         };
126 |         const name = this.scope.nodeType === NodeTypeEnum.documentNode ? 'Document' : 'Element';
127 |         const error = new this.window.SyntaxError(`Failed to execute 'querySelectorAll' on '${name}': '${selector}' is not a valid selector.`);
                            ^
TypeError: undefined is not a constructor (evaluating 'new this.window.SyntaxError(`Failed to execute 'querySelectorAll' on '${name}': '${selector}' is not a valid selector.`)')
      at getSelectorGroups (/home/runner/work/personal-site/personal-site/node_modules/happy-dom/lib/query-selector/SelectorParser.js:127:23)
      at querySelector (/home/runner/work/personal-site/personal-site/node_modules/happy-dom/lib/query-selector/QuerySelector.js:130:67)
      at main (/home/runner/work/personal-site/personal-site/tools/shiki-render.ts:72:28)

What this enables

Performance

Minimal payloads, static HTML, and aggressive caching keep pages snappy on any connection.

Maintainability

Components centralize layout and styling so content stays the focus.