Refactor site to new theme
Some checks failed
Build and Deploy Hugo / deploy (push) Failing after 20s

This commit is contained in:
Alex Selimov 2026-03-02 14:56:56 -05:00
parent 1c5cdb3b97
commit 2519b96a86
16 changed files with 2590 additions and 83 deletions

6
.gitmodules vendored
View file

@ -1,3 +1,3 @@
[submodule "themes/hugo-theme-terminal"] [submodule "themes/hugo-bearcub"]
path = themes/hugo-theme-terminal path = themes/hugo-bearcub
url = https://forge.alexselimov.com/aselimov/Terminal-Hugo-Theme.git url = https://github.com/clente/hugo-bearcub

156
assets/auto-theme.css Normal file
View file

@ -0,0 +1,156 @@
:root {
--size: 0.96rem;
--spacing: calc(var(--size) * 2);
}
body {
font-family: "Nunito", "Avenir Next", "Avenir", "Segoe UI", "Helvetica Neue",
Helvetica, Arial, sans-serif;
font-size: calc(var(--size) * 1.6);
line-height: 1.45;
padding: 0 2.8rem 2.8rem;
}
header,
main,
footer {
max-width: 66ch;
}
header,
footer {
position: relative;
}
.mesh-wrap {
position: relative;
left: 50%;
width: 100vw;
transform: translateX(-50%);
pointer-events: none;
overflow: hidden;
}
.mesh-image {
display: block;
width: auto;
height: auto;
max-width: none;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.mesh-wrap-top {
height: 100px;
margin-bottom: 0.6rem;
}
.mesh-image-top {
top: 0;
}
.footer-copy {
padding-top: 0.5rem;
}
h1,
h2,
h3,
h4 {
font-weight: 600;
}
h1 {
font-size: calc(var(--size) * 3.4);
}
h2 {
font-size: calc(var(--size) * 2.8);
}
.title h1 {
font-size: calc(var(--size) * 2.9);
}
nav a,
a.blog-tags {
margin-right: calc(var(--spacing) / 2.8);
}
a {
text-decoration: none;
}
a:hover,
a:focus-visible {
text-decoration: underline;
}
ul.blog-posts li {
margin-bottom: 0.2rem;
}
li {
margin-block-start: calc(var(--spacing) / 2.8);
}
@media (prefers-color-scheme: light) {
body {
background-color: #ffffff;
color: #1f2328;
}
h1,
h2,
h3,
h4,
h5,
h6,
strong,
b {
color: #111827;
}
a {
color: #0969da;
}
a:visited,
ul.blog-posts li a:visited {
color: #8250df;
}
textarea,
input {
background-color: #f6f8fa;
color: #1f2328;
border: 1px solid #d0d7de;
}
table,
th,
td {
border-color: #d0d7de;
}
code {
color: #24292f;
background-color: #f6f8fa;
}
pre code {
background-color: #f6f8fa;
}
blockquote {
border-left-color: #8c959f;
color: #57606a;
}
figcaption > p,
.helptext {
color: #57606a;
}
}

View file

@ -1,21 +1,14 @@
--- ---
title: "" title: ""
framed: true
date: 2022-10-03T14:17:10-04:00 date: 2022-10-03T14:17:10-04:00
layout: index layout: index
--- ---
# Hi I'm Alex Selimov.
<pre class="figlet-banner"> I write about software engineering, Linux, and practical workflows.
_ _ ____ _ _
/ \ | | _____ __ / ___| ___| (_)_ __ ___ _____ __
/ _ \ | |/ _ \ \/ / \___ \ / _ \ | | '_ ` _ \ / _ \ \ / /
/ ___ \| | __/> < ___) | __/ | | | | | | | (_) \ V /
/_/ \_\_|\___/_/\_\ |____/ \___|_|_|_| |_| |_|\___/ \_/
</pre>
I currently work at [UKG](https://www.ukg.com) as a Java Backend Engineer.
I am a materials scientist and software developer proficient in Rust, Fortran, C++, Java, and Python. I have extensive experience with Unix operating systems on both high performance computing resources and on my personal computer (check out [Void Linux](https://voidlinux.org)). I currently work at [UKG](https://www.ukg.com) as a Java Backend Engineer. My background is in materials science and scientific computing, and I build in Rust, Java, Python, C++, and Fortran.
**Checkout recent posts below or posts organized by topic [here](/topics)** You can also browse posts by topic [here](/topics).
**Thanks for stopping by!**

View file

@ -1,21 +1,10 @@
+++ ---
title = "About" title: "About"
date = "2019-01-25" date: 2026-03-02
author = "Radek" ---
+++
# Hi there I am a software engineer with a background in materials science and scientific computing.
My name is Radek and I'm the author of this theme. I made it to help you present your ideas easier. I currently work at UKG as a Java Backend Engineer. My interests span backend systems, developer tooling, Linux workflows, and performance-oriented programming.
We all know how hard is to start something on the web, especially these days. You need to prepare a bunch of stuff, configure them and when thats done — create the content. I write here about practical engineering lessons, tools I use, and projects I build.
This theme is pretty basic and covers all of the essentials. All you have to do is start typing!
The theme includes:
- fully customizable color schemes generated by [**terminal.css**](https://panr.github.io/terminal-css/).
- great reading experience thanks to [**Fira Code**](https://github.com/tonsky/FiraCode).
- nice code highlighting thanks to [**PrismJS**](https://prismjs.com) that matches the theme's color scheme.
So, there you have it... enjoy!

20
content/projects.md Normal file
View file

@ -0,0 +1,20 @@
---
title: "Projects"
date: 2026-03-02
---
This page highlights selected projects across software engineering and technical research.
## Current Focus
- Backend and platform engineering with Java and distributed systems.
- Rust-based tools and utilities for local workflows.
- Practical automation and scripting on Linux.
## Selected Work
- Open source and personal utilities.
- Technical writing and implementation notes.
- Simulation and scientific computing work from prior research roles.
More detailed project write-ups will be added here over time.

View file

@ -1,58 +1,73 @@
baseurl = "https://www.alexselimov.com/" baseURL = "https://www.alexselimov.com/"
languageCode = "en-us" languageCode = "en-US"
theme = "hugo-theme-terminal" theme = "hugo-bearcub"
pagination.pagerSize = 5 defaultContentLanguage = "en"
copyright = "© Alex Selimov"
enableRobotsTXT = true
[pagination]
pagerSize = 5
[markup]
[markup.goldmark.renderer] [markup.goldmark.renderer]
unsafe = true unsafe = true
[markup.highlight]
[params] lineNos = true
contentTypeName = "posts" lineNumbersInTable = false
showMenuItems = 3 noClasses = false
postsToShowOnIndex = 3
fullWidthTheme = false
centerTheme = true
[taxonomies] [taxonomies]
tag = "tags" tag = "tags"
topic = "topics" topic = "topics"
[languages] [languages]
[languages.en]
[languages.en.params]
title = "Alex Selimov" title = "Alex Selimov"
subtitle = "" languageName = "en-US"
keywords = "" languageCode = "en-US"
copyright = "© Alex Selimov"
menuMore = "Show more"
readMore = "Read more"
readOtherPosts = "Read other posts"
[languages.en.params.logo]
logoText = "Alex Selimov"
logoHomeLink = "/"
[languages.en.menu] [languages.en.menu]
[[languages.en.menu.main]] [[languages.en.menu.main]]
identifier = "cv" identifier = "home"
name = "[CV]" name = "Home"
url = "/cv" url = "/"
weight = 1 weight = 1
[[languages.en.menu.main]] [[languages.en.menu.main]]
identifier = "git" identifier = "projects"
name = "[Git]" name = "Projects"
url = "https://forge.alexselimov.com/aselimov" url = "/projects/"
weight = 1
[[languages.en.menu.main]]
identier = "linkedIn"
name = "[LinkedIn]"
url = "https://www.linkedin.com/in/alex-selimov/"
weight = 2 weight = 2
[[languages.en.menu.main]] [[languages.en.menu.main]]
identier = "Scholar" identifier = "about"
name = "[Google Scholar]" name = "About"
url = "https://scholar.google.com/citations?user=w6unVk8AAAAJ&hl=en&oi=ao" url = "/about/"
[[languages.en.menu.main]] weight = 3
identifier = "gpg"
name = "[GPG public key]" [params]
url = "./public.key" description = "Alex Selimov personal site and blog."
title = "Alex Selimov"
favicon = "favicon.png"
images = ["og-image.png"]
dateFormat = "2006-01-02"
hideUntranslated = false
themeStyle = "herman"
generateSocialCard = true
postsToShowOnIndex = 5
[[params.popularPosts]]
title = "Say goodbye to st and say hello to ghostty"
url = "/posts/st_to_ghostty/"
[[params.popularPosts]]
title = "Getting CUDA toolkit installed on Void Linux"
url = "/posts/cuda_on_void/"
[[params.popularPosts]]
title = "Rust is pretty good (Short thoughts on Rust)"
url = "/posts/thoughts_on_rust/"
[[params.popularPosts]]
title = "My nvim/tmux workflow"
url = "/posts/tmux_and_nvim/"
[[params.popularPosts]]
title = "Fighting the web obesity crisis using Hugo and Skeleton CSS"
url = "/posts/web_obesity/"
[params.author]
name = "Alex Selimov"

19
layouts/index.html Normal file
View file

@ -0,0 +1,19 @@
{{ define "main" }}
<content>
{{ .Content }}
<h2>My most recent posts</h2>
<ul class="blog-posts">
{{ $max := default 3 .Site.Params.postsToShowOnIndex }}
{{ $posts := where .Site.RegularPages "Section" "posts" }}
{{ range first $max $posts.ByDate.Reverse }}
<li>
<a href="{{ .RelPermalink }}">{{ .Title }}</a>
</li>
{{ end }}
</ul>
<p><a href="/posts/">All posts →</a></p>
</content>
{{ end }}

View file

@ -0,0 +1,2 @@
{{ $autoTheme := resources.Get "auto-theme.css" | minify }}
<link href="{{ $autoTheme.RelPermalink }}" rel="stylesheet">

View file

@ -0,0 +1,4 @@
<div class="footer-copy">
{{ .Site.Copyright }}
{{ with .Site.Params.madeWith }} | {{ markdownify . }}{{ end }}
</div>

View file

@ -0,0 +1,6 @@
<div class="mesh-wrap mesh-wrap-top" aria-hidden="true">
<img src="/mesh.svg" alt="" class="mesh-image mesh-image-top">
</div>
<a href="{{ relURL .Site.Home.RelPermalink }}" class="title"><h1>{{ .Site.Title }}</h1></a>
<nav>{{- partial "nav.html" . -}}</nav>

View file

@ -0,0 +1,4 @@
{{ range .Site.Menus.main.ByWeight }}
<a href="{{ .URL }}">{{ .Name }}</a>
{{ end }}
<a href='{{ absURL "index.xml" }}'>RSS</a>

View file

@ -0,0 +1,6 @@
{{ .Page.Store.Set "hasCodeBlock" true }}
{{ $lang := .Get "language" | default "" }}
{{ with .Get "title" }}
<p><strong>{{ . }}</strong></p>
{{ end }}
{{ highlight (trim .Inner "\r\n") $lang "" }}

View file

@ -0,0 +1,235 @@
#!/usr/bin/env python3
"""Generate a triangulated mesh graphic as an SVG file.
Example:
python scripts/generate_triangulated_mesh.py --width 1920 --height 1080 --output mesh.svg
"""
from __future__ import annotations
import argparse
import math
import random
from dataclasses import dataclass
from pathlib import Path
@dataclass(frozen=True)
class Point:
x: float
y: float
def clamp(value: float, low: float, high: float) -> float:
return max(low, min(high, value))
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Generate a triangulated mesh SVG.")
parser.add_argument("--width", type=int, required=True, help="Graphic width in pixels.")
parser.add_argument("--height", type=int, required=True, help="Graphic height in pixels.")
parser.add_argument(
"--output",
type=Path,
default=Path("triangulated-mesh.svg"),
help="Output SVG path (default: triangulated-mesh.svg)",
)
parser.add_argument(
"--cell-size",
type=float,
default=120.0,
help="Approximate grid cell size in pixels when x/y step are not set.",
)
parser.add_argument(
"--x-step",
type=float,
default=None,
help="Horizontal point spacing in pixels (overrides --cell-size on x-axis).",
)
parser.add_argument(
"--y-step",
type=float,
default=None,
help="Vertical point spacing in pixels (overrides --cell-size on y-axis).",
)
parser.add_argument(
"--jitter",
type=float,
default=0.35,
help="Point jitter amount as a fraction of cell size (0.0-0.5).",
)
parser.add_argument(
"--seed",
type=int,
default=None,
help="Random seed for reproducible output.",
)
parser.add_argument(
"--stroke",
type=float,
default=1.25,
help="Edge stroke width in pixels.",
)
parser.add_argument(
"--dot-radius",
type=float,
default=1.9,
help="Vertex dot radius in pixels.",
)
parser.add_argument(
"--line-color",
type=str,
default="#334155",
help="Edge color as hex (default: #334155).",
)
parser.add_argument(
"--dot-color",
type=str,
default="#0f172a",
help="Dot color as hex (default: #0f172a).",
)
parser.add_argument(
"--background",
type=str,
default="#f8fafc",
help="Background color as hex (default: #f8fafc).",
)
return parser.parse_args()
def build_points(
width: int,
height: int,
x_step: float,
y_step: float,
jitter_frac: float,
rng: random.Random,
) -> list[list[Point]]:
cols = max(2, math.ceil(width / x_step) + 1)
rows = max(2, math.ceil(height / y_step) + 1)
points: list[list[Point]] = []
jitter = clamp(jitter_frac, 0.0, 0.5) * min(x_step, y_step)
for row in range(rows):
y = (height * row) / (rows - 1)
row_points: list[Point] = []
for col in range(cols):
x = (width * col) / (cols - 1)
# Keep border anchored to make the mesh fill the canvas cleanly.
if 0 < row < rows - 1 and 0 < col < cols - 1:
x += rng.uniform(-jitter, jitter)
y_jittered = y + rng.uniform(-jitter, jitter)
else:
y_jittered = y
row_points.append(Point(x=clamp(x, 0.0, float(width)), y=clamp(y_jittered, 0.0, float(height))))
points.append(row_points)
return points
def generate_triangles(points: list[list[Point]], rng: random.Random) -> list[tuple[Point, Point, Point]]:
triangles: list[tuple[Point, Point, Point]] = []
rows = len(points)
cols = len(points[0]) if rows else 0
for row in range(rows - 1):
for col in range(cols - 1):
p00 = points[row][col]
p10 = points[row][col + 1]
p01 = points[row + 1][col]
p11 = points[row + 1][col + 1]
if rng.random() < 0.5:
triangles.append((p00, p10, p11))
triangles.append((p00, p11, p01))
else:
triangles.append((p00, p10, p01))
triangles.append((p10, p11, p01))
return triangles
def svg_polygon(points: tuple[Point, Point, Point], stroke: str, stroke_width: float) -> str:
pts = " ".join(f"{p.x:.2f},{p.y:.2f}" for p in points)
return (
f'<polygon points="{pts}" fill="none" '
f'stroke="{stroke}" stroke-width="{stroke_width:.3f}" stroke-linejoin="round" />'
)
def write_svg(
width: int,
height: int,
triangles: list[tuple[Point, Point, Point]],
stroke_width: float,
dot_radius: float,
line_color: str,
dot_color: str,
background: str,
output: Path,
points: list[list[Point]],
) -> None:
elements: list[str] = []
for tri in triangles:
elements.append(svg_polygon(tri, stroke=line_color, stroke_width=stroke_width))
circles: list[str] = []
for row in points:
for p in row:
circles.append(f'<circle cx="{p.x:.2f}" cy="{p.y:.2f}" r="{dot_radius:.2f}" fill="{dot_color}" />')
svg = "\n".join(
[
'<?xml version="1.0" encoding="UTF-8"?>',
f'<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="{height}" viewBox="0 0 {width} {height}">',
f'<rect x="0" y="0" width="100%" height="100%" fill="{background}" />',
*elements,
*circles,
"</svg>",
]
)
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text(svg, encoding="utf-8")
def main() -> None:
args = parse_args()
if args.width <= 0 or args.height <= 0:
raise SystemExit("--width and --height must be positive integers")
if args.cell_size <= 1:
raise SystemExit("--cell-size must be > 1")
x_step = args.x_step if args.x_step is not None else args.cell_size
y_step = args.y_step if args.y_step is not None else args.cell_size
if x_step <= 1 or y_step <= 1:
raise SystemExit("--x-step and --y-step must be > 1")
rng = random.Random(args.seed)
points = build_points(args.width, args.height, x_step, y_step, args.jitter, rng)
triangles = generate_triangles(points, rng)
write_svg(
args.width,
args.height,
triangles,
args.stroke,
args.dot_radius,
args.line_color,
args.dot_color,
args.background,
args.output,
points,
)
print(f"Generated {len(triangles)} triangles -> {args.output}")
if __name__ == "__main__":
main()

2058
static/mesh.svg Normal file

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 214 KiB

1
themes/hugo-bearcub Submodule

@ -0,0 +1 @@
Subproject commit 1d12a76549445b767fa02902caf30cec7ceaecf9

@ -1 +0,0 @@
Subproject commit 7cd0b57a0276349b9f107afb48f692e72f0d931a