Compare commits

..

11 Commits

23 changed files with 647 additions and 40 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
public/
_gen/

View File

@ -6,24 +6,23 @@ Site generated with [Hugo][] using the [hermit-v2][] theme.
Build site:
```
$ docker compose up build
```bash
docker compose up build
```
Run development server with live refresh:
Run development server with live refresh and draft as well as future post
rendering enabled:
```
$ docker compose up server
```bash
docker compose up server
```
Add new posts:
```bash
docker compose up -d server
docker compose exec server new content/posts/2024-07-31-my-new-blog-post.md
```
$ docker compose up -d server
$ docker compose exec server new content/posts/2024-07-31-my-new-blog-post.md
```
[hermit-v2]: https://github.com/1bl4z3r/hermit-V2
[Hugo]: https:/gohugo.io

75
assets/images/favicon.svg Normal file
View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="83mm"
height="83mm"
viewBox="0 0 82.999996 82.999991"
version="1.1"
id="svg8"
inkscape:version="1.0 (1.0+r73+1)"
sodipodi:docname="Gänseliesel-Logo rund.svg"
inkscape:export-filename="/home/daniel/cloud/Photos/Hintergrundbilder/Gänseliesel-Logo rund.png"
inkscape:export-xdpi="162.82001"
inkscape:export-ydpi="162.82001">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4684"
inkscape:cx="108.33847"
inkscape:cy="178.35599"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
fit-margin-top="3"
fit-margin-left="3"
fit-margin-right="3"
fit-margin-bottom="3"
lock-margins="true" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:rights>
<cc:Agent>
<dc:title>(c) Daniel Kraus &lt;www.bovender.de&gt;</dc:title>
</cc:Agent>
</dc:rights>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-56.138771,-86.109581)">
<circle
r="39"
cy="128.10957"
cx="97.609604"
id="path857"
style="color:black;overflow:visible;fill:#696969;fill-opacity:1;stroke:none;stroke-width:2.00001;stroke-opacity:1" />
<path
sodipodi:nodetypes="cscsssccscccsscsssccccscccssscsscsssscsccccccccccssccccssscsscssssscscccccsccsccccccccc"
style="fill:navy;stroke:white;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:bevel"
d="m 73.66954,156.68256 c -0.0257,-0.0212 -0.04676,-1.16622 -0.04676,-2.54442 v -2.50582 l -0.622191,-0.38414 c -1.041429,-0.64296 -1.426937,-2.10829 -1.070799,-4.07019 0.185083,-1.01962 0.168352,-1.20734 -0.157396,-1.76658 -0.703944,-1.2085 -0.948192,-4.22473 -0.610203,-7.5353 0.109691,-1.07467 0.224045,-1.39705 0.642726,-1.81227 0.438724,-0.43508 0.509281,-0.65636 0.509281,-1.5972 0,-0.89228 0.136876,-1.37491 0.747939,-2.63718 1.591474,-3.28755 3.650313,-5.74902 5.158472,-6.16732 0.401471,-0.11129 1.546325,-0.20294 2.544116,-0.20351 2.028793,-0.001 3.643675,-0.45634 5.034194,-1.41896 1.09234,-0.75621 3.697965,-3.58834 4.44801,-4.83468 l 0.640805,-1.06481 -0.350243,-0.64968 c -0.192622,-0.35731 -0.668559,-0.90152 -1.057631,-1.20935 -1.214761,-0.96111 -1.402229,-2.68752 -0.442115,-4.07152 0.261205,-0.37652 0.474599,-0.84815 0.474215,-1.04805 -7.42e-4,-0.40984 -0.565068,-1.40157 -1.144496,-2.01146 -0.333922,-0.3515 -0.374963,-0.58219 -0.304777,-1.7134 0.0934,-1.5051 0.471711,-2.36391 1.241469,-2.81815 0.307214,-0.18128 0.711892,-0.69671 0.936083,-1.19225 0.504605,-1.11535 3.143032,-3.706003 4.442274,-4.361847 0.595113,-0.300396 1.406641,-0.523321 2.121739,-0.58282 1.085968,-0.09039 1.224711,-0.158 2.229284,-1.087097 1.278124,-1.182077 2.812644,-2.223967 4.230694,-2.872493 2.74258,-1.25428 8.56759,-0.434746 11.85918,1.668514 1.45844,0.931903 4.02461,3.493836 4.20038,4.193423 0.0692,0.27543 0.33015,0.70489 0.57988,0.95437 0.24974,0.24945 0.45406,0.61947 0.45406,0.82223 0,0.20277 0.28544,0.96864 0.63432,1.70193 0.89526,1.88167 1.1891,2.79911 1.4438,4.50792 0.32272,2.16504 0.2756,3.01135 -0.25124,4.51229 -0.47937,1.3657 -1.00207,2.09536 -3.25909,4.54957 -1.73736,1.88914 -1.93271,2.37824 -1.93271,4.83888 0,1.96414 -0.0203,2.0706 -0.44756,2.35027 -0.26617,0.17422 -0.62899,0.24744 -0.89525,0.18069 -0.63539,-0.15931 -1.43808,0.19667 -1.64004,0.72732 -0.22403,0.58862 -0.51601,0.75501 -1.23952,0.70633 -0.85373,-0.0574 -1.59229,0.26091 -1.45207,0.6259 0.1529,0.39806 -0.57173,1.1417 -1.24329,1.27587 -0.37802,0.0756 -0.62843,0.30247 -0.85117,0.77139 -0.48801,1.0273 -1.18448,1.42249 -2.51826,1.42886 -1.32822,0.007 -1.42602,-0.0484 -3.50099,-1.96244 -0.84898,-0.7831 -1.6061,-1.42254 -1.68248,-1.42098 -0.32474,0.007 -0.57603,0.3556 -1.20847,1.67785 -1.555805,3.25282 -1.657654,3.5644 -1.769822,5.41463 l -0.107571,1.77504 1.099652,0.74367 c 1.280911,0.86625 2.842061,2.13904 3.834611,3.12634 0.54014,0.53728 0.72766,0.89812 0.8249,1.58734 0.0693,0.49058 0.33931,1.26394 0.60021,1.71855 l 0.47434,0.82657 0.36743,-0.77988 c 0.20208,-0.42894 0.44653,-0.77989 0.54317,-0.77989 0.0967,0 0.29875,-0.29412 0.4491,-0.6536 0.15034,-0.35949 0.36134,-0.65361 0.46883,-0.65361 0.10757,0 0.14348,-0.084 0.0799,-0.18675 -0.0636,-0.10269 0.0156,-0.18674 0.1759,-0.18674 0.1603,0 0.29144,-0.083 0.29144,-0.18455 0,-0.1015 0.33649,-0.23828 0.74776,-0.30398 0.41126,-0.0656 0.74776,-0.18317 0.74776,-0.26105 0,-0.0778 0.2734,-0.26955 0.60755,-0.42593 1.04677,-0.48989 4.87233,-0.18305 5.95124,0.47733 0.61483,0.37632 1.42997,1.87491 1.76605,3.24673 0.35754,1.45941 0.66483,2.03534 1.40645,2.63593 0.28695,0.23237 0.58092,0.69177 0.65328,1.02089 0.0723,0.32911 0.36623,0.89531 0.65304,1.25821 0.71105,0.89969 0.92402,1.82361 0.9269,4.02122 0.001,1.02709 0.0901,2.40659 0.19706,3.06554 0.16565,1.01985 0.15054,1.24214 -0.10161,1.49396 -17.98696,11.95593 -33.854294,9.38426 -47.53174,0.0543 z M 90.631571,114.6264 c 0.104392,0 0.189694,-0.093 0.189694,-0.20673 0,-0.11368 -0.13049,-0.15667 -0.290125,-0.0956 -0.159555,0.0611 -0.242313,0.0339 -0.183891,-0.0605 0.175174,-0.28313 -0.269127,-0.43381 -0.562339,-0.19072 -0.284613,0.23596 -0.355038,0.86752 -0.154852,1.38867 0.09485,0.24697 0.183931,0.19621 0.464597,-0.26485 0.190979,-0.31371 0.432591,-0.57038 0.536916,-0.57038 z m -0.917191,0.0778 c 0.0093,-0.21755 0.05326,-0.2618 0.113003,-0.11288 0.05405,0.13481 0.04743,0.29587 -0.01471,0.35794 -0.06213,0.0621 -0.106247,-0.0483 -0.09817,-0.24511 z"
id="path935" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,68 @@
// I got the key, I got the secret…
let key = 'mastodon-instance';
let instance = localStorage.getItem(key);
// get the link from the DOM
const button = document.querySelector('.mastodon-share');
// refresh the link with the instance name
const refreshlink = (instance) => {
button.href = `https://${instance}/share?text=${encodeURIComponent(document.title)}%0A${encodeURIComponent(location.href)}`;
}
// got it? Let's go!
if (button) {
// labels and texts from the link
let prompt = button.dataset.prompt || 'Please tell me your Mastodon instance';
let editlabel = button.dataset.editlabel || 'Edit your Mastodon instance';
let edittext = button.dataset.edittext || '✏️';
// Ask the user for the instance name and set it…
const setinstance = _ => {
instance = window.prompt(prompt, instance);
if(instance) {
localStorage.setItem(key, instance);
createeditbutton();
refreshlink(instance);
button.click();
}
}
// create and insert the edit link
const createeditbutton = _ => {
if (document.querySelector('button.mastodon-edit')) return;
let editlink = document.createElement('button');
editlink.innerText = edittext;
editlink.classList.add('mastodon-edit');
editlink.title = editlabel;
editlink.ariaLabel = editlabel;
editlink.addEventListener('click', (e) => {
e.preventDefault();
localStorage.removeItem(key);
setinstance();
});
button.insertAdjacentElement('afterend', editlink);
}
// if there is a value in localstorage, create the edit link
if(localStorage.getItem(key)) {
createeditbutton();
}
// When a user clicks the link
button.addEventListener('click', (e) => {
// If the user has already entered their instance
// and it is in localstorage write out the link href
// with the instance and the current page title and URL
if(localStorage.getItem(key)) {
refreshlink(localStorage.getItem(key));
// otherwise, prompt the user for their instance and save it to localstorage
} else {
e.preventDefault();
setinstance();
}
});
}

View File

@ -0,0 +1,54 @@
// Colors
$theme: hsl(172, 99%, 26%);
$text: hsl(204, 28%, 93%);
$light-grey: #292e32; // #494f5c;
$dark-grey: #3B3E48;
$highlight-grey: #7d828a;
$midnightblue: #2c3e50;
$typewriter: hsl(172, 100%, 36%);
// Fonts
$fonts: "IBM Plex Sans Light", "Trebuchet MS", Verdana, "Verdana Ref", "Segoe UI", Candara, "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Tahoma, sans-serif;
$code-fonts: Consolas, "Andale Mono WT", "Andale Mono", Menlo, Monaco, "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", Courier, "YaHei Consolas Hybrid", monospace, "Segoe UI Emoji", "PingFang SC", "Microsoft YaHei";
//Admonition
$admonition-background: (
'note': rgba(68, 138, 255, 0.1),
'info': rgba(0, 184, 212, 0.1),
'tip': rgba(0, 191, 165, 0.1),
'success': rgba(0, 200, 83, 0.1),
'warning': rgba(255, 145, 0, 0.1),
'failure': rgba(255, 82, 82, 0.1),
'danger': rgba(255, 23, 68, 0.1),
'bug': rgba(245, 0, 87, 0.1),
) !default;
$admonition-color: (
'note': #448aff,
'info': #00b8d4,
'tip': #00bfa5,
'success': #00c853,
'warning': #ff9100,
'failure': #ff5252,
'danger': #ff1744,
'bug': #f50057,
) !default;
// Mixins
@mixin dimmed {
opacity: .6;
}
@mixin aTag {
a {
word-wrap: break-word;
border: none;
box-shadow: inset 0 -4px 0 $theme;
transition-property: box-shadow;
transition-duration: .1s;
&:hover {
box-shadow: inset 0 -1em 0 $theme;
}
}
}

View File

@ -1,5 +1,6 @@
baseURL = 'https://bovender.de/'
baseURL = 'https://www.bovender.de/'
languageCode = 'en-us'
defaultContentLanguage = 'en'
title = 'bovender'
theme = "hermit-v2"
@ -26,13 +27,12 @@ lastmod = ["lastmod", ":git", "date", "publishDate"]
publishDate = ["publishDate", "date"]
expiryDate = ["expiryDate"]
[params.author]
name = "Daniel Kraus"
about = "CHANGE SITE AUTHOR ABOUT"
about = "/about"
[blackfriday]
# hrefTargetBlank = true
hrefTargetBlank = true
# noreferrerLinks = true
# nofollowLinks = true
@ -58,14 +58,16 @@ expiryDate = ["expiryDate"]
dateformNum = "2006-01-02"
dateformNumTime = "2006-01-02 15:04 -0700"
# description = "CHANGE ME SITE DESC RIPTION"
description = "Daniel Kraus' personal homepage"
# images = [""]
themeColor = "#494f5c"
themeColor = "#292e32"
homeSubtitle = "Daniel Kraus"
footerCopyright = "all rights reserved"
# bgImg = ""
gitUrl = "https://github.com/1bl4z3r/hermit-V2/tree/staging"
ShowLastmod = true
gitUrl = "https://git.bovender.de/daniel/blog"
justifyContent = true
@ -75,8 +77,8 @@ expiryDate = ["expiryDate"]
homeSubtitlePrinter = true
scrollToTop = true
global_mathjax = false
# readTime = true
# readTimeSeparator = "CHANGE ME READ TIME"
readTime = false
readTimeSeparator = "~"
# legacyLayout = false
shareSocial = true
# googleTagManager = "GTM-XXXXXXXX"
@ -85,8 +87,8 @@ expiryDate = ["expiryDate"]
# pinned = "Pinned Posts"
# pinnedSVGname = "pin"
# descriptionInPosts= true
# initialPublish = "Initally Posted on: "
# human = ["single","posts"]
initialPublish = "Initally Posted on: "
human = ["single","posts"]
[[params.socialLinks]]
name = "mastodon"
@ -111,11 +113,16 @@ expiryDate = ["expiryDate"]
[menu]
[[menu.main]]
name = "Posts"
name = "Blog"
url = "posts/"
weight = 10
[[menu.main]]
name = "About"
name = "About bovender"
url = "about/"
weight = 20
weight = 20
[[menu.main]]
name = "Impressum"
url = "impressum/"
weight = 30

BIN
content/about/ggap-ev.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

View File

@ -1,8 +1,47 @@
---
title: "Content Placeholder"
_build:
render: never
list: never
publishResources: false
title: "About bovender"
toc: true
---
I'm a physician-scientist from Germany.
[Bovenden](https://www.bovenden.de) is the name of the village/small town
in lovely Lower Saxony, Germany, where I grew up. Hence I'm a bovender --
not _the_ bovender, of course, just one of many, but proud to be one :-)
Computers have been part of my life ever since I programmed my dad's
calculator back in the 1980's.
## Portfolio -- websites
### [ggap-ev.org](https://ggap-ev.org)
{{< figure src="ggap-ev.png">}}
### [nephrowiki.de](https://nephrowiki.de)
{{< figure src="nephrowiki.png">}}
## Portfolio -- software
### [Daniel's XL Toolbox](https://xltoolbox.net)
{{< figure src="xltoolbox.png">}}
### [LinkTitles](https://github.com/bovender/linktitles)
LinkTitles is a [MediaWiki](https://mediawiki.org) extension that automatically
links terms to existing pages in a Wiki.
### [PubmedParser](https://github.com/bovender/pubmedparser)
PubmedParser is a [MediaWiki](https://mediawiki.org) extension to include and
reference articles from [Pubmed](https://pubmed.gov) by PMID.
## Server administration
I have 10+ years experience with running and administrating my own server.
This includes running a mail and an IMAP server, hosting my own
[Nextcloud](https://nextcloud.com) and [Gitea](https://gitea.io) instances,
[Mastodon for Nephrology](https://neph.social)
and more. Almost all of my services are dockerized.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

BIN
content/about/xltoolbox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

46
content/impressum.md Normal file
View File

@ -0,0 +1,46 @@
---
title: "Impressum und Datenschutz"
date: 2024-07-31T12:42:53Z
draft: false
---
Dr. Daniel Kraus
H&zwnj;ö&zwnj;hen&zwnj;str&zwnj;aße 1&zwnj;5
65451 K&zwnj;e&zwnj;l&zwnj;s&zwnj;t&zwnj;e&zwnj;r&zwnj;b&zwnj;a&zwnj;c&zwnj;h
Tel. (0 61 07&zwnj;) 7 5&zwnj;6 88 4&zwnj;0
<bovender@bovender.de>
Ich bitte, von Anrufen abzusehen. Über Mail oder die verlinkten
sozialen Netzwerke (siehe Icons) bin ich i.d.R. kurzfristig
erreichbar.
## Mailserver bovender.de
Der Mailserver bovender.de ist zuständig für die Domains:
- [bantel-stiftung.de](https://bantel-stiftung.de)
- [bantelstiftung.de](https://bantelstiftung.de)
- [bovender.de](https://bovender.de)
- [gemeinsam-gegen-armut.org](https://gemeinsam-gegen-armut.org)
- [ggap-ev.org](https://ggap-ev.org)
- [mainzer-niere.de](https://mainzer-niere.de)
- [neph.social](https://neph.social)
- [nephrowiki.de](https://nephrowiki.de)
- [nierenverein.de](https://nierenverein.de)
- [xltoolbox.net](https://xltoolbox.net)
## Datenschutz
Diese Website erfasst keine personenbezogenen Daten, und es werden keine
Dienste von Drittfirmen in Anspruch genommen.
Es findet eine anonymisierte Erfassung von Seitenbesuchen statt, die keine
Rückverfolgung zu einzelnen Personen/Geräten ermöglicht.
## Dank
Besonderer Dank an [Christian Heilmann][] für das Script [mastodon-share][],
um Links leicht auf Mastodon zu posten.
[Christian Heilmann]: https://christianheilmann.com/2023/08/18/adding-a-share-to-mastodon-link-to-any-web-site-and-here/
[mastodon-share]: https://github.com/codepo8/mastodon-share

View File

@ -0,0 +1,204 @@
---
title: "Experience with running Fedora Linux on a Thinkpad P14s Gen 5"
description: "Everything works out of the box, but the keyboard and the battery leave something to be desired."
date: 2024-08-05T21:00:00Z
draft: false
toc: true
scrolltotop: true
tags:
- Thinkpad
- Linux
- Fedora
- NVIDIA
---
I have recently acquired a Lenovo Thinkpad P14s Gen 5. As of the time of writing
-- summer of '24 -- these machines are brand new, and so is their architecture:
Intel Core Ultra (Meteor Lake) with a dedicated NVIDIA GPU. Here I report my
experience with running Linux with the [KDE Plasma][] desktop on this machine.
My previous daily driver was a T480s (see my old blog post over at [xltoolbox.net][]
for a report). I also administer two different X1 Carbons (5th generation and
9th generation), however, I don't use these very often myself.
Here are the specs (the 1 TB SSD has been swapped for a Samsung 990 PRO with 2 TB).
```plain
daniel@seppel9 ~> fastfetch
.',;::::;,'. daniel@seppel9
.';:cccccccccccc:;,. --------------
.;cccccccccccccccccccccc;. OS: Fedora Linux 40 (KDE Plasma) x86_64
.:cccccccccccccccccccccccccc:. Host: 21G3S00A00 (ThinkPad P14s Gen 5)
.;ccccccccccccc;.:dddl:.;ccccccc;. Kernel: Linux 6.9.11-200.fc40.x86_64
.:ccccccccccccc;OWMKOOXMWd;ccccccc:. Uptime: 1 hour, 47 mins
.:ccccccccccccc;KMMc;cc;xMMc;ccccccc:. Packages: 4338 (rpm)
,cccccccccccccc;MMM.;cc;;WW:;cccccccc, Shell: fish 3.7.0
:cccccccccccccc;MMM.;cccccccccccccccc: Display (LEN8AB1): 3072x1920 @ 120 Hz (as 2048x1280) in 14″ [Built-in]
:ccccccc;oxOOOo;MMM000k.;cccccccccccc: DE: KDE Plasma 6.1.3
cccccc;0MMKxdd:;MMMkddc.;cccccccccccc; WM: KWin (Wayland)
ccccc;XMO';cccc;MMM.;cccccccccccccccc' WM Theme: Breeze
ccccc;MMo;ccccc;MMW.;ccccccccccccccc; Theme: Breeze (Dark) [Qt], Breeze [GTK3]
ccccc;0MNc.ccc.xMMd;ccccccccccccccc; Icons: breeze-dark [Qt], breeze-dark [GTK3/4]
cccccc;dNMWXXXWM0:;cccccccccccccc:, Font: IBM Plex Sans (10pt) [Qt], IBM Plex Sans (10pt) [GTK3/4]
cccccccc;.:odl:.;cccccccccccccc:,. Cursor: breeze (24px)
ccccccccccccccccccccccccccccc:'. Terminal: konsole 24.5.2
:ccccccccccccccccccccccc:;,.. CPU: Intel(R) Core(TM) Ultra 7 155H (22) @ 4,80 GHz
':cccccccccccccccc::;,. GPU 1: Intel rc Graphics @ 2,25 GHz [Integrated]
GPU 2: NVIDIA RTX 500 Ada Generation Laptop GPU
Memory: 9,13 GiB / 62,29 GiB (15%)
Swap: 302,50 MiB / 104,00 GiB (0%)
Disk (/): 18,77 GiB / 146,59 GiB (13%) - ext4
Disk (/home): 524,56 GiB / 1,55 TiB (33%) - ext4
Local IP (wlp0s20f3): 192.168.3.114/24
Battery: 93% [AC Connected]
Locale: en_US.UTF-8
```
## Difficulties and finally success with installing Linux
At first, I was totally unable to install [KDE neon][], my preferred Linux distribution,
on this system. I freaked out. (I don't care if it's officially a 'distribution' or not.)
The live CD just would not boot. It did work in safe graphics mode, but when I installed
the system onto the laptop, I was once again unable to boot into Plasma.
(I already posted in the [KDE forum][] about this).
At some point it occurred to me that I may need to try a distribution, so I tried [Fedora][]
-- and it worked!! In order to boot the live CD, I also had to choose basic graphics mode
just like with KDE neon (which is Ubuntu under the hood). Once I had the live desktop up
and running, I could enable the NVIDIA repositories, so that the NVIDIA drivers were
included during system installation. Luckily, the Fedora Project provides a [KDE spin][]
so that I could continue to use my favorite desktop environment.
## Hardware
Except for the initial difficulties getting this system with a dedicated NVIDIA GPU
to run Linux, everything else just works out of the box. Nice! :-)
The **trackpoint** works as usual. This is really the main reason why I keep buying
Thinkpads. A laptop without trackpoint is a no-go for me. In fact, I did consider buying
a MacBook Pro, but the absence of a trackpoint and the uncertainty whether I could do
my beloved Linux foo with MacOS made me stick with a Thinkpad.
The **fingerprint scanner** is integrated into the power button. While not essential, it's
a nice gimmick and KDE Plasma provides a pretty UI to set it up. Currently, logging
into the system after booting is not (yet) supported, but unlocking (e.g., after resume
from sleep) works very well.
The 3k **screen** is really good, it's very bright and super crisp. At 100%, the
user interface is quite tiny. Luckily, with Wayland, fractional scaling is now
easy to accomplish and reliable. With a scale factor of 1.2 (120%), I am very happy
with my P14s' display. Interestingly though, the corners are rounded, even though
the laptop frame has sharp corners. I tend to think: If you have enough time wondering
about something like this, it's probably time to take a break and do something else
for a while.
Unfortunately, the **keyboard** is the worst that I have ever had in any Thinkpad.
It feels like typing on jelly. Luckily, for most of the heavy-duty work, I connect
the laptop to a Thunderbolt dock with a proper mechanical keyboard attached.
I wonder why Lenovo does not equip this machine with the same keyboard as in the
other models -- given the price tag of this machine, the extra bucks surely cannot
make such a big difference?
**Camera**, mike, and speakers just work. No problem running Zoom. I have not yet
tried out Teams.
## Form factor and weight
The P14s is somewhat bigger than the old T480s and certainly somewhat heavier.
Before deciding on the purchase, I carefully thought about my use cases and decided
that I can live with an extra 200-300 grams that I mostly only carry onto and
off from the commute train, as well as on my bicycle's rack. Therefore, I made a
decision for the extra performance (with dedicated GPU, which the alternative
models, i.e. X1 Carbons or T14s's do not offer).)
Lenovo [says][p14s-weight] the P14s starts at 1.6 kg, which compares to a MacBook Pro's
nominal weight. On our kitchen scale, my P14s weighs 1.74 kg.
In real life, the laptop's body is somewhat bigger than the actual casing, because
it has a very long "foot" underneath it. This ensures proper ventilation, because
the two fans blow out the warm air underneath the laptop. While this "foot" makes
the P14s rather thick, it turns out that this also provides a good grip when pulling
it ouf of a bag or carrying it around.
I have yet to come to terms with the new camera casing that all new Thinkpads
seem to have nowadays.
{{< figure src="p14s -camera-casing.jpg"
alt="A photograph of the camera casing of a Thinkpad P14s Gen 5"
caption="The camera casing. It disrupts the smooth surface of the Thinkpad.">}}
{{< figure src="p14s-foot.jpg"
alt="A photograph of the 'foot' underneath a Thinkpad P14s Gen 5"
caption="The 'foot' underneath the P14s makes it thicker, but also provides a good grip on the machine.">}}
## Performance
Compared to the old T480s, the performance gain of the Intel Core Ultra and the
dedicated NVIDIA GPU is very noticeable. Whether I compile R packages or analyze
clinical data with ~80k subjects in [RStudio][], develop RAW images in [Darktable][],
or work with Office in a VirtualBox-hosted Windows machine, everything is very
snappy. For instance, a typical RAW image is now processed in under 1 second, as
opposed to ~10 seconds on the T480s.
The machine wakes from sleep (suspend to RAM) extremely quickly, I guess this is due to
[novel suspend mechanisms][s3]? On the other hand, boot times are rather slow
(34-40s on AC power, T480s on battery 31 s!!).
## Fan
The fans spin up quickly, but the noise is not unpleasant. Maybe I can tweak the
fan control in order to have them spin up a little more lazily. But when I had both
my old laptop and the new one side by side, I realized that the T480s' fan noise
drowns the P14s' fan noise. Notably, the P14s was running on AC power, while the
T480s ran on battery. In fact, even the T480s with built-in graphics had its fan
running most of the time when I was working with it (academic work, researching,
writing, data analysis etc.).
## Energy consumption
The P14s' battery has much more capacity than the T480s' one, 75 Wh vs. 42 Wh.
However, with my normal work load, the battery drains rather quickly. The
following screenshot shows the charge level over time as I sat outside,
editing a manuscript with Word running in a virtual machine (VirtualBox
with Windows 11 guest) and doing some internet research in a browser. The
screen brightness was set to 100%. After some 3.5 hours, it's time for a
break...
{{< figure src="p14s-battery-drain.png">}}
## Making the switch from Ubuntu to Fedora
When I downloaded the Fedora [KDE spin][], I was admittedly a bit anxious.
I had been working with Ubuntu and KDE neon, which is based on Ubuntu,
for many years, and I wondered if Fedora would be very different.
It's not.
The three things that are really different from my perspective:
- To install something on the command line, use `dnf` rather than `apt`:
```bash
sudo dnf install good-stuff
```
- Removable disks (USB drives) are mounted on `/run/media/<USER>` rather
than `/media/<USER>`.
- More up-to-date kernel and software
## Conclusion
All in all, I am quite happy with the P14s. In the past couple of weeks, it has
already proven to be a reliable work horse, and this is what I need. The
keyboard really should be better, but hey, life is not perfect, is it?
[Darktable]: https://darktable.org
[Fedora]: https://fedoraproject.org/
[KDE forum]: https://discuss.kde.org/t/unable-to-start-kde-neon-plasma-on-core-ultra-nvidia-rtx-500-ada/18578
[KDE neon]: https://neon.kde.org
[KDE plasma]: https://kde.org/plasma-desktop/
[KDE spin]: https://fedoraproject.org/spins/
[p14s-weight]: https://www.lenovo.com/us/en/p/laptops/thinkpad/thinkpadp/thinkpad-p14s-gen-5-(14-inch-intel)-mobile-workstation/21g2002cus#tech_specs
[rstudio]: https://posit.co/products/open-source/rstudio
[s3]: https://en.wikipedia.org/wiki/ACPI#S3
[xltoolbox.net]: https://www.xltoolbox.net/blog/2018/08/exit-thinkpad-t430s-enter-thinkpad-t480s.html

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

View File

@ -1,13 +1,15 @@
services:
build:
image: klakegg/hugo:ext-alpine
image: hugomods/hugo:latest
command: hugo
volumes:
- ".:/src"
user: 1000:1000
server:
image: klakegg/hugo:ext-alpine
command: server
image: hugomods/hugo:latest
command: server --buildDrafts --buildFuture
volumes:
- ".:/src"
ports:
- "1313:1313"
- "127.0.0.1:1313:1313"
user: 1000:1000

View File

@ -0,0 +1,16 @@
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://matomo.bovender.de/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '1']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->

View File

@ -0,0 +1,22 @@
{{- with .Params.description }}<p>{{.}}</p>{{- end }}
{{- if and .Params.author .Params.authorLink}}{{ $relreflink := relref . .Params.authorLink }}<p>{{ partial "svg.html" (dict "context" . "name" "author") }}<a href="{{ $relreflink }}" target="_blank">{{ .Params.author }}</a></p>
{{- else if .Params.author }}{{ $relreflink := relref . .Site.Params.author.about }}<p>{{ partial "svg.html" (dict "context" . "name" "author") }}<a href="{{ $relreflink }}" target="_blank">{{ .Params.author }}</a></p>
{{- else }}{{ $relreflink := relref . .Site.Params.author.about }}<p>{{ partial "svg.html" (dict "context" . "name" "author") }}<a href="{{ $relreflink }}" target="_blank">{{ .Site.Params.author.name }}</a></p>
{{- end }}
{{- with .Params.tags }}
<p>{{- partial "svg.html" (dict "context" . "name" "posts_single_tags") -}}{{- range . -}}<span class="tag"><a href="{{ "tags/" | absLangURL }}{{ . | urlize }}">{{.}}</a></span>{{- end }}</p>
{{- end }}
{{- with .Params.categories }}
<p>{{- partial "svg.html" (dict "context" . "name" "posts_single_categories") -}}{{- range . -}}<span class="category"><a href="{{ "categories/" | absLangURL }}{{ . | urlize }}">{{.}}</a></span>{{- end }}</p>
{{- end }}
<p>{{- partial "svg.html" (dict "context" . "name" "posts_single_date") }}{{ dateFormat .Site.Params.dateformNumTime .Date.Local -}}
{{- if and (not (eq .Page.Params.ShowLastmod nil)) (.Page.Params.ShowLastmod) -}}
{{- if and .GitInfo .Site.Params.gitUrl -}}
[{{- partial "svg.html" (dict "context" . "name" "posts_single_git_commit") -}}<a href="{{ .Site.Params.gitUrl -}}{{ .GitInfo.Hash }}" target="_blank" rel="noopener">{{ .GitInfo.AbbreviatedHash -}}</a> @ {{ dateFormat .Site.Params.dateformNum .GitInfo.AuthorDate.Local -}}]
{{- else if not (eq .Lastmod .Date ) -}}
&nbsp;[{{.Site.Params.initialPublish | default "Initial Published on : "}} {{ dateFormat .Site.Params.dateformNumTime .Lastmod.Local -}}]
{{- else -}}
{{ errorf "Lastmod is not found in Page Frontmatter or Lastmod is same as Date" }}
{{- end -}}
{{- end -}}
</p>

View File

@ -0,0 +1,37 @@
<button id="share-btn" class="hdr-btn" title="{{i18n "share"}}">{{- partial "svg.html" (dict "context" . "name" "share") -}}</button>
<div id="share-links" class="animated fast">
{{ $title := .Title }}
{{ $url := printf "%s" .Permalink }}
{{ $author := (.Params.author | default .Site.Params.author.name) }}
{{ $summary := print $title ", by " $author "\n\n" .Params.description "\n" }}
<ul>
<li>
<a href="#" rel="noreferrer noopener"
target="mastodon"
data-prompt="Please tell me your Mastodon instance"
data-edittext="✏️"
data-editlabel="Edit your Mastodon instance"
class="mastodon-share">
Share to Mastodon
</a>
{{ $mastodon_share := resources.Get "js/mastodon-share.js" | js.Build "mastodon-share.js" }}
<script src="{{ $mastodon_share.RelPermalink }}" defer></script>
</li>
<li>
<a href="https://twitter.com/intent/tweet?hashtags=hermit2&amp;url={{ .Permalink }}&amp;text={{ .Title }}" target="_blank" rel="noopener" aria-label="Share on X">{{- partial "svg.html" (dict "context" . "name" "x") -}}</a>
</li>
<li>
<a href="https://facebook.com/sharer/sharer.php?u={{ .Permalink }}" target="_blank" rel="noopener" aria-label="Share on Facebook">{{- partial "svg.html" (dict "context" . "name" "facebook") -}}</a>
</li>
<li>
<a href="mailto:?subject={{ .Title }}&amp;body={{ .Permalink }}" target="_self" rel="noopener" aria-label="Share on Email">{{- partial "svg.html" (dict "context" . "name" "email") -}}</a>
</li>
<li>
<a href="https://www.linkedin.com/shareArticle?mini=true&amp;url={{ $url }}&amp;source={{ .Site.BaseURL }}&amp;title={{ $title }}&amp;summary={{ $summary }}" target="_blank" rel="noopener" aria-label="Share on LinkedIn">{{- partial "svg.html" (dict "context" . "name" "linkedin") -}}</a>
</li>
<li>
<a href="#" onclick="linkShare({{ $title }},{{ $url }},{{ $summary }}); return false;" target="_self" rel="noopener" aria-label="Copy Link">{{- partial "svg.html" (dict "context" . "name" "share_2") -}}</a>
</li>
</ul>
</div>

View File

@ -0,0 +1,38 @@
<figure{{ with .Get "class" }} class="{{ . }}"{{ end }}>
{{- if .Get "link" -}}
<a href="{{ .Get "link" }}"{{ with .Get "target" }} target="{{ . }}"{{ end }}{{ with .Get "rel" }} rel="{{ . }}"{{ end }}>
{{- end -}}
{{- $u := urls.Parse (.Get "src") -}}
{{- $src := $u.String -}}
{{- if not $u.IsAbs -}}
{{- with or (.Page.Resources.Get $u.Path) (resources.Get $u.Path) -}}
{{- $src = .RelPermalink -}}
{{- end -}}
{{- end -}}
<img src="{{ $src }}"
{{- if or (.Get "alt") (.Get "caption") }}
alt="{{ with .Get "alt" }}{{ . }}{{ else }}{{ .Get "caption" | markdownify| plainify }}{{ end }}"
{{- end -}}
{{- with .Get "width" }} width="{{ . }}"{{ end -}}
{{- with .Get "height" }} height="{{ . }}"{{ end -}}
{{- with .Get "loading" }} loading="{{ . }}"{{ end -}}
><!-- Closing img tag -->
{{- if .Get "link" }}</a>{{ end -}}
{{- if or (or (.Get "title") (.Get "caption")) (.Get "attr") -}}
<figcaption>
{{ with (.Get "title") -}}
<h4>{{ . }}</h4>
{{- end -}}
{{- if or (.Get "caption") (.Get "attr") -}}<p>
{{- .Get "caption" | markdownify -}}
{{- with .Get "attrlink" }}
<a href="{{ . }}">
{{- end -}}
{{- .Get "attr" | markdownify -}}
{{- if .Get "attrlink" }}</a>{{ end }}</p>
{{- end }}
</figcaption>
{{- end }}
</figure>

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"Target":"css/style.min.3b715be5bd264701c0fc591b2c4a36421d10ed026ad15fcf6d2f91991d4a77a7.css","MediaType":"text/css","Data":{"Integrity":"sha256-O3Fb5b0mRwHA/FkbLEo2Qh0Q7QJq0V/PbS+RmR1Kd6c="}}

5
update-blog.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
pushd /home/daniel/local/Code/blog
docker compose up build && rsync -av --delete public/* bovender.de:/var/www/bovender/
popd