Compare commits

...

10 commits

Author SHA1 Message Date
Jan Kremer
b12087238b
Add 404 page 2026-03-27 08:11:14 +01:00
Jan Kremer
7f9ae523a4
Fix 2026-03-27 06:58:27 +01:00
Jan Kremer
64270fbde7
Remove GitHub action 2026-03-26 19:12:03 +01:00
Jan Kremer
aca3387492
Deploy as jankremer.de to nimbus (Oracle) 2026-03-26 19:11:05 +01:00
Jan Kremer
3a35b1dae7
Remove deprecated links 2026-03-18 08:22:13 +01:00
Jan Kremer
a4bfec11f5
Fix feed links 2026-03-17 11:23:59 +01:00
Jan Kremer
4c1aa547e1
Move from Hugo to Zola 2026-03-17 11:06:46 +01:00
Jan Kremer
aa8a58141d
Update header 2026-03-15 12:12:13 +01:00
Jan Kremer
b1e32b2c9f
Convert frontmatter from YAML to TOML 2026-03-10 08:23:16 +01:00
Jan Kremer
709cb556c1
Remove static images not used 2026-03-10 08:02:21 +01:00
73 changed files with 472 additions and 654 deletions

View file

@ -1,52 +0,0 @@
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,3 +1,2 @@
/public/
.hugo_build.lock
.direnv

7
.helix/languages.toml Normal file
View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,12 +1,13 @@
---
title: Über mich
date: 2024-12-12
---
+++
title = "Über mich"
date = 2024-12-12
updated = 2026-03-17
+++
Mein Name ist _Jan Kremer_. Ich bin 29 Jahre alt und bin *Apotheker*. Manchmal schreibe ich über Technik und Software die ich benutze.
Mein Name ist *Jan Kremer*. Ich bin 29 Jahre alt und habe *Pharmazie* studiert. 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.eu](mailto:mail@jankremer.eu)
[mail@jankremer.de](mailto:mail@jankremer.de)

6
content/blog/_index.md Normal file
View file

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

View file

@ -1,13 +1,23 @@
---
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,8 +1,9 @@
---
title: Email
date: 2026-02-20T15:46:52+01:00
description:
tags: micro
---
+++
title = "Email"
date = 2026-02-20T15:46:52+01:00
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.

9
content/blog/github.md Normal file
View file

@ -0,0 +1,9 @@
+++
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,15 +1,14 @@
---
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,12 +1,9 @@
---
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.
@ -38,7 +35,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](https://github.com/jukremer/nix-config) 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 auf GitHub veröffentlicht, falls jemand reinschauen oder sie als Grundlage verwenden möchte.~~
### Tailscale
@ -72,4 +69,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](https://github.com/jukremer/nix-config) 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 auf GitHub an~~. Vielleicht hilft dir mein Weg ja bei deinem Einstieg.

View file

@ -0,0 +1,9 @@
+++
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,16 +1,17 @@
---
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.eu
jankremer.de
```
```txt
btc.jankremer.eu
btc.jankremer.de
```

View file

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

6
content/fotos/_index.md Normal file
View file

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

View file

@ -1,12 +1,8 @@
---
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"
caption="Abendliche Bewölkung über Regensburg"
fetchpriority="high" >}}
{{ figure(src="./abendliche-bewoelkung.webp", alt="Abendliche Bewölkung über Regensburg")}}

View file

@ -1,42 +1,21 @@
---
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"
fetchpriority="high" >}}
{{ figure(src="holzwall.jpeg" alt="Holzwall" caption="Holzwall"
first=true) }}
{{< 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.eu
jankremer.de
```
```txt
xmr.jankremer.eu
xmr.jankremer.de
```

12
flake.lock generated
View file

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

View file

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

View file

@ -1,50 +0,0 @@
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

@ -1,25 +0,0 @@
<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

@ -1,27 +0,0 @@
<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

@ -1,14 +0,0 @@
{{- 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

@ -1,16 +0,0 @@
{{- 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

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

View file

@ -1,47 +0,0 @@
{{- /*
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

@ -1,24 +0,0 @@
{{- /* 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

@ -1,16 +0,0 @@
<!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>

View file

@ -1,21 +0,0 @@
{{ 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 }}

View file

@ -1,60 +0,0 @@
{{- $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>

View file

@ -1,18 +0,0 @@
{{ 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 }}

View file

@ -1,63 +0,0 @@
{{- $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>

View file

@ -1,20 +0,0 @@
{{ 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 }}

View file

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7 KiB

View file

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

58
templates/404.html Normal file
View file

@ -0,0 +1,58 @@
<!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>

70
templates/base.html Normal file
View file

@ -0,0 +1,70 @@
{% 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>

19
templates/blog-page.html Normal file
View file

@ -0,0 +1,19 @@
{% 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 %}

18
templates/blog.html Normal file
View file

@ -0,0 +1,18 @@
{% 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

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 310 B

After

Width:  |  Height:  |  Size: 310 B

Before After
Before After

21
templates/index.html Normal file
View file

@ -0,0 +1,21 @@
{% 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

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

6
templates/macros.html Normal file
View file

@ -0,0 +1,6 @@
{% 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

@ -0,0 +1,15 @@
<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

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Before After
Before After

View file

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

85
zola.toml Normal file
View file

@ -0,0 +1,85 @@
# 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