diff --git a/astro.config.mjs b/astro.config.mjs
index 17f6a62..b31e90a 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -1,5 +1,9 @@
// @ts-check
import { defineConfig } from "astro/config";
+import icon from "astro-icon";
+
// https://astro.build/config
-export default defineConfig({});
+export default defineConfig({
+ integrations: [icon()]
+});
\ No newline at end of file
diff --git a/content.config.ts b/content.config.ts
new file mode 100644
index 0000000..10605c0
--- /dev/null
+++ b/content.config.ts
@@ -0,0 +1,60 @@
+import z from "astro/zod";
+import { glob } from "astro/loaders";
+import { defineCollection } from "astro:content";
+
+const writingTags = z.enum([
+ 'emacs',
+ 'neovim',
+ 'keyboards',
+ 'triathlon',
+ 'dev',
+ 'design',
+ 'linux',
+ 'nixos',
+ 'ghostty',
+ 'niri',
+]);
+
+const projectTags = z.enum([
+ 'work',
+ 'open source',
+ 'typescript',
+ 'golang',
+ 'emacs lisp',
+ 'react',
+ 'react native',
+]);
+
+const writingSchema = z.object({
+ title: z.string(),
+ tags: z.array(writingTags),
+ author: z.string().default('Dennis'),
+ publishedAt: z.coerce.date(),
+ lastUpdatedAt: z.coerce.date().optional(),
+ isPublic: z.boolean(),
+});
+
+export type JournalData = z.infer;
+
+const projectSchema = z.object({
+ title: z.string(),
+ tags: z.array(projectTags),
+ isWork: z.boolean(),
+ isLeisure: z.boolean(),
+ year: z.number().gte(2012),
+ isPublic: z.boolean(),
+});
+
+export type ProjectData = z.infer;
+
+const blog = defineCollection({
+ loader: glob({ pattern: '**/*.md', base: 'src/content/blog' }),
+ schema: writingSchema
+});
+
+const projects = defineCollection({
+ loader: glob({ pattern: '**/*.md', base: 'src/content/projects' }),
+ schema: projectSchema
+});
+
+export const collections = { blog, projects };
diff --git a/deploy.sh b/deploy.sh
new file mode 100755
index 0000000..7a8d124
--- /dev/null
+++ b/deploy.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+echo "Deploying to remote server..."
+rsync -avz --delete dist/ dnsc-vps-sm:/var/www/homepage
diff --git a/package.json b/package.json
index 6619ecc..22b4b44 100644
--- a/package.json
+++ b/package.json
@@ -10,8 +10,10 @@
"format": "pnpm exec prettier . --write"
},
"dependencies": {
+ "@iconify-json/tabler": "^1.2.26",
"@knadh/oat": "0.3.0",
- "astro": "5.17.2"
+ "astro": "5.17.2",
+ "astro-icon": "^1.1.5"
},
"devDependencies": {
"prettier": "3.8.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b70e52c..11a4873 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,12 +8,18 @@ importers:
.:
dependencies:
+ '@iconify-json/tabler':
+ specifier: ^1.2.26
+ version: 1.2.26
'@knadh/oat':
specifier: 0.3.0
version: 0.3.0
astro:
specifier: 5.17.2
- version: 5.17.2(rollup@4.57.1)(typescript@5.9.3)
+ version: 5.17.2(@types/node@25.3.0)(rollup@4.57.1)(typescript@5.9.3)
+ astro-icon:
+ specifier: ^1.1.5
+ version: 1.1.5
devDependencies:
prettier:
specifier: 3.8.1
@@ -24,6 +30,12 @@ importers:
packages:
+ '@antfu/install-pkg@1.1.0':
+ resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==}
+
+ '@antfu/utils@8.1.1':
+ resolution: {integrity: sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==}
+
'@astrojs/compiler@2.13.1':
resolution: {integrity: sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==}
@@ -377,6 +389,18 @@ packages:
cpu: [x64]
os: [win32]
+ '@iconify-json/tabler@1.2.26':
+ resolution: {integrity: sha512-92G+ZD70AZgeJf07JfQzH+isnai6DwPcMBuF/qL1F+xAxdXCJzGd3w2RmsRvOmB+w1ImmWEEDms50QivQIjd6g==}
+
+ '@iconify/tools@4.2.0':
+ resolution: {integrity: sha512-WRxPva/ipxYkqZd1+CkEAQmd86dQmrwH0vwK89gmp2Kh2WyyVw57XbPng0NehP3x4V1LzLsXUneP1uMfTMZmUA==}
+
+ '@iconify/types@2.0.0':
+ resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
+
+ '@iconify/utils@2.3.0':
+ resolution: {integrity: sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==}
+
'@img/colour@1.0.0':
resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==}
engines: {node: '>=18'}
@@ -514,6 +538,10 @@ packages:
cpu: [x64]
os: [win32]
+ '@isaacs/fs-minipass@4.0.1':
+ resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
+ engines: {node: '>=18.0.0'}
+
'@jridgewell/sourcemap-codec@1.5.5':
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
@@ -678,6 +706,10 @@ packages:
'@shikijs/vscode-textmate@10.0.2':
resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
+ '@trysound/sax@0.2.0':
+ resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
+ engines: {node: '>=10.13.0'}
+
'@types/debug@4.1.12':
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
@@ -696,9 +728,15 @@ packages:
'@types/nlcst@2.0.3':
resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==}
+ '@types/node@25.3.0':
+ resolution: {integrity: sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A==}
+
'@types/unist@3.0.3':
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
+ '@types/yauzl@2.10.3':
+ resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
+
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
@@ -736,6 +774,9 @@ packages:
array-iterate@2.0.1:
resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==}
+ astro-icon@1.1.5:
+ resolution: {integrity: sha512-CJYS5nWOw9jz4RpGWmzNQY7D0y2ZZacH7atL2K9DeJXJVaz7/5WrxeyIxO8KASk1jCM96Q4LjRx/F3R+InjJrw==}
+
astro@5.17.2:
resolution: {integrity: sha512-7jnMqGo53hOQNwo1N/wqeOvUp8wwW/p+DeerSjSkHNx8L/1mhy6P7rVo7EhdmF8DpKqw0tl/B5Fx1WcIzg1ysA==}
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'}
@@ -758,6 +799,9 @@ packages:
resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==}
engines: {node: '>=18'}
+ buffer-crc32@0.2.13:
+ resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
+
camelcase@8.0.0:
resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==}
engines: {node: '>=16'}
@@ -778,10 +822,21 @@ packages:
character-entities@2.0.2:
resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
+ cheerio-select@2.1.0:
+ resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==}
+
+ cheerio@1.2.0:
+ resolution: {integrity: sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==}
+ engines: {node: '>=20.18.1'}
+
chokidar@5.0.0:
resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
engines: {node: '>= 20.19.0'}
+ chownr@3.0.0:
+ resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
+ engines: {node: '>=18'}
+
ci-info@4.4.0:
resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==}
engines: {node: '>=8'}
@@ -801,9 +856,19 @@ packages:
resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
engines: {node: '>=16'}
+ commander@7.2.0:
+ resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
+ engines: {node: '>= 10'}
+
common-ancestor-path@1.0.1:
resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==}
+ confbox@0.1.8:
+ resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
+
+ confbox@0.2.4:
+ resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==}
+
cookie-es@1.2.2:
resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==}
@@ -821,6 +886,10 @@ packages:
resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==}
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
+ css-tree@2.3.1:
+ resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==}
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
+
css-tree@3.1.0:
resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==}
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
@@ -904,6 +973,12 @@ packages:
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+ encoding-sniffer@0.2.1:
+ resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==}
+
+ end-of-stream@1.4.5:
+ resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
+
entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
@@ -912,6 +987,10 @@ packages:
resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
engines: {node: '>=0.12'}
+ entities@7.0.1:
+ resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
+ engines: {node: '>=0.12'}
+
es-module-lexer@1.7.0:
resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
@@ -938,9 +1017,20 @@ packages:
eventemitter3@5.0.4:
resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==}
+ exsolve@1.0.8:
+ resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
+
extend@3.0.2:
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+ extract-zip@2.0.1:
+ resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==}
+ engines: {node: '>= 10.17.0'}
+ hasBin: true
+
+ fd-slicer@1.1.0:
+ resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
+
fdir@6.5.0:
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
engines: {node: '>=12.0.0'}
@@ -970,9 +1060,17 @@ packages:
resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==}
engines: {node: '>=18'}
+ get-stream@5.2.0:
+ resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
+ engines: {node: '>=8'}
+
github-slugger@2.0.0:
resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==}
+ globals@15.15.0:
+ resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==}
+ engines: {node: '>=18'}
+
h3@1.15.5:
resolution: {integrity: sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg==}
@@ -1012,9 +1110,16 @@ packages:
html-void-elements@3.0.0:
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
+ htmlparser2@10.1.0:
+ resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==}
+
http-cache-semantics@4.2.0:
resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
+ iconv-lite@0.6.3:
+ resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
+ engines: {node: '>=0.10.0'}
+
import-meta-resolve@4.2.0:
resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==}
@@ -1051,6 +1156,13 @@ packages:
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
engines: {node: '>=6'}
+ kolorist@1.8.0:
+ resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
+
+ local-pkg@1.1.2:
+ resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==}
+ engines: {node: '>=14'}
+
longest-streak@3.1.0:
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
@@ -1109,6 +1221,9 @@ packages:
mdn-data@2.0.28:
resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==}
+ mdn-data@2.0.30:
+ resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
+
mdn-data@2.12.2:
resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==}
@@ -1196,6 +1311,17 @@ packages:
micromark@4.0.2:
resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}
+ minipass@7.1.3:
+ resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ minizlib@3.1.0:
+ resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
+ engines: {node: '>= 18'}
+
+ mlly@1.8.0:
+ resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==}
+
mrmime@2.0.1:
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
engines: {node: '>=10'}
@@ -1234,6 +1360,9 @@ packages:
ohash@2.0.11:
resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
oniguruma-parser@0.12.1:
resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==}
@@ -1258,9 +1387,21 @@ packages:
parse-latin@7.0.0:
resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==}
+ parse5-htmlparser2-tree-adapter@7.1.0:
+ resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==}
+
+ parse5-parser-stream@7.1.2:
+ resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==}
+
parse5@7.3.0:
resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
+ pathe@2.0.3:
+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+
+ pend@1.2.0:
+ resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
+
piccolore@0.1.3:
resolution: {integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==}
@@ -1275,6 +1416,12 @@ packages:
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
engines: {node: '>=12'}
+ pkg-types@1.3.1:
+ resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
+
+ pkg-types@2.3.0:
+ resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==}
+
postcss@8.5.6:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
@@ -1299,6 +1446,12 @@ packages:
property-information@7.1.0:
resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
+ pump@3.0.3:
+ resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==}
+
+ quansync@0.2.11:
+ resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==}
+
radix3@1.1.2:
resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==}
@@ -1363,6 +1516,9 @@ packages:
s.color@0.0.15:
resolution: {integrity: sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA==}
+ safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
sass-formatter@0.7.9:
resolution: {integrity: sha512-CWZ8XiSim+fJVG0cFLStwDvft1VI7uvXdCNJYXhDvowiv+DsbD1nXLiQ4zrE5UBvj5DWZJ93cwN0NX5PMsr1Pw==}
@@ -1418,11 +1574,20 @@ packages:
suf-log@2.5.3:
resolution: {integrity: sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==}
+ svgo@3.3.2:
+ resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+
svgo@4.0.0:
resolution: {integrity: sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==}
engines: {node: '>=16'}
hasBin: true
+ tar@7.5.9:
+ resolution: {integrity: sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==}
+ engines: {node: '>=18'}
+
tiny-inflate@1.0.3:
resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
@@ -1471,6 +1636,13 @@ packages:
uncrypto@0.1.3:
resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}
+ undici-types@7.18.2:
+ resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
+
+ undici@7.22.0:
+ resolution: {integrity: sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==}
+ engines: {node: '>=20.18.1'}
+
unified@11.0.5:
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
@@ -1626,6 +1798,15 @@ packages:
web-namespaces@2.0.1:
resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
+ whatwg-encoding@3.1.1:
+ resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
+ engines: {node: '>=18'}
+ deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation
+
+ whatwg-mimetype@4.0.0:
+ resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==}
+ engines: {node: '>=18'}
+
which-pm-runs@1.1.0:
resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==}
engines: {node: '>=4'}
@@ -1638,13 +1819,23 @@ packages:
resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
engines: {node: '>=18'}
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
xxhash-wasm@1.1.0:
resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==}
+ yallist@5.0.0:
+ resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
+ engines: {node: '>=18'}
+
yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
+ yauzl@2.10.0:
+ resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==}
+
yocto-queue@1.2.2:
resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==}
engines: {node: '>=12.20'}
@@ -1676,6 +1867,13 @@ packages:
snapshots:
+ '@antfu/install-pkg@1.1.0':
+ dependencies:
+ package-manager-detector: 1.6.0
+ tinyexec: 1.0.2
+
+ '@antfu/utils@8.1.1': {}
+
'@astrojs/compiler@2.13.1': {}
'@astrojs/internal-helpers@0.7.5': {}
@@ -1900,6 +2098,39 @@ snapshots:
'@esbuild/win32-x64@0.27.3':
optional: true
+ '@iconify-json/tabler@1.2.26':
+ dependencies:
+ '@iconify/types': 2.0.0
+
+ '@iconify/tools@4.2.0':
+ dependencies:
+ '@iconify/types': 2.0.0
+ '@iconify/utils': 2.3.0
+ cheerio: 1.2.0
+ domhandler: 5.0.3
+ extract-zip: 2.0.1
+ local-pkg: 1.1.2
+ pathe: 2.0.3
+ svgo: 3.3.2
+ tar: 7.5.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@iconify/types@2.0.0': {}
+
+ '@iconify/utils@2.3.0':
+ dependencies:
+ '@antfu/install-pkg': 1.1.0
+ '@antfu/utils': 8.1.1
+ '@iconify/types': 2.0.0
+ debug: 4.4.3
+ globals: 15.15.0
+ kolorist: 1.8.0
+ local-pkg: 1.1.2
+ mlly: 1.8.0
+ transitivePeerDependencies:
+ - supports-color
+
'@img/colour@1.0.0':
optional: true
@@ -1997,6 +2228,10 @@ snapshots:
'@img/sharp-win32-x64@0.34.5':
optional: true
+ '@isaacs/fs-minipass@4.0.1':
+ dependencies:
+ minipass: 7.1.3
+
'@jridgewell/sourcemap-codec@1.5.5': {}
'@knadh/oat@0.3.0': {}
@@ -2119,6 +2354,8 @@ snapshots:
'@shikijs/vscode-textmate@10.0.2': {}
+ '@trysound/sax@0.2.0': {}
+
'@types/debug@4.1.12':
dependencies:
'@types/ms': 2.1.0
@@ -2139,8 +2376,18 @@ snapshots:
dependencies:
'@types/unist': 3.0.3
+ '@types/node@25.3.0':
+ dependencies:
+ undici-types: 7.18.2
+ optional: true
+
'@types/unist@3.0.3': {}
+ '@types/yauzl@2.10.3':
+ dependencies:
+ '@types/node': 25.3.0
+ optional: true
+
'@ungap/structured-clone@1.3.0': {}
acorn@8.15.0: {}
@@ -2166,7 +2413,15 @@ snapshots:
array-iterate@2.0.1: {}
- astro@5.17.2(rollup@4.57.1)(typescript@5.9.3):
+ astro-icon@1.1.5:
+ dependencies:
+ '@iconify/tools': 4.2.0
+ '@iconify/types': 2.0.0
+ '@iconify/utils': 2.3.0
+ transitivePeerDependencies:
+ - supports-color
+
+ astro@5.17.2(@types/node@25.3.0)(rollup@4.57.1)(typescript@5.9.3):
dependencies:
'@astrojs/compiler': 2.13.1
'@astrojs/internal-helpers': 0.7.5
@@ -2223,8 +2478,8 @@ snapshots:
unist-util-visit: 5.1.0
unstorage: 1.17.4
vfile: 6.0.3
- vite: 6.4.1
- vitefu: 1.1.1(vite@6.4.1)
+ vite: 6.4.1(@types/node@25.3.0)
+ vitefu: 1.1.1(vite@6.4.1(@types/node@25.3.0))
xxhash-wasm: 1.1.0
yargs-parser: 21.1.1
yocto-spinner: 0.2.3
@@ -2287,6 +2542,8 @@ snapshots:
widest-line: 5.0.0
wrap-ansi: 9.0.2
+ buffer-crc32@0.2.13: {}
+
camelcase@8.0.0: {}
ccount@2.0.1: {}
@@ -2299,10 +2556,35 @@ snapshots:
character-entities@2.0.2: {}
+ cheerio-select@2.1.0:
+ dependencies:
+ boolbase: 1.0.0
+ css-select: 5.2.2
+ css-what: 6.2.2
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ domutils: 3.2.2
+
+ cheerio@1.2.0:
+ dependencies:
+ cheerio-select: 2.1.0
+ dom-serializer: 2.0.0
+ domhandler: 5.0.3
+ domutils: 3.2.2
+ encoding-sniffer: 0.2.1
+ htmlparser2: 10.1.0
+ parse5: 7.3.0
+ parse5-htmlparser2-tree-adapter: 7.1.0
+ parse5-parser-stream: 7.1.2
+ undici: 7.22.0
+ whatwg-mimetype: 4.0.0
+
chokidar@5.0.0:
dependencies:
readdirp: 5.0.0
+ chownr@3.0.0: {}
+
ci-info@4.4.0: {}
cli-boxes@3.0.0: {}
@@ -2313,8 +2595,14 @@ snapshots:
commander@11.1.0: {}
+ commander@7.2.0: {}
+
common-ancestor-path@1.0.1: {}
+ confbox@0.1.8: {}
+
+ confbox@0.2.4: {}
+
cookie-es@1.2.2: {}
cookie@1.1.1: {}
@@ -2336,6 +2624,11 @@ snapshots:
mdn-data: 2.0.28
source-map-js: 1.2.1
+ css-tree@2.3.1:
+ dependencies:
+ mdn-data: 2.0.30
+ source-map-js: 1.2.1
+
css-tree@3.1.0:
dependencies:
mdn-data: 2.12.2
@@ -2404,10 +2697,21 @@ snapshots:
emoji-regex@8.0.0: {}
+ encoding-sniffer@0.2.1:
+ dependencies:
+ iconv-lite: 0.6.3
+ whatwg-encoding: 3.1.1
+
+ end-of-stream@1.4.5:
+ dependencies:
+ once: 1.4.0
+
entities@4.5.0: {}
entities@6.0.1: {}
+ entities@7.0.1: {}
+
es-module-lexer@1.7.0: {}
esbuild@0.25.12:
@@ -2478,8 +2782,24 @@ snapshots:
eventemitter3@5.0.4: {}
+ exsolve@1.0.8: {}
+
extend@3.0.2: {}
+ extract-zip@2.0.1:
+ dependencies:
+ debug: 4.4.3
+ get-stream: 5.2.0
+ yauzl: 2.10.0
+ optionalDependencies:
+ '@types/yauzl': 2.10.3
+ transitivePeerDependencies:
+ - supports-color
+
+ fd-slicer@1.1.0:
+ dependencies:
+ pend: 1.2.0
+
fdir@6.5.0(picomatch@4.0.3):
optionalDependencies:
picomatch: 4.0.3
@@ -2499,8 +2819,14 @@ snapshots:
get-east-asian-width@1.4.0: {}
+ get-stream@5.2.0:
+ dependencies:
+ pump: 3.0.3
+
github-slugger@2.0.0: {}
+ globals@15.15.0: {}
+
h3@1.15.5:
dependencies:
cookie-es: 1.2.2
@@ -2604,8 +2930,19 @@ snapshots:
html-void-elements@3.0.0: {}
+ htmlparser2@10.1.0:
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ domutils: 3.2.2
+ entities: 7.0.1
+
http-cache-semantics@4.2.0: {}
+ iconv-lite@0.6.3:
+ dependencies:
+ safer-buffer: 2.1.2
+
import-meta-resolve@4.2.0: {}
iron-webcrypto@1.2.1: {}
@@ -2630,6 +2967,14 @@ snapshots:
kleur@3.0.3: {}
+ kolorist@1.8.0: {}
+
+ local-pkg@1.1.2:
+ dependencies:
+ mlly: 1.8.0
+ pkg-types: 2.3.0
+ quansync: 0.2.11
+
longest-streak@3.1.0: {}
lru-cache@11.2.6: {}
@@ -2768,6 +3113,8 @@ snapshots:
mdn-data@2.0.28: {}
+ mdn-data@2.0.30: {}
+
mdn-data@2.12.2: {}
micromark-core-commonmark@2.0.3:
@@ -2961,6 +3308,19 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ minipass@7.1.3: {}
+
+ minizlib@3.1.0:
+ dependencies:
+ minipass: 7.1.3
+
+ mlly@1.8.0:
+ dependencies:
+ acorn: 8.15.0
+ pathe: 2.0.3
+ pkg-types: 1.3.1
+ ufo: 1.6.3
+
mrmime@2.0.1: {}
ms@2.1.3: {}
@@ -2991,6 +3351,10 @@ snapshots:
ohash@2.0.11: {}
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
oniguruma-parser@0.12.1: {}
oniguruma-to-es@4.3.4:
@@ -3021,10 +3385,23 @@ snapshots:
unist-util-visit-children: 3.0.0
vfile: 6.0.3
+ parse5-htmlparser2-tree-adapter@7.1.0:
+ dependencies:
+ domhandler: 5.0.3
+ parse5: 7.3.0
+
+ parse5-parser-stream@7.1.2:
+ dependencies:
+ parse5: 7.3.0
+
parse5@7.3.0:
dependencies:
entities: 6.0.1
+ pathe@2.0.3: {}
+
+ pend@1.2.0: {}
+
piccolore@0.1.3: {}
picocolors@1.1.1: {}
@@ -3033,6 +3410,18 @@ snapshots:
picomatch@4.0.3: {}
+ pkg-types@1.3.1:
+ dependencies:
+ confbox: 0.1.8
+ mlly: 1.8.0
+ pathe: 2.0.3
+
+ pkg-types@2.3.0:
+ dependencies:
+ confbox: 0.2.4
+ exsolve: 1.0.8
+ pathe: 2.0.3
+
postcss@8.5.6:
dependencies:
nanoid: 3.3.11
@@ -3056,6 +3445,13 @@ snapshots:
property-information@7.1.0: {}
+ pump@3.0.3:
+ dependencies:
+ end-of-stream: 1.4.5
+ once: 1.4.0
+
+ quansync@0.2.11: {}
+
radix3@1.1.2: {}
readdirp@5.0.0: {}
@@ -3194,6 +3590,8 @@ snapshots:
s.color@0.0.15: {}
+ safer-buffer@2.1.2: {}
+
sass-formatter@0.7.9:
dependencies:
suf-log: 2.5.3
@@ -3282,6 +3680,16 @@ snapshots:
dependencies:
s.color: 0.0.15
+ svgo@3.3.2:
+ dependencies:
+ '@trysound/sax': 0.2.0
+ commander: 7.2.0
+ css-select: 5.2.2
+ css-tree: 2.3.1
+ css-what: 6.2.2
+ csso: 5.0.5
+ picocolors: 1.1.1
+
svgo@4.0.0:
dependencies:
commander: 11.1.0
@@ -3292,6 +3700,14 @@ snapshots:
picocolors: 1.1.1
sax: 1.4.4
+ tar@7.5.9:
+ dependencies:
+ '@isaacs/fs-minipass': 4.0.1
+ chownr: 3.0.0
+ minipass: 7.1.3
+ minizlib: 3.1.0
+ yallist: 5.0.0
+
tiny-inflate@1.0.3: {}
tinyexec@1.0.2: {}
@@ -3322,6 +3738,11 @@ snapshots:
uncrypto@0.1.3: {}
+ undici-types@7.18.2:
+ optional: true
+
+ undici@7.22.0: {}
+
unified@11.0.5:
dependencies:
'@types/unist': 3.0.3
@@ -3406,7 +3827,7 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.3
- vite@6.4.1:
+ vite@6.4.1(@types/node@25.3.0):
dependencies:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.3)
@@ -3415,14 +3836,21 @@ snapshots:
rollup: 4.57.1
tinyglobby: 0.2.15
optionalDependencies:
+ '@types/node': 25.3.0
fsevents: 2.3.3
- vitefu@1.1.1(vite@6.4.1):
+ vitefu@1.1.1(vite@6.4.1(@types/node@25.3.0)):
optionalDependencies:
- vite: 6.4.1
+ vite: 6.4.1(@types/node@25.3.0)
web-namespaces@2.0.1: {}
+ whatwg-encoding@3.1.1:
+ dependencies:
+ iconv-lite: 0.6.3
+
+ whatwg-mimetype@4.0.0: {}
+
which-pm-runs@1.1.0: {}
widest-line@5.0.0:
@@ -3435,10 +3863,19 @@ snapshots:
string-width: 7.2.0
strip-ansi: 7.1.2
+ wrappy@1.0.2: {}
+
xxhash-wasm@1.1.0: {}
+ yallist@5.0.0: {}
+
yargs-parser@21.1.1: {}
+ yauzl@2.10.0:
+ dependencies:
+ buffer-crc32: 0.2.13
+ fd-slicer: 1.1.0
+
yocto-queue@1.2.2: {}
yocto-spinner@0.2.3:
diff --git a/src/components/Sidebar.astro b/src/components/Sidebar.astro
index 6f17ad3..2da893f 100644
--- a/src/components/Sidebar.astro
+++ b/src/components/Sidebar.astro
@@ -1,4 +1,6 @@
---
+import { Icon } from "astro-icon/components";
+
const { pathname } = Astro.url;
const year = new Date().getFullYear();
@@ -7,9 +9,16 @@ const currentPath =
? pathname.slice(0, -1)
: pathname;
const navItems = [
- { href: "/", label: "About" },
- { href: "/now", label: "Now" },
- { href: "/writing", label: "Writing" },
+ { href: "/", label: "Home", icon: "tabler:smart-home" },
+ { href: "/work", label: "Work", icon: "tabler:code" },
+ { href: "/photography", label: "Photography", icon: "tabler:photo" },
+ { href: "/homelab", label: "Homelab", icon: "tabler:server-2" },
+ {
+ href: "/proglog",
+ label: "Triathlon Logbook",
+ icon: "tabler:book-2",
+ },
+ { href: "/blog", label: "Blog", icon: "tabler:writing-filled" },
];
---
@@ -20,9 +29,10 @@ const navItems = [
-
+
diff --git a/src/content/blog/another-move-to-linux.md b/src/content/blog/another-move-to-linux.md
new file mode 100644
index 0000000..ad7435a
--- /dev/null
+++ b/src/content/blog/another-move-to-linux.md
@@ -0,0 +1,73 @@
+---
+title: An(other) attempt to move to Wayland on my nVidia desktop
+tags:
+ - linux
+ - nixos
+publishedAt: 2025-11-29T17:09:00+01:00
+lastUpdatedAt: 2025-11-29T17:09:00+01:00
+isPublic: true
+---
+
+I recently found myself with a few days off and some time to spare to upgrade (or rather downsize) my desktop PC. The last few months it gathered a bit of dust, as I mostly worked on some lightweight projects or on my [servers](./selfhosted) from my Macbook Air. While I do love its hardware, I resent window management on MacOS. [AeroSpace](https://github.com/nikitabobko/AeroSpace) makes it bearable, but it ultimately can only be a bolt-on solution due to the limited MacOS API surface. To see if the grass on the other side of the window management fence is actually greener and to scratch the itch of toying around with some hardware, I layed down the following plan.
+
+## Hardware
+
+I wanted to make a bit of room in my office and downsize my PC from an ATX case ([Corsair 4000D Airflow](https://www.corsair.com/de/de/p/pc-cases/cc-9011201-ww/4000d-airflow-tempered-glass-mid-tower-atx-case-white-cc-9011201-ww)) to a smaller case. As I've already gone for a mATX-board within that case, I went looking around for a small mATX option to not break the bank by changing out all of my components. The most compelling (for me, as it was the smallest) option came from Jonsbo. I'm already using one of their cases for my self-built [home server](./selfhosted#home-server) and am generally pretty satisfied with it, so I went with the [C6](https://www.jonsbo.com/en/products/C6HandleBlack.html). I've heard of some issues with the [airflow](https://www.youtube.com/watch?v=5U8-58YHaEs&pp=ygUJYzYgam9uc2Jv) - especially when using it with an ATX power supply - but ultimately pulled the trigger because of its size. If there are issues with it I might buy a SFX power supply to mitigate those problems.
+
+The only non-compatible hardware component I owned turned out to be my CPU cooler, a huge [Noctua NH-D15](https://www.noctua.at/en/products/nh-d15) air cooler that I switched out for a smaller [Noctua NH-L9x65](https://www.noctua.at/en/products/nh-l9x65) as the case only allows for about 8-9 centimeters of clearance when using an ATX power supply.
+
+The C6 can't accomodate full size graphics cards, which did not present an issue, as I am currently owning a small form-factor nVidia RTX 3060Ti (which I want to change out for an AMD card down the line). This card - and its predecessor, my GTX 1070 - proved to be the showstoppers last time I've tried to switch to Linux and more specifically Wayland.
+
+## Software
+
+Which brings me to the software I use. I've always liked working with Tiling Window Managers since my first experiment with them on my Dell XPS 13 a few years back, where I mainly used [i3](https://i3wm.org/). At that time I routinely travelled 5-6 hours by train, often without the option to charge a device during the ride. The Dell was not up to the task, so I went for an ARM-based Macbook. To still taste the sweet nectar of tiling window management, I first used [yabai](https://github.com/koekeishiya/yabai) and not long after switched to [AeroSpace](https://github.com/nikitabobko/AeroSpace).
+
+Over time I grew frustrated with some aspects of MacOS, though and yearned for change. It is currently not economically viable for me to switch my notebook back to an x86 device running Linux even though my battery life requirements have loosened. The next best device to experiment on - besides the aforementioned servers, with serve a wildly different use case than my personal computing devivces - was my desktop PC.
+
+I was a bit hesitant to begin working on that, because of some failed attempts in the past. Not to go too much into detail, there were a few things that made me switch back to Linux everytime:
+
+- My nVidia-based graphics card together with the desire to not run X11
+- Playing League of Legends with some of my old friends, especially with the introduction of Vanguard, killing any hope of running it on Linux
+- Using Lightroom to edit the photos I am taking
+
+Over time some of that changed:
+
+- Greatly improved nVidia support for Wayland
+- Playing fewer games in general and if so, mostly those that are also available on my Steam Deck
+- Moving to Photomator on MacOS to edit my photos
+
+Lastly, I've always closely followed some Linux communities and took note of [niri](https://github.com/YaLTeR/niri). The idea of a scrolling window manager seemed interesting, so I yearned to try it out. The project included some [nVidia-specific documentation](https://yalter.github.io/niri/Nvidia.html) which gave me the confidence to try it out with my setup.
+
+In addition to that, I had great success with using NixOS on my servers (and `nix-darwin` on my Mac) and wanted to use it on my desktop, too. Ultimately I've settled on these tools:
+
+- [NixOS](https://nixos.org/) as the base OS, for declarative package and device management
+- [niri](https://github.com/YaLTeR/niri) as the window manager
+- [ironbar](https://github.com/JakeStanger/ironbar), due to its accessible but extensive configuration options
+- [fuzzel](https://codeberg.org/dnkl/fuzzel), due to its simplicity and dmenu mode
+- [swaync](https://github.com/ErikReider/SwayNotificationCenter), due to having a configurable control center
+- [awww](https://codeberg.org/LGFae/awww), due to its runtime-based wallpaper management
+
+The only issues I've found so far were with [Wezterm](https://wezterm.org/). It started lagging a lot after being open a few minutes, probably because I am using nVidia. I did not want to disable Wayland in its configuration due to other issues, so I went with [Ghostty](https://ghostty.org/docs) instead. So far I cannot report any problems with it. The only thing I've lost is some of my custom Lua config that is not replicable in Ghostty, especially concerning session/project management. As I do not want to go back to using `tmux` for that, I approximated my previous setup with a `fuzzel` script (more on that in [this blog post](./fuzzel-scripts)). So far I did not run into any non-solvable problems and am pretty happy with `niri` as well. Steam games run well with Proton and I switched to using GIMP and Krita for some creative endeavours, which eased the transition as well.
+
+Even the dreaded nVidia support was as simple as enabling (my `nix-config` is currently private, but I am going to update this article as soon as I made the repository public for reference):
+
+```nix
+hardware = {
+ graphics.enable = true;
+ nvidia = {
+ modesetting.enable = true;
+ powerManagement.enable = false;
+ powerManagement.finegrained = false;
+ open = true;
+ nvidiaSettings = true;
+ package = config.boot.kernelPackages.nvidiaPackages.stable;
+ };
+ };
+};
+```
+
+Overall I feel more in control of my computing environment again and less bound to the decisions of some multi-national corporations. If this experiment proves to be a success, I am planning to move all of my computing devices back to Linux in the coming year.
+
+## An escape hatch
+
+To be truthful, I still have two escape hatches at the moment. Should the need arise to run some software (or a software alternative) that is not available on Linux, I can fall back to my Macbook. Also, for the occasional game that does not run on Linux due to kernel-level anti-cheat, I've purchased a small, inexpensive 256GB M.2 SSD. I'll track how often I am booting into it over the next few months. If that number is low enough, I might repurpose it as a boot drive for my home server and look for a larger drive to extend the space for the OS I actually want to work and play in.
diff --git a/src/content/blog/fuzzel-scripts.md b/src/content/blog/fuzzel-scripts.md
new file mode 100644
index 0000000..c5b9ead
--- /dev/null
+++ b/src/content/blog/fuzzel-scripts.md
@@ -0,0 +1,178 @@
+---
+title: Scripting with fuzzel (and niri)
+tags:
+ - linux
+ - nixos
+ - ghostty
+ - niri
+publishedAt: 2025-11-30:09:00+01:00
+lastUpdatedAt: 2025-11-30:09:00+01:00
+isPublic: true
+---
+
+I've recently [moved to linux](./another-move-to-linux) on my desktop PC. Growing accustomed to some workflows and tools on my other machines, I wanted some of the niceties on linux as well - to be precise:
+
+- Quickly launch a SSH session to some of my configured hosts in a new terminal window
+- Have a clipboard history accessible from my launcher
+- Open a browser and a terminal at a specific project location in a separate workspace
+- Trigger device actions (shutdown, screenshot, logout) through my launcher
+
+While some of the more popular Wayland launchers on linux provide these features out of the box, I've chosen [fuzzel](https://codeberg.org/dnkl/fuzzel) for its simplicity and therefore wanted to extend its functionality for my specific use case. `fuzzel` provides a [dmenu mode](https://codeberg.org/dnkl/fuzzel/src/branch/master/doc/fuzzel.1.scd) which allows for fuzzy finding generic text and providing a selected option for further processing. The most accessible way of scripting `fuzzel` therefore are some good-old bash scripts, which I've gathered here for reference.
+
+## Launch SSH sessions for hosts in SSH config
+
+I often have the need to quickly open a SSH session to one of the devices defined in my SSH config, so I've written a script that:
+
+1. Reads the possible hosts from a SSH config file with `cat`, `grep`, `sort` and `tail`
+2. Provides the hosts as newline-separated text to fuzzel in dmenu mode
+3. Opens a new `ghostty` terminal that initializes a shell (`fish` in my case) and immediately connects to the selected host
+
+This is the script I've ended up with (change out `ghostty` and `fish` for your use case):
+
+```sh
+#!/bin/sh
+fish_executable="/run/current-system/sw/bin/fish" # Only applicable for NixOS
+selected=$(cat ~/.ssh/config | grep "Host " | cut -d " " -f 2 | sort | tail -n +2 | fuzzel --dmenu --prompt "Connect to: ")
+
+if [ "$selected" != "" ]; then
+ ghostty -e "$fish_executable" -c "ssh $selected"
+fi
+
+```
+
+## Searching through clipboard history
+
+My clipboard manager of choice is `cliphist`, which already provides instructions on how to use it with fuzzel in their [documentation](https://github.com/sentriz/cliphist?tab=readme-ov-file#picker-examples).
+
+## Open a workspace with project tools
+
+Up until my move to `ghostty` I've used `wezterm` to quickly open a terminal at a project's location to start working on it. I do not have the need for persistent sessions as of now, but the ability to quickly start working on a project was something I wanted to keep. To allow for this, I moved the project selector out of `wezterm` and into `fuzzel` as `ghostty` does not have the same capabilities as of now. I already keep all my projects in a single `/dev` directory in `home/$USER` so reading these with `fd` was not a huge task. Similarly to the other scripts, the selected option provided by `fuzzel` is then used to start a new `ghostty` instance with its working directory set to the project root. To further separate the project from what I am doing now, I am using niri's [IPC](https://github.com/YaLTeR/niri/wiki/IPC) to create a new workspace with both the project terminal as well as a new browser window.
+
+To prettify the output I provided both the project name as well as their full paths to `fuzzel`. It already supports selecting parts of a line of text for display and output by utilizing the `--with-nth` and `--accept-nth` options. Text is split into `n` parts on `\t` (configurable through `--nth-delimiter`) when passing it to `fuzzel`. `--with-nth=1` is then used to show only the first part of the string - in this case the path basename of the project - and `--accept-nth=2` makes sure that the bash variable I declare in my script is set to the full path.
+
+```sh
+#!/bin/sh
+projects=$(fd -d=1 -t=d . ~/dev)
+projects_with_names=()
+
+for project in ${projects[*]}; do
+ projects_with_names+=("$(basename $project)\t$project")
+done
+
+selected=$(printf "$projects_with_names" | fuzzel --dmenu --with-nth=1 --accept-nth=2 --prompt "Work on: ")
+
+if [ "$selected" != "" ]; then
+ niri msg action focus-workspace "code"
+ firefox &
+ ghostty --working-directory="$selected"
+fi
+```
+
+## Trigger device actions
+
+Lastly I wanted to trigger some device actions not only through their CLI commands but also visually from my launcher. The easiest way I've found to achive that, was to create XDG desktop entries. These are already searchable from Fuzzel by default and thus no further setup is needed. The only potential downside is that they are mixed in with other applications - which does not matter to me in the slightest, as the fuzzy search takes care of selecting the correct entry.
+
+This is an example desktop entry used to start niri's built-in screenshot tool from `fuzzel` (refer to the [specification](https://specifications.freedesktop.org/desktop-entry/latest/) for more options):
+
+```sh
+[Desktop Entry]
+Type=Application
+Version=1.0
+Name=Screenshot
+Comment=Niris screenshot tool
+Exec=niri msg action screenshot
+# Provided by the Reversal icon theme that I use
+Icon=screenie
+Terminal=false
+```
+
+I've added multiple desktop entries for all kinds of actions as well as entries for triggering the other fuzzel scripts. This allows me to e.g. open the `Connect with SSH` entry, which starts a subsequent `fuzzel` selection as described above.
+
+## Putting it all together with Nix
+
+Overall these little niceties allow me for seamless context switching, action triggering and generally efficient computer usage. As I am using `nix` for all of my devices the last step was to write a Home Manager configuration, so that this setup is replicated wherever needed:
+
+```sh
+{ config, pkgs, ... }:
+
+{
+ # The scripts are copied from my nix-config repo to ~/.config/fuzzel/bin
+ xdg.configFile."fuzzel/bin" = {
+ source = config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/dev/nix-config/modules/wm/fuzzel/scripts";
+ };
+
+ xdg.desktopEntries = {
+ fuzzel-ssh = {
+ type = "Application";
+ name = "SSH";
+ exec = "${config.home.homeDirectory}/.config/fuzzel/bin/fuzzel-ssh.sh";
+ icon = "ksmserver";
+ };
+ fuzzel-cliphist = {
+ type = "Application";
+ name = "Clipboard History";
+ exec = "${config.home.homeDirectory}/.config/fuzzel/bin/fuzzel-cliphist.sh";
+ icon = "xclipboard";
+ };
+ open-project = {
+ type = "Application";
+ name = "Open Project";
+ exec = "${config.home.homeDirectory}/.config/fuzzel/bin/fuzzel-projects.sh";
+ icon = "multitasking-view";
+ };
+ screenshot = {
+ type = "Application";
+ name = "Screenshot";
+ exec = "niri msg action screenshot";
+ icon = "screenie";
+ };
+ screenshot-screen = {
+ type = "Application";
+ name = "Screenshot Screen";
+ exec = "niri msg action screenshot-screen";
+ icon = "screenie";
+ };
+ color-pickers = {
+ type = "Application";
+ name = "Color Picker";
+ exec = "hyprpicker -a -f=hex -n -l -q";
+ icon = "colorpicker";
+ };
+ # This opens the Snacks picker in neovim directly within my notes
+ # repo in a new ghostty window
+ notes = {
+ type = "Application";
+ name = "Notes";
+ exec = "ghostty --working-directory=${config.home.homeDirectory}/notes -e nvim -c \":lua Snacks.picker('files')\"";
+ icon = "gnotes";
+ };
+ lock = {
+ type = "Application";
+ name = "Lock";
+ exec = "hyprlock";
+ icon = "lock-screen";
+ };
+ logout = {
+ type = "Application";
+ name = "Logout";
+ exec = "niri msg action quit";
+ icon = "administration";
+ };
+ shutdown = {
+ type = "Application";
+ name = "Shutdown";
+ exec = "shutdown now";
+ icon = "com.github.bcedu.shutdownscheduler";
+ };
+ };
+
+ programs.fuzzel = {
+ enable = true;
+ settings = { ... };
+ };
+}
+```
+
+## Alternatives
+
+The [vicinae launcher](https://github.com/vicinaehq/vicinae) looks very promising - especially because I am using Raycast on MacOS. It brings most of the features I use (as well as those that I scripted above) and allows for extensions as well as a dmenu mode. I might try out that in the future. Currently I am happy with the simplicity of fuzzel, so the need for change is not too great.
diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro
index d342ff5..cd04d91 100644
--- a/src/layouts/Layout.astro
+++ b/src/layouts/Layout.astro
@@ -37,13 +37,16 @@ const { title } = Astro.props;
font-size: 16px;
}
- html,
- body {
+ html {
margin: 0;
width: 100%;
height: 100%;
}
+ body {
+ margin: 0;
+ }
+
:root {
/* Oat UI */
--background: #ffffff;
@@ -56,10 +59,12 @@ const { title } = Astro.props;
--container-sm: 480px;
}
+ img {
+ width: 100%;
+ max-width: var(--container-lg);
+ }
+
[data-main-layout] {
- margin-top: 3rem;
- padding: 0.5rem;
- padding-left: 0;
- padding-right: 1rem;
+ padding: 3rem 4rem 3rem 3rem;
}
diff --git a/src/pages/blog/[id].astro b/src/pages/blog/[id].astro
new file mode 100644
index 0000000..1822935
--- /dev/null
+++ b/src/pages/blog/[id].astro
@@ -0,0 +1,37 @@
+---
+import { getCollection, render } from "astro:content";
+import Layout from "../../layouts/Layout.astro";
+
+export async function getStaticPaths() {
+ const entries = await getCollection("blog");
+ return entries
+ .filter((entry) => (import.meta.env.PROD ? !!entry.data.isPublic : true))
+ .map((entry) => ({
+ params: { id: entry.id },
+ props: { entry },
+ }));
+}
+
+const { entry } = Astro.props;
+const { Content } = await render(entry);
+---
+
+
+
+
diff --git a/src/pages/homelab.astro b/src/pages/homelab.astro
new file mode 100644
index 0000000..5d72191
--- /dev/null
+++ b/src/pages/homelab.astro
@@ -0,0 +1,8 @@
+---
+import Layout from "../layouts/Layout.astro";
+---
+
+
+
Homelab
+
In Progress ...
+
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 749072c..f3a182b 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -4,12 +4,4 @@ import Layout from "../layouts/Layout.astro";
Welcome!
-
-
-
diff --git a/src/pages/legal.md b/src/pages/legal.md
new file mode 100644
index 0000000..94fccdd
--- /dev/null
+++ b/src/pages/legal.md
@@ -0,0 +1,33 @@
+---
+layout: ../layouts/Layout.astro
+---
+
+# Impressum
+
+## Angaben gemäß §5 TMG
+
+Dennis Schöpf
+
+## Kontakt
+
+E-Mail: [services@dnsc.io](mailto:services@dnsc.io)
+
+## Haftung für Inhalte
+
+Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen.
+
+Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen.
+
+## Haftung für Links
+
+Unser Angebot enthält Links zu externen Websites Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar.
+
+Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.
+
+## Urheberrecht
+
+Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet.
+
+Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.
+
+Quelle: [e-recht24.de](https://www.e-recht24.de/)
diff --git a/src/pages/now.md b/src/pages/now.md
new file mode 100644
index 0000000..90ae463
--- /dev/null
+++ b/src/pages/now.md
@@ -0,0 +1,20 @@
+---
+layout: ../layouts/Layout.astro
+---
+
+# Now
+
+This section is inspired by all the pages on [Nownownow](https://nownownow.com/). It acts as a showcase on what's currently going on in my professional and personal life.
+
+I am currently working at [Digital H](https://digital-h.de) as a senior software engineer. Here's what I am doing now:
+
+- Pursuing Kubernetes Administration certification (Linux Foundation) to deepen my Kubernetes and general DevOps knowledge
+- Conceptualize the next step for our public transport mobile application -- An application that adapts to the user instead of the other way around
+- Set up internal knowledge sharing structures and internal dev tooling within the company
+- Continually test how AI tools and agents can improve my throughput and software quality
+
+Here's what's going on in my personal life right now:
+
+- Training for the [Ironman Barcelona](https://www.ironman.com/races/im-barcelona) in 2026 with [Challenge Walchsee](http://challenge-walchsee.com) as an intermediate middle-distance goal
+- Building and provisioning my homelab using NixOS
+- Building small (mainly CLI) helpers and experimenting around with different programming languages (currently Odin & Go)
diff --git a/src/pages/photography.astro b/src/pages/photography.astro
new file mode 100644
index 0000000..ec99404
--- /dev/null
+++ b/src/pages/photography.astro
@@ -0,0 +1,8 @@
+---
+import Layout from "../layouts/Layout.astro";
+---
+
+
+
Photography
+
In Progress ...
+
diff --git a/src/pages/proglog.astro b/src/pages/proglog.astro
new file mode 100644
index 0000000..019f382
--- /dev/null
+++ b/src/pages/proglog.astro
@@ -0,0 +1,8 @@
+---
+import Layout from "../layouts/Layout.astro";
+---
+
+
+
Triathlon Logbook
+
In Progress ...
+
diff --git a/src/pages/work.astro b/src/pages/work.astro
new file mode 100644
index 0000000..70bda07
--- /dev/null
+++ b/src/pages/work.astro
@@ -0,0 +1,8 @@
+---
+import Layout from "../layouts/Layout.astro";
+---
+
+
+