mljr.eu
Open to opportunities

Hi, I'm Michael.

I build

Master's student (Dipl.-Ing.) in Networks & IT Security at JKU Linz, writing my thesis on permission metamodels at Dynatrace. I care about correctness, performance, and shipping things that actually work.

Michael Reinegger
Michael Reinegger
Linz, Austria
Current focus
Dynatrace thesis
Permission metamodel · Prolog
Near
Linz, Austria
Open to opportunities
MSc / Dipl.-Ing.
Networks & IT Security
JKU Linz · 2026
Homelab
VPS edge + home servers
Caddy · CrowdSec · Tailscale
22
Projects
11+
Years coding
8+
Yrs coding
22
Projects
7
Companies
3
Degrees
Go
Rust
TypeScript
Python
Docker
Linux
Ansible
Tailscale
Grafana
Svelte
Kotlin
Security
Networking
Homelab
IAM / PAM
Embedded
PostgreSQL
SQLite
02

Projects

12 projects
LSTM-Based-Speaker-Diarization 1
LSTM-Based-Speaker-Diarization 2
LSTM-Based-Speaker-Diarization 3
LSTM-Based-Speaker-Diarization 4

LSTM Based Speaker Diarization

Bachelor thesis research implementing LSTM and BiLSTM networks for speaker diarization — the task of labeling who speaks when in an audio recording. Compares d-vector generation architectures and four…

PythonPyTorchMachine LearningAudio
cg-lab-2023-project-reineggersilber 1
cg-lab-2023-project-reineggersilber 2
cg-lab-2023-project-reineggersilber 3

Cg Lab 2023 Project Reineggersilber

A university computer graphics lab project implementing real-time animated 3D scenes directly against raw WebGL (no engine, no three.js) using hand-rolled GLSL shaders. A person wanders a furnished ro…

JavaScriptWebGLGLSLComputer Graphics
face-auth 1
face-auth 2
face-auth 3
face-auth 4

Face Auth

A Linux PAM module for facial recognition login using IR cameras and Windows Hello–compatible hardware. Features liveness anti-spoofing, an egui graphical configuration tool, and plugs into any PAM st…

RustPAMSecurityLinux
jku-master-project-network-devices-power-consumption-analysis 1
jku-master-project-network-devices-power-consumption-analysis 2
jku-master-project-network-devices-power-consumption-analysis 3
jku-master-project-network-devices-power-consumption-analysis 4

Jku Master Project Network Devices Power Consumption Analysis

★ 1

A master's project measuring the power consumption of network devices under different traffic loads. A FritzBox smart plug captures energy data while Go tooling generates UDP, TCP, and Layer-2 loads; …

TeXGoNetworkingData Analysis
Game-of-Life-Multiplatform 1
Game-of-Life-Multiplatform 2

Game Of Life Multiplatform

★ 1

Conway's Game of Life implemented as a Kotlin Multiplatform project for desktop and Android. Developed as a university programming project exploring KMP's shared logic and platform-specific UI capabil…

KotlinMultiplatformSimulation
Lebenslauf 1
Lebenslauf 2
Lebenslauf 3

Lebenslauf

Source files for my CV and cover letter written in Typst — a modern typesetting language. Clean, version-controlled, and trivially re-compilable to PDF.

TypstResumePDF
webcambot 1
webcambot 2
webcambot 3
webcambot 4

Webcambot

A Discord bot that fetches snapshots and video clips from Home Assistant camera entities on command. Configurable clip lengths and instant image delivery make it useful for home monitoring over Discor…

PythonDiscordHome Assistant
Flexbar-Plugin-Youtube-Music-Desktop-App

Flexbar Plugin Youtube Music Desktop App

★ 1

A Node.js plugin for the Flexbar macro pad that controls YouTube Music Desktop App via Socket.IO. Shows the current track, album art, and playback controls directly on the Flexbar display.

JavaScriptTypeScriptPluginDesktop
WordWiz 1
WordWiz 2
WordWiz 3

WordWiz

A SvelteKit word finder and unscrambler: type a bag of letters and it returns every word that can be made from them, in English or German, filtered to a chosen length range. Backed by 450k+ and 670k+ …

JavaScriptTypeScriptSvelteKitWeb
nightscout-display 1
nightscout-display 2

Nightscout Display

A Stream Deck plugin that shows live Nightscout CGM glucose readings on a Stream Deck key. Supports numeric display and a scrolling sparkline graph, with configurable time ranges and color-coded alert…

TypeScriptGoNightscoutStream Deck
AdventOfCode2022_MrCode

AdventOfCode2022 MrCode

Advent of Code 2022 solutions in Kotlin, exploring algorithmic challenges across the December puzzle calendar.

KotlinAlgorithmsPuzzles
AOC2024

AOC2024

Advent of Code 2024 solutions written in Kotlin, working through all December puzzles with clean, readable implementations.

KotlinAlgorithmsPuzzles
03

Live Tools

3 live tool

Regex Lab

LIVE

An interactive regex workbench built in Go + Datastar. Uses regexp2 (PCRE-compatible engine) for backreferences, lookahead, and lookbehind. Matches highlight as you type via server-sent events, with a built-in cheat sheet and 20+ preset examples.

GoRegexPCREDatastarSSE

Cron Explorer

LIVE

An interactive cron expression explorer built in Go + Datastar. Supports standard 5-field and 6-field (with seconds) syntax, @aliases, and common presets. Shows a field-by-field breakdown and the next 10 execution times with countdown.

GoCronDatastarSSE

Codec

LIVE

A multi-mode encode/decode tool built in Go + Datastar. Hash mode computes all four digests simultaneously. Encoding modes support Base64, URL percent-encoding, and HTML entity encoding — all processed server-side via SSE.

GoCryptoBase64DatastarSSE
04

Playground

old side projects, rebuilt

AI Snake

Snake plays itself by following a fixed loop through every cell on the board — a mathematical guarantee it can never trap itself.

Snake

The classic, keyboard-controlled. Eat apples, grow longer, don't hit the wall or yourself.

Minenfeld

Cross a minefield one row at a time — one wrong step and it's over.

Double Pendulum

A chaotic n-segment pendulum — tune the physics and watch tiny changes explode into wildly different motion.

Fourier Drawing

Draw any shape and watch a stack of rotating circles reconstruct it from pure sine waves.

Boids

A flock that organizes itself from three simple local rules — no leader, no plan, just steering.

Particle Life

Colored particles that attract and repel each other by simple pairwise rules — and organize into swarming, chasing clusters on their own.

Maze

Watch a maze carve itself out cell by cell, then watch a breadth-first search solve it.

Sorting Visualizer

Race classic sorting algorithms as animated bars and watch how differently each one earns its comparisons and swaps.

05

Open Source

live data
Contributions

A year of commits

MonWedFriSep1 contributions on Sep 2OctNovDec10 contributions on Dec 1011 contributions on Dec 123 contributions on Dec 161 contributions on Dec 174 contributions on Dec 187 contributions on Dec 1911 contributions on Dec 209 contributions on Dec 2113 contributions on Dec 2210 contributions on Dec 2311 contributions on Dec 275 contributions on Dec 2813 contributions on Dec 2911 contributions on Dec 307 contributions on Dec 31Jan3 contributions on Jan 13 contributions on Jan 21 contributions on Jan 33 contributions on Jan 45 contributions on Jan 59 contributions on Jan 1120 contributions on Jan 125 contributions on Jan 1349 contributions on Jan 147 contributions on Jan 1515 contributions on Jan 1613 contributions on Jan 1743 contributions on Jan 1819 contributions on Jan 205 contributions on Jan 2121 contributions on Jan 2223 contributions on Jan 2314 contributions on Jan 2416 contributions on Jan 253 contributions on Jan 261 contributions on Jan 271 contributions on Jan 284 contributions on Jan 295 contributions on Jan 30Feb12 contributions on Feb 11 contributions on Feb 21 contributions on Feb 814 contributions on Feb 932 contributions on Feb 1022 contributions on Feb 112 contributions on Feb 142 contributions on Feb 202 contributions on Feb 2313 contributions on Feb 2412 contributions on Feb 253 contributions on Feb 2611 contributions on Feb 2717 contributions on Feb 28Mar15 contributions on Mar 13 contributions on Mar 23 contributions on Mar 112 contributions on Mar 133 contributions on Mar 143 contributions on Mar 171 contributions on Mar 205 contributions on Mar 213 contributions on Mar 222 contributions on Mar 31Apr6 contributions on Apr 42 contributions on Apr 121 contributions on Apr 164 contributions on Apr 216 contributions on Apr 22May1 contributions on May 24 contributions on May 87 contributions on May 91 contributions on May 107 contributions on May 1315 contributions on May 1418 contributions on May 151 contributions on May 1617 contributions on May 1717 contributions on May 189 contributions on May 197 contributions on May 208 contributions on May 225 contributions on May 2311 contributions on May 2416 contributions on May 2514 contributions on May 2611 contributions on May 278 contributions on May 291 contributions on May 31Jun4 contributions on Jun 11 contributions on Jun 21 contributions on Jun 105 contributions on Jun 1121 contributions on Jun 1221 contributions on Jun 138 contributions on Jun 146 contributions on Jun 1526 contributions on Jun 1628 contributions on Jun 177 contributions on Jun 186 contributions on Jun 194 contributions on Jun 205 contributions on Jun 236 contributions on Jun 281 contributions on Jun 29Jul2 contributions on Jul 11 contributions on Jul 26 contributions on Jul 34 contributions on Jul 42 contributions on Jul 144 contributions on Jul 201 contributions on Jul 211 contributions on Jul 2620 contributions on Jul 2822 contributions on Jul 291 contributions on Jul 3012 contributions on Jul 31Aug8 contributions on Aug 1
22%GO
20%SVELTE
12%JAVASCRIPT
22
Public repos
3
GitHub stars
914
Commits / year
11d
Longest streak
06

Experience

9 positions
1
2
3
Dynatrace
Dynatrace
Nov 2025 – Present · 9 months

Master Thesis · Software Engineer

Master thesis: abstracting complex IAM systems into a Prolog-based unified permission metamodel

GoPrologIAMSecurity
Dynatrace
Dynatrace
Aug 2025 – Sep 2025 · 2 months

Software Engineering Intern

Software engineering internship at Dynatrace Engineering Headquarters.

GoJavaSecurity
Johannes Kepler University Linz
Johannes Kepler University Linz
Oct 2023 – Jun 2026 · 2 yrs 9 mo

Student Assistant · Tutor

Tutor for Digital Circuits and Computer Architecture across six semesters

TeachingElectronicsArchitecture
4
5
6
ventopay gmbh
ventopay gmbh
Jul 2024 – Jul 2024 · 1 month

Software Development Intern

Angular and C# development of an existing cashless payment system

AngularC#UI/UX
Bosch
Bosch
Aug 2023 – Sep 2023 · 2 months

Software Development Intern

Development of a dashboard for team-relevant information with SvelteKit and TailwindCSS

SvelteKitTailwindCSSREST
Bosch Rexroth
Bosch Rexroth
Jun 2021 – Jun 2021 · 1 month

Assembly & Testing Intern

Assembly of cable ducts and switch cabinets

HardwareHydraulics
7
8
9
HerzReha Bad Ischl
HerzReha Bad Ischl
Sep 2020 – May 2021 · 9 months

Civil Servant

Support of office staff

Healthcare
ENGEL
ENGEL
Jul 2018 – Jul 2018 · 1 month

Mandatory Internship

Data processing with Excel

Manufacturing
ENGEL
ENGEL
Jul 2017 – Jul 2017 · 1 month

Mandatory Internship

Assistance in production

ManufacturingElectronics
DynatraceNov 2025 – Present · 9 months
Master Thesis · Software Engineer
Dynatrace

Master thesis: abstracting complex IAM systems into a Prolog-based unified permission metamodel

DynatraceAug 2025 – Sep 2025 · 2 months
Software Engineering Intern
Dynatrace

Software engineering internship at Dynatrace Engineering Headquarters.

Johannes Kepler University LinzOct 2023 – Jun 2026 · 2 yrs 9 mo
Student Assistant · Tutor
Johannes Kepler University Linz

Tutor for Digital Circuits and Computer Architecture across six semesters

ventopay gmbhJul 2024 – Jul 2024 · 1 month
Software Development Intern
ventopay gmbh

Angular and C# development of an existing cashless payment system

BoschAug 2023 – Sep 2023 · 2 months
Software Development Intern
Bosch

Development of a dashboard for team-relevant information with SvelteKit and TailwindCSS

Bosch RexrothJun 2021 – Jun 2021 · 1 month
Assembly & Testing Intern
Bosch Rexroth

Assembly of cable ducts and switch cabinets

HerzReha Bad IschlSep 2020 – May 2021 · 9 months
Civil Servant
HerzReha Bad Ischl

Support of office staff

ENGELJul 2018 – Jul 2018 · 1 month
Mandatory Internship
ENGEL

Data processing with Excel

ENGELJul 2017 – Jul 2017 · 1 month
Mandatory Internship
ENGEL

Assistance in production

Education

3 degrees
Johannes Kepler University Linz
Johannes Kepler University Linz
Oct 2024 – Present

MSc Networks and IT Security

Coursework and thesis work in network security, cryptography, and formal methods.

Johannes Kepler University Linz
Johannes Kepler University Linz
Oct 2021 – Jul 2024

BSc Computer Science

Computer Science fundamentals with specialization in software engineering.

HTL Steyr
HTL Steyr
Sep 2015 – Jun 2020

Matura · Mechatronics and Robotics

Robotics, automation engineering, embedded systems, and practical technical project work.

Papers & Theses

research work
HTL

HTL Diploma Thesis

Diploma thesis at HTL Steyr (Mechatronics, Robotics & Automation).

Bachelor

Bachelor Thesis

Bachelor thesis in Computer Science at JKU Linz — LSTM-based speaker diarization.

Master

Master Thesis

Abstracting permission systems into a Prolog-based metamodel, written at Dynatrace. Coming soon — currently in progress.

Coming soon
Project

JKU Master Project Report

Network devices power consumption analysis — a Go-based test runner measuring UDP/TCP/L2 throughput against real-time power draw via FritzBox smart plug.

Places

work · education · home
07

Homelab

live via tailscale
Services

Self-hosted fleet

26 / 26 up
Ping: homeassistant2 ms
Ping: mljr1248 ms
Ping: nas1232 ms
Ping: nuc
SMTP: mail.mljr.eu679 ms
authelia1422 ms
bichon2464 ms
cglab876 ms
gameoflife1129 ms
glance1393 ms
goaccess3545 ms
homeassistant2616 ms
homepage4935 ms
immich525 ms
kuma2775 ms
mailcow2250 ms
nas7639 ms
nextcloud4551 ms
nightscout1490 ms
ntfy640 ms
nuc-webui1612 ms
projects1487 ms
sudoku1659 ms
syncthing2719 ms
ui-showcase7374 ms
wordwiz2055 ms
Tailscale mesh

Live infra topology

5 / 5 online
tailnethomeassistant — homeassistantLNXhomeassistanthomeassistanthomeassist…mljr — authelia, glance, ntfy, goaccess, mailcow, crowdsec, cockpit, diun, hellpot, endlessh, spidertrap, homepage, ui-showcase, regex, cron, codec, newsletter, weather-cli, statusLNXmljrautheliaautheliaglanceglancentfyntfygoaccessgoaccessmailcowmailcowcrowdseccrowdseccockpitcockpitdiundiunhellpothellpotendlesshendlesshspidertrapspidertraphomepagehomepageui-showcaseui-showcaseregexregexcroncroncodeccodecnewsletternewsletterweather-cliweather-clistatusstatusnas — nas-alloy, ollama, nas, immich, nextcloud, dockhand, syncthing, test-ocis, projects, dawarichLNXnasnas-alloynas-alloyollamaollamanasnasimmichimmichnextcloudnextclouddockhanddockhandsyncthingsyncthingtest-ocistest-ocisprojectsprojectsdawarichdawarichnuc — nocturne, nightscout, kuma, healthreport, grafana, bichon, umami, forgejo, speedtest, nuc-webui, wordwiz, sudoku, gameoflife, cglab, godrive-demo, service-templateLNXnucnocturnenocturnenightscoutnightscoutkumakumahealthreporthealthrepo…grafanagrafanabichonbichonumamiumamiforgejoforgejospeedtestspeedtestnuc-webuinuc-webuiwordwizwordwizsudokusudokugameoflifegameoflifecglabcglabgodrive-demogodrive-de…service-templateservice-te…ugreen — syncthing-ugreenLNXugreensyncthing-ugreensyncthing-…

Avg response time

2333 ms
2792.8186.424h agonow

Avg CPU · all hosts · 24h

11%
17.47.0

CrowdSec perimeter

27190
Active bans
483
Blocked · 24h
922
Alerts · total
3
Hosts online
Community blocklist · 27174caught here · 16

Top threats · active bans

HTTP scanning25296
SSH brute force959
HTTP exploits555
HTTP brute force337
Aggressive crawling27
http probing9
CrowdSec · last 12 months

Attacks blocked per day

62716 total
MonWedFriSepOctNovDecJanFebMarAprMayJun2026 attacks blocked on Jun 12785 attacks blocked on Jun 131299 attacks blocked on Jun 142117 attacks blocked on Jun 151199 attacks blocked on Jun 16876 attacks blocked on Jun 17548 attacks blocked on Jun 18348 attacks blocked on Jun 19509 attacks blocked on Jun 20301 attacks blocked on Jun 21399 attacks blocked on Jun 22698 attacks blocked on Jun 232327 attacks blocked on Jun 241960 attacks blocked on Jun 255684 attacks blocked on Jun 264411 attacks blocked on Jun 272316 attacks blocked on Jun 283420 attacks blocked on Jun 29903 attacks blocked on Jun 30Jul632 attacks blocked on Jul 1756 attacks blocked on Jul 2603 attacks blocked on Jul 3642 attacks blocked on Jul 4815 attacks blocked on Jul 53693 attacks blocked on Jul 64272 attacks blocked on Jul 73193 attacks blocked on Jul 82263 attacks blocked on Jul 91384 attacks blocked on Jul 10326 attacks blocked on Jul 11488 attacks blocked on Jul 12681 attacks blocked on Jul 13416 attacks blocked on Jul 14493 attacks blocked on Jul 15715 attacks blocked on Jul 161216 attacks blocked on Jul 17677 attacks blocked on Jul 18832 attacks blocked on Jul 19543 attacks blocked on Jul 20195 attacks blocked on Jul 21362 attacks blocked on Jul 22309 attacks blocked on Jul 23851 attacks blocked on Jul 24687 attacks blocked on Jul 25439 attacks blocked on Jul 26556 attacks blocked on Jul 27328 attacks blocked on Jul 28291 attacks blocked on Jul 29143 attacks blocked on Jul 30122 attacks blocked on Jul 31Aug531 attacks blocked on Aug 1655 attacks blocked on Aug 2481 attacks blocked on Aug 3
live — uptime kuma + victoriametrics over tailscale · updated 12:53:29
Architecture

How it hangs together

100% IaC

All public traffic enters through Caddy on the VPS, with CrowdSec banning attackers at the edge and Authelia guarding private apps. Behind that, three machines talk over an encrypted Tailscale mesh — no open ports at home. Every host, container and config file is declared in one Ansible repo: a single make deploy converges the whole fleet.

Internet
→ HTTPS :443 · Caddy ingress · CrowdSec at the edge →
Tailscale mesh · WireGuard
mljr
VPS · public entry
CaddyCrowdSecAutheliapublic apps
nuc
home server
VictoriaMetricsGrafanaLokiinternal services
nas
Unraid NAS
storagebackupsmedia
Ansible provisions all three hosts — inventory, hardening, Docker Compose services, deploy hooks. No snowflakes.
08

Activity

public aggregates
Strava snapshot

Training as data

Distance
155.5 km
run · hike · ski
Moving time
63 h 30 m
logged effort
Sessions
87
year to date
Elevation
1810 m
climbed
Avg HR
138 bpm
session-weighted
Running · 207Cycling · 58Training · 169

Recent public activities

aggregated
Afternoon Training
30.07.2026 · 1:04:48 · ♥ 112 bpm · 471 kcal
Evening Laufen
27.07.2026 · 29:44 · 5.1 km · 5:53 /km · ↑ 39 m · ♥ 176 bpm · 441 kcal
Afternoon Training
23.07.2026 · 46:50 · ♥ 111 bpm · 330 kcal
Morning Laufen
21.07.2026 · 30:28 · 5.0 km · 6:04 /km · ↑ 42 m · ♥ 171 bpm · 433 kcal
Morning Laufen
19.07.2026 · 42:05 · 7.0 km · 6:00 /km · ↑ 60 m · ♥ 175 bpm · 621 kcal
Morning Laufen
15.07.2026 · 29:10 · 5.0 km · 5:50 /km · ↑ 41 m · ♥ 178 bpm · 436 kcal
Morning Laufen
12.07.2026 · 1:11:46 · 10.0 km · 7:10 /km · ↑ 68 m · ♥ 177 bpm · 1071 kcal
Afternoon Training
09.07.2026 · 45:14 · ♥ 104 bpm · 283 kcal

Training load

Fitness (CTL) · Fatigue (ATL) · Form, last 90 days
Form +4.5
30.1-14.4May 6May 28Jun 19Jul 11Aug 2
Fitness
Fatigue
Form
09

Skills

depth × breadth
LanguagesWebInfraSecurityEmbeddedOps/Data
self-assessed depth per area · dots match the cards

Languages

8
GoRustTypeScriptJavaScriptPythonKotlinJavaC#

Web

8
HTMLCSSSvelteSvelteKitAngularJSAngularASP.NET.NET

Infra / Homelab

7
DockerAnsibleLinuxUnraidTailscaleCaddyCI/CD

Security

5
CybersecurityNetwork SecurityIAMPrologPAM

Embedded / BLE

5
ESP32BLEDexcom G7NightscoutKotlin Multiplatform

Ops / Data

5
SQLiteVictoriaMetricsGrafanaslogWebGL
Go
Rust
TypeScript
JavaScript
Python
Kotlin
Java
C#
HTML
CSS
Svelte
SvelteKit
AngularJS
Angular
ASP.NET
.NET
Docker
Ansible
Linux
Unraid
Tailscale
Caddy
CI/CD
SQLite
VictoriaMetrics
Grafana
slog
WebGL
Cybersecurity
Network Security
IAM
Prolog
PAM
ESP32
BLE
Dexcom G7
Nightscout
Kotlin Multiplatform
10

Under the hood

this site, in code

Every component on this page is a Go function. No React, no npm, no build pipeline for the markup — the server renders HTML, Datastar adds reactivity, and SVG charts are computed at request time.

Browser
no framework runtime — Datastar (14 kB) only
HTTPS · one round trip
Caddy ingress
TLS, CrowdSec + Authelia in front
reverse proxy
One Go binary
gomponents render HTML · SSE patches fragments · SVG charts computed per request
175
UI components
0
npm runtime deps
4×2
themes × modes
1
binary to deploy
5 real excerpts from this site

The arc math behind the gauges in the open-source section.

ui/data/gauge.go
Go
// Gauge renders a circular gauge as inline SVG.
// Zero JS, zero dependencies — pure server-side Go.
func Gauge(p GaugeProps) g.Node {
	cx, cy := float64(p.Size)/2, float64(p.Size)/2
	radius := float64(p.Size) * 0.38
	strokeW := float64(p.Size) * 0.1

	// Arc spans 270° (from 135° to 45°)
	startAngle := 135.0
	totalAngle := 270.0
	pct := (p.Value - p.Min) / (p.Max - p.Min)

	toRad := func(deg float64) float64 {
		return deg * math.Pi / 180
	}
	arcPt := func(deg float64) (float64, float64) {
		a := toRad(deg)
		return cx + radius*math.Cos(a),
			cy + radius*math.Sin(a)
	}
	arcPath := func(start, end float64, color string) string {
		x1, y1 := arcPt(start)
		x2, y2 := arcPt(end)
		large := 0
		if math.Abs(end-start) > 180 {
			large = 1
		}
		return fmt.Sprintf(
			'<path d="M %.1f %.1f A %.1f %.1f 0 %d 1 %.1f %.1f"
			   fill="none" stroke="%s" stroke-width="%.1f"
			   stroke-linecap="round"/>',
			x1, y1, radius, radius, large, x2, y2,
			color, strokeW)
	}

	// Track (full arc), then value arc on top
	sb.WriteString(arcPath(startAngle, startAngle+totalAngle, p.TrackColor))
	sb.WriteString(arcPath(startAngle, startAngle+totalAngle*pct, p.Color))
	// …
}

The homelab panel polls VictoriaMetrics — range queries over 40 days come back empty, so the attack heatmap is fetched in 30-day chunks.

projects/homepage/homelab/homelab.go
Go
// Attacks blocked per day, last ~12 months.
// VictoriaMetrics range queries spanning >40 days can return
// empty results (per-day index cutoff), so fetch the year in
// 30-day chunks and dedupe by day.
seenDay := map[string]bool{}
for chunk := 11; chunk >= 0; chunk-- {
	start := now.AddDate(0, 0, -30*(chunk+1))
	end := now.AddDate(0, 0, -30*chunk)
	pts, err := p.promQueryRange(ctx,
		"sum(increase(cs_bucket_overflowed_total[1d]))",
		start, end, 24*time.Hour,
	)
	if err != nil {
		continue // empty until a year of data exists
	}
	for _, pt := range pts {
		day := time.Unix(int64(pt[0]), 0)
		key := day.Format("2006-01-02")
		if pt[1] > 0 && !seenDay[key] {
			seenDay[key] = true
			s.AttackDays = append(s.AttackDays,
				DayValue{Date: day, Count: int(pt[1])})
		}
	}
}

This very carousel. Pages flip on a Datastar signal; the observer only reacts to display:none→visible, so the animation can never re-trigger itself.

ui/data/pagination.go
Go
// PaginatedPages: each page shown while the shared
// Datastar signal matches its index.
for i, page := range pages {
	wrapped[i] = h.Div(
		g.Attr("data-slot", "page"),
		ui.Show(fmt.Sprintf("$%s === %d", sig, i)),
		page,
	)
}

// Entrance animation replays exactly once per page switch:
// the observer only reacts to style mutations whose OLD value
// was display:none — the CSS animation itself can never
// re-trigger it.
var obs=new MutationObserver(function(muts){
  muts.forEach(function(m){
    var was=(m.oldValue||'');
    var wasHidden=was.indexOf('display:none')>-1;
    if(wasHidden&&m.target.style.display!=='none'){
      m.target.removeAttribute('data-anim');
      void m.target.offsetWidth;      // restart keyframes
      m.target.setAttribute('data-anim','');
    }
  });
});

Live updates without a framework: one attribute on the section, one SSE handler, Datastar morphs the panel in place.

projects/homepage/handlers.go
Go
// One attribute on the section…
h.Section(
	h.ID("homelab"),
	g.Attr("data-on-interval__duration.60s",
		"@get('/api/homelab')"),
	// …
)

// …one SSE handler on the server.
e.GET("/api/homelab", func(c echo.Context) error {
	sse := datastar.NewSSE(c.Response().Writer, c.Request())
	return sse.PatchElements(
		web.RenderToString(pages.HomelabPanel(snapshot())),
	)
})

// Datastar morphs #homelab-panel in place every 60 s:
// no reload, no virtual DOM, no client-side state to sync.

The skills radar — plain trigonometry rendered to an SVG polygon at request time.

ui/data/radarchart.go
Go
// Radar chart: axis i sits at angle 2πi/n, starting at
// 12 o'clock. Values scale along the spoke; the series
// becomes a single <polygon>.
angle := func(i int) float64 {
	return float64(i)*2*math.Pi/float64(n) - math.Pi/2
}
pt := func(radius float64, i int) (float64, float64) {
	a := angle(i)
	return cx + radius*math.Cos(a), cy + radius*math.Sin(a)
}

pts := make([]string, len(p.Axes))
for i := range p.Axes {
	scaled := (s.Values[i] / p.Max) * r
	x, y := pt(scaled, i)
	pts[i] = fmt.Sprintf("%.1f,%.1f", x, y)
}
sb.WriteString(fmt.Sprintf(
	'<polygon points="%s" fill="%s" fill-opacity="0.18"
	   stroke="%s" stroke-width="2"/>',
	strings.Join(pts, " "), color, color))
11

Get in touch

Let's talk

Open to interesting projects, thesis collaborations, and conversations about systems, security, and self-hosting.

Currently

  • MSc thesis @ Dynatrace — Prolog-based permission metamodel
  • Tutor for Digital Circuits @ JKU Linz
  • Building this site with Go · gomponents · Datastar