Compare commits

..

No commits in common. "b12087238b3ec27876a452f5cc96f34fbf305716" and "2fc3b7bb7ddaae093b5df5e4371835920b2e015b" have entirely different histories.

73 changed files with 651 additions and 469 deletions

52
.github/workflows/main.yml vendored Normal file
View file

@ -0,0 +1,52 @@
name: Deploy Hugo site to Pages
on:
push:
branches: ["main"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
defaults:
run:
shell: bash
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@main
with:
submodules: true
fetch-depth: 0
- name: Setup Pages
id: pages
uses: actions/configure-pages@main
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/flake-checker-action@main
- name: Build with Hugo
run: nix run .
- name: Upload to GitHub Pages
uses: actions/upload-pages-artifact@main
with:
path: ./public
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@main

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
/public/
.hugo_build.lock
.direnv

View file

@ -1,7 +0,0 @@
[[language]]
name = "css"
auto-format = false
[[language]]
name = "html"
auto-format = false

View file

@ -1,7 +1,7 @@
# Webseite von Jan Kremer
[Webseite](https://jankremer.de)
[Webseite](https://jankremer.eu)
## Lizenz
CC0 1.0 | Jan Kremer | 20212026
CC0 1.0 \| Jan Kremer \| 20212025

7
archetypes/blog.md Normal file
View file

@ -0,0 +1,7 @@
---
title: {{ replace .Name "-" " " | title }}
date: {{ .Date }}
description:
tags:
draft: true
---

5
archetypes/default.md Normal file
View file

@ -0,0 +1,5 @@
---
title: {{ replace .Name "-" " " | title }}
date: {{ .Date }}
draft: true
---

7
archetypes/photos.md Normal file
View file

@ -0,0 +1,7 @@
---
title: {{ replace .Name "-" " " | title }}
date: {{ .Date }}
description:
tags:
draft: true
---

View file

@ -157,7 +157,6 @@ svg {
margin: 0.5rem;
vertical-align: middle;
fill: light-dark(var(--uchu-yin), var(--uchu-yang));
@media (prefers-color-scheme: dark) {
path {
fill: white;
@ -207,7 +206,7 @@ article {
height: auto;
margin: 0;
figcaption>p {
figcaption > p {
margin: 0.25rem 0 2rem;
font-family: var(--sans-serif);
text-align: center;
@ -219,7 +218,7 @@ article {
height: auto;
}
>p:nth-of-type(2)::first-letter {
> p:nth-of-type(2)::first-letter {
font-size: 3.3rem;
float: left;
line-height: 3rem;
@ -303,7 +302,6 @@ footer {
width: 0.75rem;
vertical-align: middle;
margin: 0 1px;
@media (prefers-color-scheme: dark) {
path {
fill: white;
@ -346,14 +344,24 @@ footer {
}
}
.giallo {
border: 1px solid light-dark(var(--uchu-gray), var(--uchu-dark-gray));
code {
font-family: var(--mono);
border-radius: 0.3rem;
font-size: 0.8rem;
margin: 0;
padding: 0 1rem;
}
.giallo-l {
.highlight {
font-family: var(--mono);
padding: 1rem;
border: 1px solid light-dark(var(--uchu-gray), var(--uchu-dark-gray));
border-radius: 0.3rem;
margin: 1rem 0;
padding: 0 1rem;
overflow: auto;
display: block;
pre {
margin: 0;
padding: 0;
}
}

View file

@ -1,6 +1,2 @@
+++
title = "Jan Kremer"
sort_by = "date"
template = "index.html"
page_template = "blog-page.html"
+++
---
---

View file

@ -1,13 +1,12 @@
+++
title = "Über mich"
date = 2024-12-12
updated = 2026-03-17
+++
---
title: Über mich
date: 2024-12-12
---
Mein Name ist *Jan Kremer*. Ich bin 29 Jahre alt und habe *Pharmazie* studiert. Manchmal schreibe ich über Technik und Software die ich benutze.
Mein Name ist _Jan Kremer_. Ich bin 29 Jahre alt und bin *Apotheker*. Manchmal schreibe ich über Technik und Software die ich benutze.
Wenn ich nicht gerade lerne, mache ich gerne Sport, vor allem Joggen, Kraftsport und Tanzen.
## Kontakt
[mail@jankremer.de](mailto:mail@jankremer.de)
[mail@jankremer.eu](mailto:mail@jankremer.eu)

View file

@ -1,6 +0,0 @@
+++
title = "Blog"
sort_by = "date"
template = "blog.html"
page_template = "blog-page.html"
+++

View file

@ -1,23 +1,13 @@
+++
title = "Discord"
date = 2026-02-16T19:45:02+01:00
tags = [ "micro" ]
+++
---
title: Discord
date: 2026-02-16T19:45:02+01:00
tags: micro
---
Since
[Discord announced](https://discord.com/press-releases/discord-launches-teen-by-default-settings-globally)
it will start asking users for age verification, I became obsessed with reading
about alternatives to the platform. And there are a lot of them. As a
self-hoster, I immediately thought of Matrix and XMPP. Both have their pros and
cons and different implementations.
Since [Discord announced](https://discord.com/press-releases/discord-launches-teen-by-default-settings-globally) it will start asking users for age verification, I became obsessed with reading about alternatives to the platform. And there are a lot of them. As a self-hoster, I immediately thought of Matrix and XMPP. Both have their pros and cons and different implementations.
I was almost ready to pick one of them when I stopped and thought to myself,
_would I really use them?_
I was almost ready to pick one of them when I stopped and thought to myself, _would I really use them?_
And my answer is a clear: **No!**
I will not replace Discord because _I don't even use Discord now_. I haven't had
an account there for years. When I message my friends, it's either on Signal,
WhatsApp, or iMessage, which are all end-to-end-encrypted (E2EE) messengers. The
only thing I'm waiting for is E2EE RCS (Rich Communication Services) so I can
ditch WhatsApp at some point.
I will not replace Discord because _I don't even use Discord now_. I haven't had an account there for years. When I message my friends, it's either on Signal, WhatsApp, or iMessage, which are all end-to-end-encrypted (E2EE) messengers. The only thing I'm waiting for is E2EE RCS (Rich Communication Services) so I can ditch WhatsApp at some point.

View file

@ -1,9 +1,8 @@
+++
title = "Email"
date = 2026-02-20T15:46:52+01:00
tags = [ "micro" ]
+++
---
title: Email
date: 2026-02-20T15:46:52+01:00
description:
tags: micro
---
It's a shame we don't have _ubiquitous decentralized chat_ equivalent to
**email**. I know **Matrix** and **XMPP** exist, but neither are complete
enough. And they dont't have a lot of users.
It's a shame we don't have _ubiquitous decentralized chat_ equivalent to **email**. I know **Matrix** and **XMPP** exist, but neither are complete enough. And they dont't have a lot of users.

View file

@ -1,9 +0,0 @@
+++
title = "Leaving GitHub"
date = 2026-03-27
description = ""
tags = []
draft = true
+++
About a year ago I wrote a post about my self hosting journey which ended with me shutting down my server

View file

@ -1,14 +1,15 @@
+++
title = "Markdown Tables Suck"
date = 2023-12-25T16:28:52+01:00
tags = [ "micro" ]
+++
---
title: Markdown Tables Suck
date: 2023-12-25T16:28:52+01:00
tags:
- micro
---
Tables are arguably the worst part of Markdown. No horizontal lines except for
the mandatory one at the top. The only feature is the possibility to align
cells.
Tables are arguably the worst part of Markdown.
No horizontal lines except for the mandatory one at the top.
The only feature is the possibility to align cells.
Org Mode does much better, but isn't perfect either.
Don't get me wrong. It's nice to have a simple tool for simple tables. But
sometimes I need more customizability.
Don't get me wrong. It's nice to have a simple tool for simple tables.
But sometimes I need more customizability.

View file

@ -1,9 +1,12 @@
+++
title = "Selbsthosting"
date = 2025-04-14
description = "Kleiner Computer, große Pläne"
tags = [ "selbsthosting", "nixos", "git" ]
+++
---
title: Selbsthosting
date: 2025-04-14
description: Kleiner Computer, große Pläne
tags:
- selbsthosting
- nixos
- git
---
Seit etwa 2020 hat mich die Idee fasziniert, meinen _eigenen Server zu betreiben_ also die volle Kontrolle über Daten, Dienste und Medien zu haben. Vor allem auf Reddit, und dort besonders in den Communities [r/selfhosted](https://www.reddit.com/r/selfhosted) und [r/homelab](https://www.reddit.com/r/homelab), habe ich immer wieder spannende Projekte gesehen. Lange blieb das für mich ein Traum zu wenig Zeit, zu wenig Geld. Aber im April 2024 war es so weit: Mein kleines Selbsthosting-Abenteuer begann.
@ -35,7 +38,7 @@ Das Betriebssystem meiner Wahl ist [NixOS](https://nixos.org/). Hauptsächlich,
**Deklarativ** bedeutet: Ich beschreibe in einer Konfigurationsdatei, _was_ das System tun soll nicht _wie_. Dadurch ist mein Setup reproduzierbar, nachvollziehbar und schnell wiederherstellbar.
Viele Dienste lassen sich mit nur wenigen Zeilen Code aktivieren. ~~Ich habe meine Konfiguration auf GitHub veröffentlicht, falls jemand reinschauen oder sie als Grundlage verwenden möchte.~~
Viele Dienste lassen sich mit nur wenigen Zeilen Code aktivieren. Ich habe [meine Konfiguration](https://github.com/jukremer/nix-config) auf GitHub veröffentlicht, falls jemand reinschauen oder sie als Grundlage verwenden möchte.
### Tailscale
@ -69,4 +72,4 @@ Ein weiterer Grund: Ich habe den Server _kaum genutzt_. Meine iCloud läuft noch
Aber: Ich habe in den letzten 8 Monaten extrem viel gelernt über Linux, Netzwerke, NixOS, Systemadministration, Sicherheit und mehr. Das Projekt hat mir gezeigt, wie viel man aus einem alten Mini-PC herausholen kann. Vielleicht wird der Server eines Tages reaktiviert in neuer Form. Für den Moment war es vor allem: _ein spannendes Lernprojekt_.
Falls du Fragen hast oder selbst mit Selbsthosting starten willst: Schreib mir gern ~~oder schau dir meine Konfiguration auf GitHub an~~. Vielleicht hilft dir mein Weg ja bei deinem Einstieg.
Falls du Fragen hast oder selbst mit Selbsthosting starten willst: Schreib mir gern oder schau dir [meine Konfiguration](https://github.com/jukremer/nix-config) auf GitHub an. Vielleicht hilft dir mein Weg ja bei deinem Einstieg.

View file

@ -1,9 +0,0 @@
+++
title = "Still self hosting"
date = 2026-03-27
description = "Guess who's back"
tags = [ "selbsthosting", "nixos", "git" ]
draft = true
+++
About a year ago I wrote a post about my self hosting journey which ended with me shutting down my server

View file

@ -1,17 +1,16 @@
+++
title= "Use Timestamps"
date= 2023-11-15T10:12:30+01:00
tags= ["micro"]
+++
---
title: Use Timestamps
date: 2023-11-15T10:12:30+01:00
tags:
- micro
---
Every blog post should include a timestamp. In fact, this extends to almost
anything online and even offline.
Every blog post should include a timestamp.
In fact, this extends to almost anything online and even offline.
Also, don't make me look for the date. Put the date as obvious as possible,
preferably at the beginning of the post.
Also, don't make me look for the date.
Put the date as obvious as possible, preferably at the beginning of the post.
I was reading
[Julia Evans post about nix](https://jvns.ca/blog/2023/02/28/some-notes-on-using-nix/)
and it was not immediately clear to me if this was a recent post. Only when I
copied the URL to complain about it I discovered the date there. Safari hides
most of the URL by default.
I was reading [Julia Evans post about nix](https://jvns.ca/blog/2023/02/28/some-notes-on-using-nix/) and it was not immediately clear to me if this was a recent post.
Only when I copied the URL to complain about it I discovered the date there.
Safari hides most of the URL by default.

View file

@ -1,8 +1,8 @@
+++
title = "Bitcoin"
date = 2022-12-10
tags = [ "crypto" ]
+++
---
title: Bitcoin
date: 2022-12-10
tags: [crypto]
---
## Address
@ -17,9 +17,9 @@ bc1qf8qjt4gut2la8k4v3emfv7wrj6f3pfcjrj3slplnwrldkz7hqmaqaju7ym
## OpenAlias
```txt
jankremer.de
jankremer.eu
```
```txt
btc.jankremer.de
btc.jankremer.eu
```

View file

@ -1,8 +1,8 @@
+++
title = "Ethereum"
date = 2022-12-10
tags = [ "crypto" ]
+++
---
title: Ethereum
date: 2022-12-10
tags: [crypto]
---
## Address

View file

@ -1,6 +0,0 @@
+++
title = "Fotos"
sort_by = "date"
template = "blog.html"
page_template = "blog-page.html"
+++

View file

@ -1,8 +1,12 @@
+++
title = "Abendliche Bewölkung"
date = 2023-07-19T10:48:33+02:00
description = "über Regensburg"
tags = ["fotos", "regensburg"]
+++
---
title: Abendliche Bewölkung
date: 2023-07-19T10:48:33+02:00
description: "über Regensburg"
tags: [fotos, regensburg]
---
{{ figure(src="./abendliche-bewoelkung.webp", alt="Abendliche Bewölkung über Regensburg")}}
{{< figure
src="./abendliche-bewoelkung.webp"
alt="Abendliche Bewölkung über Regensburg"
caption="Abendliche Bewölkung über Regensburg"
fetchpriority="high" >}}

View file

@ -1,21 +1,42 @@
+++
title = "Ustronie Morskie"
description = "Polen"
date = 2025-11-15T21:53:01+01:00
tags = ["fotos", "polen"]
+++
---
title: Ustronie Morskie
description: Polen
date: 2025-11-15T21:53:01+01:00
tags: [fotos, polen]
---
{{ figure(src="holzwall.jpeg" alt="Holzwall" caption="Holzwall"
first=true) }}
{{< figure
src="holzwall.jpeg"
alt="Holzwall"
caption="Holzwall"
fetchpriority="high" >}}
{{ figure(src="pfote.jpeg" alt="Pfote" caption="Pfote") }}
{{< figure
src="pfote.jpeg"
alt="Pfote"
caption="Pfote" >}}
{{ figure(src="nala.jpeg" alt="Nala" caption="Nala") }}
{{< figure
src="nala.jpeg"
alt="Nala"
caption="Nala" >}}
{{ figure(src="pier.jpeg" alt="Pier" caption="Pier") }}
{{< figure
src="pier.jpeg"
alt="Pier"
caption="Pier" >}}
{{ figure(src="dom-1.jpeg" alt="Kolberger Dom" caption="Kolberger Dom")}}
{{< figure
src="Dom-1.jpeg"
alt="Kolberger Dom"
caption="Kolberger Dom" >}}
{{ figure(src="dom-2.jpeg" alt="Kolberger Dom" caption="Kolberger Dom")}}
{{< figure
src="dom-2.jpeg"
alt="Kolberger Dom"
caption="Kolberger Dom" >}}
{{ figure(src="moeve.jpeg" alt="Möve" caption="Möve")}}
{{< figure
src="moeve.jpeg"
alt="Möve"
caption="Möve" >}}

View file

@ -1,8 +1,8 @@
+++
title = "Monero"
date = 2022-12-10
tags = [ "crypto" ]
+++
---
title: Monero
date: 2022-12-10
tags: [crypto]
---
## Address
@ -17,9 +17,9 @@ tags = [ "crypto" ]
## OpenAlias
```txt
jankremer.de
jankremer.eu
```
```txt
xmr.jankremer.de
xmr.jankremer.eu
```

12
flake.lock generated
View file

@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1771892004,
"narHash": "sha256-V96pa9awm6hjnf8yGJeoC4uOirYDEPsaBbuU0stROQI=",
"lastModified": 1768364046,
"narHash": "sha256-PDFfpswLiuG/DcadTBb7dEfO3jX1fcGlCD4ZKSkC0M8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5e4522be6bdf1600682a6f383434b057b2d77a37",
"rev": "ea30586ee015f37f38783006a9bc9e4aa64d7d61",
"type": "github"
},
"original": {
@ -44,11 +44,11 @@
]
},
"locked": {
"lastModified": 1770228511,
"narHash": "sha256-wQ6NJSuFqAEmIg2VMnLdCnUc0b7vslUohqqGGD+Fyxk=",
"lastModified": 1768158989,
"narHash": "sha256-67vyT1+xClLldnumAzCTBvU0jLZ1YBcf4vANRWP3+Ak=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "337a4fe074be1042a35086f15481d763b8ddc0e7",
"rev": "e96d59dff5c0d7fddb9d113ba108f03c3ef99eca",
"type": "github"
},
"original": {

View file

@ -1,5 +1,5 @@
{
description = "Blog von Jan Kremer";
description = "Hugo website";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
treefmt = {
@ -24,10 +24,10 @@
{
devShells = eachSystem (pkgs: {
default = pkgs.mkShell {
name = "Zola website";
name = "Hugo website";
buildInputs = with pkgs; [
zola
vscode-langservers-extracted
go
hugo
];
};
});
@ -42,28 +42,30 @@
default = {
type = "app";
meta = {
description = "Build website";
homepage = "https://jankremer.de";
description = "Build my blog";
homepage = "https://jankremer.eu";
license = nixpkgs.lib.licenses.cc0;
};
program =
(pkgs.writeShellScript "build-website" ''
set -e
${pkgs.zola}/bin/zola build --minify
${pkgs.hugo}/bin/hugo --minify
'').outPath;
};
deploy = {
type = "app";
meta = {
description = "Deploy to nimbus (Oracle)";
homepage = "https://jankremer.de";
description = "Deploy to Codeberg";
homepage = "https://kremer.codeberg.page";
license = nixpkgs.lib.licenses.cc0;
};
program =
(pkgs.writeShellScript "deploy-website" ''
set -e
${pkgs.zola}/bin/zola build --minify
${pkgs.rsync}/bin/rsync -avP --delete public/ jan@jankremer.de:/var/www/jankremer.de/
${pkgs.hugo}/bin/hugo --minify
cd public
git commit --all -m "Deploy"
git push
'').outPath;
};
});

50
hugo.toml Normal file
View file

@ -0,0 +1,50 @@
baseURL = "https://jankremer.eu/"
title = "Jan Kremer"
copyright = "CC0 1.0"
defaultContentLanguage = "de"
enableGitInfo = true
[params]
[params.author]
name = "Jan Kremer"
email = "mail@jankremer.eu"
[menus]
[[menus.main]]
name = "Blog"
pageRef = "/"
weight = 1
[[menus.main]]
name = "Fotos"
pageRef = "/fotos"
weight = 2
[[menus.main]]
name = "Über mich"
pageRef = "/about"
weight = 3
[markup]
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true
[markup.goldmark.parser]
wrapStandAloneImageWithinParagraph = false
[markup.goldmark.parser.attribute]
block = true
[markup.highlight]
style = "github"
[mediaTypes]
[mediaTypes.'application/atom+xml']
suffixes = ['atom']
[outputFormats]
[outputFormats.atom]
mediaType = 'application/atom+xml'
noUgly = true
[outputs]
home = ['html', 'rss', 'atom']
section = ['html', 'rss', 'atom']
taxonomy = ['html', 'rss', 'atom']
term = ['html', 'rss', 'atom']

View file

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Before After
Before After

View file

@ -0,0 +1,25 @@
<ul>
<li>
<a href="https://creativecommons.org/publicdomain/zero/1.0/"
target="_blank"
rel="noopener noreferrer"
aria-label="CC0: This work has been marked as dedicated to the public domain.">
{{ partial "cc.svg" . }}
{{ partial "zero.svg" . }}
</a>
</li>
<li>
<a href="/about" id="title">
{{ partial "logo.svg" . }}
{{ site.Title }}
</a>
</li>
<!-- <li>
{{ with .GitInfo }}
<a href="https://github.com/jukremer/jukremer.github.io/commit/{{ .Hash }}">
{{ partial "git.svg" }} {{ .Subject }} ({{ .AbbreviatedHash }})
</a>
{{ end }}
</li> -->
<li>2021{{ now.Year }}</li>
</ul>

View file

Before

Width:  |  Height:  |  Size: 310 B

After

Width:  |  Height:  |  Size: 310 B

Before After
Before After

View file

@ -0,0 +1,27 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Blog von Jan Kremer" />
<meta name="author" content="Jan Kremer" />
<meta name="apple-mobile-web-app-title" content="Jan Kremer" />
<meta name="keywords" content="Blog" />
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />
<title>
{{ if .IsHome }}
{{ site.Title }}
{{ else }}
{{ printf "%s %s" .Title
site.Title
}}
{{ end }}
</title>
{{ partialCached "head/css.html" . }}
{{ partialCached "head/js.html" . }}
{{ with .OutputFormats.Get "rss" }}
{{ printf `<link rel=%q type=%q href=%q title=%q>` .Rel .MediaType.Type .Permalink site.Title | safeHTML }}
{{ end }}{{ with .OutputFormats.Get "atom" }}
{{ printf `<link rel=%q type=%q href=%q title=%q>` .Rel .MediaType.Type .Permalink site.Title | safeHTML }}
{{ end }}

View file

@ -0,0 +1,14 @@
{{- with resources.Get "css/main.css" }}
{{- if eq hugo.Environment
"development"
}}
<link rel="stylesheet" href="{{ .RelPermalink }}" />
{{- else }}
{{- with . | minify | fingerprint }}
<link rel="stylesheet"
href="{{ .RelPermalink }}"
integrity="{{ .Data.Integrity }}"
crossorigin="anonymous" />
{{- end }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,16 @@
{{- with resources.Get "js/main.js" }}
{{- if eq hugo.Environment "development" }}
{{- with . | js.Build }}
<script src="{{ .RelPermalink }}"></script>
{{- end }}
{{- else }}
{{- $opts := dict "minify" true }}
{{- with . | js.Build
$opts | fingerprint
}}
<script src="{{ .RelPermalink }}"
integrity="{{- .Data.Integrity }}"
crossorigin="anonymous"></script>
{{- end }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,2 @@
<a href="/" class="title">{{ partial "logo.svg" . }}{{ site.Title }}</a>
{{ partial "menu.html" (dict "menuID" "main" "page" .) }}

View file

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

View file

@ -0,0 +1,47 @@
{{- /*
Renders a menu for the given menu ID.
@context {page} page The current page.
@context {string} menuID The menu ID.
@example: {{ partial "menu.html" (dict "menuID" "main" "page" .)
}}
*/}}
{{- $page := .page }}
{{- $menuID := .menuID }}
{{- with index site.Menus $menuID }}
<nav>
<ul>
{{- partial "inline/menu/walk.html" (dict "page" $page "menuEntries" .) }}
</ul>
</nav>
{{- end }}
{{- define "partials/inline/menu/walk.html" }}
{{- $page := .page }}
{{- range .menuEntries }}
{{- $attrs := dict "href" .URL }}
{{- if $page.IsMenuCurrent .Menu . }}
{{- $attrs = merge $attrs (dict "class" "active" "aria-current" "page") }}
{{- else if $page.HasMenuCurrent .Menu . }}
{{- $attrs = merge $attrs (dict "class" "ancestor" "aria-current" "true") }}
{{- end }}
{{- $name := .Name }}
{{- with .Identifier }}
{{- with T . }}
{{- $name = . }}
{{- end }}
{{- end }}
<li>
<a {{- range $k, $v := $attrs }}
{{- with $v }}
{{- printf " %s=%q" $k $v | safeHTMLAttr }}
{{- end }}
{{- end -}}>{{ $name }}</a>
{{- with .Children }}
<ul>
{{- partial "inline/menu/walk.html" (dict "page" $page "menuEntries" .) }}
</ul>
{{- end }}
</li>
{{- end }}
{{- end }}

View file

@ -0,0 +1,24 @@
{{- /* For a given taxonomy, renders a list of terms assigned to the page.
@context {page} page The current page. @context {string} taxonomy The taxonony.
@example: {{ partial "terms.html" (dict "taxonomy" "tags" "page" .)
}}
*/}}
{{- $page := .page }}
{{- $taxonomy := .taxonomy }}
{{- with $page.GetTerms
$taxonomy
}}
{{- $label := (index . 0).Parent.LinkTitle }}
<div class="tags">
<ul>
<li>Tags:</li>
<ul>
{{- range . }}
<li>
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
</li>
{{- end }}
</ul>
</ul>
</div>
{{- end }}

View file

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Before After
Before After

16
layouts/baseof.html Normal file
View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="{{ or site.Language.LanguageCode site.Language.Lang }}"
dir="{{ or site.Language.LanguageDirection `ltr` }}">
<head>{{ partial "head.html" . }}</head>
<body>
<header>
{{ partial "header.html" . }}
</header>
<main>
{{ block "main" . }}{{ end }}
</main>
<footer>
{{ partial "footer.html" . }}
</footer>
</body>
</html>

21
layouts/home.html Normal file
View file

@ -0,0 +1,21 @@
{{ define "main" }}
{{ .Content }}
{{ $pages := .Paginate (where
.Site.RegularPages "Type" "ne" "page")
}}
<div class="list">
<ul>
{{ range $pages.Pages }}
<li>
<a href="{{ .RelPermalink }}" style="display: block">
<h2>{{ .Title }}</h2>
<p class="lead">{{ .Description }}</p>
{{ $dateMachine := .Date | time.Format "2006-01-02T15:04:05-07:00" }}
{{ $dateHuman := .Date | time.Format ":date_long" }}
<time datetime="{{ $dateMachine }}">{{ $dateHuman }}</time>
</a>
</li>
{{ end }}
</ul>
</div>
{{ end }}

60
layouts/list.atom.atom Normal file
View file

@ -0,0 +1,60 @@
{{- $authorEmail := "" }}
{{- with site.Params.author }}
{{- if reflect.IsMap . }}
{{- with .email }}
{{- $authorEmail = . }}
{{- end }}
{{- end }}
{{- end }}
{{- $authorName := "" }}
{{- with site.Params.author }}
{{- if reflect.IsMap . }}
{{- with .name }}
{{- $authorName = . }}
{{- end }}
{{- else }}
{{- $authorName = . }}
{{- end }}
{{- end }}
{{- $pctx := . }}
{{- if .IsHome }}{{ $pctx = .Site }}{{ end }}
{{- $pages := slice }}
{{- if or $.IsHome $.IsSection }}
{{- $pages = $pctx.RegularPages }}
{{- else }}
{{- $pages = $pctx.Pages }}
{{- end }}
{{- $limit := .Site.Config.Services.RSS.Limit }}
{{- if ge $limit 1 }}
{{- $pages = $pages | first $limit }}
{{- end }}
<feed xmlns="http://www.w3.org/2005/Atom">
<title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{ . }} on {{ end }}{{ .Site.Title }}{{ end }}</title>
<link href="{{ .Permalink }}index.atom" rel="self"/>
<link href="{{ .Permalink }}"/>
<updated>{{ .Date.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</updated>
<id>{{ .Permalink }}</id>
<author>
<name>{{ with $authorName }}{{ . }}{{ end }}</name>
<email>{{ with $authorEmail }}{{ . }}{{ end }}</email>
</author>
<generator>Hugo</generator>
{{- range $pages }}
<entry>
<title type="html">{{ .Title }}</title>
<link href="{{ .Permalink }}"/>
<id>{{ .Permalink }}</id>
<author>
<name>{{ with $authorName }}{{ . }}{{ end }}</name>
<email>{{ with $authorEmail }}{{ . }}{{ end }}</email>
</author>
<published>{{ .Date.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</published>
<updated>{{ .Lastmod.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</updated>
<content type="html">
{{ .Content | transform.XMLEscape | safeHTML }}
</content>
</entry>
{{- end }}
</feed>

18
layouts/list.html Normal file
View file

@ -0,0 +1,18 @@
{{ define "main" }}
{{ .Content }}
<div class="list">
<ul>
{{ range .Pages }}
<li>
<a href="{{ .RelPermalink }}" style="display: block">
<h2>{{ .Title }}</h2>
<p class="lead">{{ .Description }}</p>
{{ $dateMachine := .Date | time.Format "2006-01-02T15:04:05-07:00" }}
{{ $dateHuman := .Date | time.Format ":date_long" }}
<time datetime="{{ $dateMachine }}">{{ $dateHuman }}</time>
</a>
</li>
{{ end }}
</ul>
</div>
{{ end }}

63
layouts/list.rss.xml Normal file
View file

@ -0,0 +1,63 @@
{{- $authorEmail := "" }}
{{- with site.Params.author }}
{{- if reflect.IsMap . }}
{{- with .email }}
{{- $authorEmail = . }}
{{- end }}
{{- end }}
{{- end }}
{{- $authorName := "" }}
{{- with site.Params.author }}
{{- if reflect.IsMap . }}
{{- with .name }}
{{- $authorName = . }}
{{- end }}
{{- else }}
{{- $authorName = . }}
{{- end }}
{{- end }}
{{- $pctx := . }}
{{- if .IsHome }}{{ $pctx = .Site }}{{ end }}
{{- $pages := slice }}
{{- if or $.IsHome $.IsSection }}
{{- $pages = $pctx.RegularPages }}
{{- else }}
{{- $pages = $pctx.Pages }}
{{- end }}
{{- $limit := .Site.Config.Services.RSS.Limit }}
{{- if ge $limit 1 }}
{{- $pages = $pages | first $limit }}
{{- end }}
{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{ . }} on {{ end }}{{ .Site.Title }}{{ end }}</title>
<link>{{ .Permalink }}</link>
<description>Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{ . }} {{ end }}{{ end }}on {{ .Site.Title }}</description>
<generator>Hugo</generator>
<language>{{ site.Language.LanguageCode }}</language>{{ with $authorEmail }}
<managingEditor>{{.}}{{ with $authorName }} ({{ . }}){{ end }}</managingEditor>{{ end }}{{ with $authorEmail }}
<webMaster>{{ . }}{{ with $authorName }} ({{ . }}){{ end }}</webMaster>{{ end }}{{ with .Site.Copyright }}
<copyright>{{ . }}</copyright>{{ end }}{{ if not .Date.IsZero }}
<lastBuildDate>{{ (index $pages.ByLastmod.Reverse 0).Lastmod.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
{{- with .OutputFormats.Get "RSS" }}
{{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
{{- end }}
{{- range $pages }}
<item>
<title>{{ .Title }}</title>
<link>{{ .Permalink }}</link>
<pubDate>{{ .PublishDate.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
{{- with $authorEmail }}<author>{{ . }}{{ with $authorName }} ({{ . }}){{ end }}</author>{{ end }}
<guid>{{ .Permalink }}</guid>
<description>
&lt;strong&gt;{{ .Description | transform.XMLEscape | safeHTML }}&lt;/strong&gt;
{{ .Content | transform.XMLEscape | safeHTML }}
</description>
</item>
{{- end }}
</channel>
</rss>

20
layouts/single.html Normal file
View file

@ -0,0 +1,20 @@
{{ define "main" }}
<article>
{{ $dateHuman := .Date | time.Format ":date_long" }}
{{ $dateMachine := .Date | time.Format "2006-01-02T15:04:05-07:00" }}
{{ $lastmodDateHuman := .Lastmod | time.Format ":date_long" }}
{{ $lastmodDateMachine := .Lastmod | time.Format "2006-01-02T15:04:05-07:00" }}
<div class="dates">
<p>
Editiert:
<time datetime="{{ $lastmodDateMachine }}">{{ $lastmodDateHuman }}</time>
</p>
<p>
<time datetime="{{ $dateMachine }}">{{ $dateHuman }}</time>
</p>
</div>
<h1>{{ .Title }}</h1>
<p class="lead">{{ .Description }}</p>
{{ .Content }}
</article>
{{ end }}

BIN
static/pharmacist-0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

15
static/pharmacist-0.txt Normal file
View file

@ -0,0 +1,15 @@
▄▄▀▀▄▀▀▀▀▀▀▀▀▄▄
▄▀ █
▄▀ ▄▄▄ █
█ ▄▀▀▀ ▀▀▀▀▀▀▀█▀
▀▄▄█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▄
█ █ █
▀█▀▄ ▄▀▄ ▄▀
█ ▀▀▀▀▀ ▀▀▀▀█
█ █
█ ▀▀▀▀ █
█ ▄▀
█ █▀▀▀▀▀▀
▄▀▀▀▄ ▄▀▀▀▄
█ ▀▄▀ █
█ █ ▀▀ █

BIN
static/pharmacist-0.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
static/pharmacist-1-red.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

BIN
static/skier-1-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
static/skier-1-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
static/skier-1-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View file

@ -1,58 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>404 {{ config.title }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Blog von Jan Kremer" />
<meta name="author" content="Jan Kremer" />
<meta name="apple-mobile-web-app-title" content="Jan Kremer" />
<meta name="keywords" content="Blog" />
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="stylesheet" href="/main.css" />
</head>
<body>
<header>
<a href="/" class="title">{{ load_data(path="templates/logo.svg") | safe }}Jan Kremer</a>
<nav>
<ul>
<li>
<a href="/blog/">Blog</a>
</li>
<li>
<a href="/fotos/">Fotos</a>
</li>
<li>
<a href="/about/">Über mich</a>
</li>
</ul>
</nav>
</header>
<main>
<article>
<h1>404 Not Found</h1>
</article>
</main>
<footer>
<ul>
<li>
<a href="https://creativecommons.org/publicdomain/zero/1.0/"
target="_blank"
rel="noopener noreferrer"
aria-label="CC0: This work has been marked as dedicated to the public domain.">
{{ load_data(path="templates/cc.svg") | safe }}
{{ load_data(path="templates/zero.svg") | safe }}
</a>
</li>
<li>
<a href="/" id="title">{{ load_data(path="templates/logo.svg") | safe }}Jan Kremer</a>
</li>
<li>2021{{ now() | date(format="%Y") }}</li>
</ul>
</footer>
</body>
</html>

View file

@ -1,70 +0,0 @@
{% import "macros.html" as macros %}
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>
{% if current_path == "/" %}
{{ config.title }}
{% elif section %}
{{ section.title }} {{ config.title }}
{% elif page %}
{{ page.title }} {{ config.title }}
{% endif %}
</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Blog von Jan Kremer" />
<meta name="author" content="Jan Kremer" />
<meta name="apple-mobile-web-app-title" content="Jan Kremer" />
<meta name="keywords" content="Blog" />
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />
{% block rss %}
<link rel="alternate"
type="application/atom+xml"
title="Atom feed"
href="{{ get_url(path="atom.xml", trailing_slash=false) }}">
<link rel="alternate"
type="application/rss+xml"
title="RSS"
href="{{ get_url(path="rss.xml", trailing_slash=false) }}">
{% endblock %}
<link rel="stylesheet" href="/main.css" />
</head>
<body>
<header>
<a href="/" class="title">{{ load_data(path="templates/logo.svg") | safe }}Jan Kremer</a>
<nav>
<ul>
{{ macros::menu_item(url="/blog/", name="Blog") }}
{{ macros::menu_item(url="/fotos/", name="Fotos") }}
{{ macros::menu_item(url="/about/", name="Über mich") }}
</ul>
</nav>
</header>
<main>
{% block content %}
{% endblock content %}
</main>
<footer>
<ul>
<li>
<a href="https://creativecommons.org/publicdomain/zero/1.0/"
target="_blank"
rel="noopener noreferrer"
aria-label="CC0: This work has been marked as dedicated to the public domain.">
{{ load_data(path="templates/cc.svg") | safe }}
{{ load_data(path="templates/zero.svg") | safe }}
</a>
</li>
<li>
<a href="/" id="title">{{ load_data(path="templates/logo.svg") | safe }}Jan Kremer</a>
</li>
<li>2021{{ now() | date(format="%Y") }}</li>
</ul>
</footer>
</body>
</html>

View file

@ -1,19 +0,0 @@
{% extends "base.html" %}
{% block content %}
<article>
<div class="dates">
<p>
<time datetime="{{ page.date }}">{{ page.date | date(format="%e. %B %Y", locale="de_DE") }}</time>
</p>
{% if page.updated %}
<p>
Aktualisiert: <time datetime="{{ page.updated }}">{{ page.updated | date(format="%e. %B %Y", locale="de_DE")
}}</time>
</p>
{% endif %}
</div>
<h1>{{ page.title }}</h1>
<p class="lead">{{ page.description }}</p>
{{ page.content | safe }}
</article>
{% endblock content %}

View file

@ -1,18 +0,0 @@
{% extends "base.html" %}
{% block content %}
<div class="list">
<ul>
<!-- If you are using pagination, section.pages will be empty.
You need to use the paginator object -->
{% for page in section.pages %}
<li>
<a href="{{ page.permalink | safe }}" style="display: block">
<h2>{{ page.title }}</h2>
<p class="lead">{{ page.description | safe }}</p>
<time datetime="{{ page.date | date(format="%Y-%m-%d %H:%M") }}">{{ page.date | date(format="%e. %B %Y", locale="de_DE") }}</time>
</a>
</li>
{% endfor %}
</ul>
</div>
{% endblock content %}

View file

@ -1,21 +0,0 @@
{% extends "base.html" %}
{% block content %}
<div class="list">
<ul>
<!-- If you are using pagination, section.pages will be empty.
You need to use the paginator object -->
{% set blog = get_section(path="blog/_index.md") %}
{% set fotos = get_section(path="fotos/_index.md") %}
{% set all_pages = blog.pages | concat(with=fotos.pages) | sort(attribute="date") | reverse %}
{% for page in all_pages %}
<li>
<a href="{{ page.permalink | safe }}" style="display: block">
<h2>{{ page.title }}</h2>
<p class="lead">{{ page.description | safe }}</p>
<time datetime="{{ page.date | date(format="%Y-%m-%d %H:%M") }}">{{ page.date | date(format="%e. %B %Y", locale="de_DE") }}</time>
</a>
</li>
{% endfor %}
</ul>
</div>
{% endblock content %}

View file

@ -1,6 +0,0 @@
{% macro menu_item(url, name) %}
<li>
<a href="{{ url }}" {% if current_path==url %} class="active" aria-current="page" {% elif current_path is
starting_with(url) and url !="/" %} class="ancestor" aria-current="true" {% endif %}>{{ name }}</a>
</li>
{% endmacro %}

View file

@ -1,15 +0,0 @@
<figure>
<img src="{{ src }}" {% if alt %}alt="{{ alt }}"{% endif %} {% if first %} fetchpriority="high" decoding="async" {%
else %} loading="lazy" decoding="async" {% endif %}>
{% if caption or alt %}
<figcaption>
<p>
{% if caption %}
{{ caption }}
{% elif alt %}
{{ alt }}
{% endif %}
</p>
</figcaption>
{% endif %}
</figure>

View file

@ -2,7 +2,6 @@
programs = {
nixfmt.enable = true;
taplo.enable = true;
mdformat.enable = true;
djlint.enable = true;
};
settings.global.excludes = [

View file

@ -1,85 +0,0 @@
# The URL the site will be built for
base_url = "https://jankremer.de"
title = "Jan Kremer"
description = "Blog von Jan Kremer"
author = "Jan Kremer"
default_language = "de"
# Whether dotfiles at the root level of the output directory are preserved when (re)building the site.
# Enabling this also prevents the deletion of the output folder itself on rebuilds.
# preserve_dotfiles_in_output = true
generate_feeds = true
feed_filenames = ["atom.xml", "rss.xml"]
# Whether to build a search index to be used later on by a JavaScript library
build_search_index = true
[markdown]
# CSS class to add to external links (e.g. "external-link")
# external_links_class =
# Whether to set decoding="async" and loading="lazy" for all images
# When turned on, the alt text must be plain text.
# For example, `![xx](...)` is ok but `![*x*x](...)` isnt ok
lazy_async_image = true
definition_list = true
bottom_footnotes = true
smart_punctuation = true
# When set to "true", support for GitHub-style alerts, a.k.a. callouts or admonitions, is enabled in the Markdown parser.
# For example, this Markdown syntax:
#
# > [!NOTE]
# > alert note
#
# will result in the following generated HTML:
#
# <blockquote class="markdown-alert-note">
# <p>alert note</p>
# </blockquote>
#
# where the CSS class name suffix may be `note`, `tip`, `important`, `warning`, or `caution`, depending on the alert type.
# Visual appearance depends on theme-level support; refer to your theme's documentation for more information.
github_alerts = false
# insert_anchor_links = "left"
[markdown.highlighting]
error_on_missing_language = true
# Whether to use inline hex colours (`inline`) or CSS classes (`class`)
style = "inline"
light_theme = "catppuccin-latte"
dark_theme = "catppuccin-macchiato"
# A list of files for additional JSON TextMate grammars
extra_grammars = []
[search]
# Whether to include the title of the page/section in the index
include_title = true
# Whether to include the description of the page/section in the index
include_description = false
# Whether to include the RFC3339 datetime of the page in the search index
include_date = false
# Whether to include the path of the page/section in the index (the permalink is always included)
include_path = false
# Whether to include the rendered content of the page/section in the index
include_content = true
# At which code point to truncate the content to. Useful if you have a lot of pages and the index would
# become too big to load on the site. Defaults to not being set.
# truncate_content_length = 100
# Whether to produce the search index as a javascript file or as a JSON file
# Accepted values:
# - "elasticlunr_javascript", "elasticlunr_json"
# - "fuse_javascript", "fuse_json"
index_format = "elasticlunr_javascript"
[extra]
# Put all your custom variables here