Server issues solved. mdx-remote was the problem

This commit is contained in:
2025-08-30 21:57:07 +02:00
parent 9f4717d707
commit 4e0d77baeb
13 changed files with 552 additions and 185 deletions

View File

@@ -5,6 +5,7 @@ excerpt: "TA & Coordinator for the Operating Systems lecture, focusing on system
teaser: /images/teaching/computer_os.png
icon: /images/teaching/computer_os.png
---
Following the introductory course on Computer Architecture, I also served as a Teaching Assistant and Tutorial Coordinator for the subsequent **"Betriebssysteme" (Operating Systems)** lecture at LMU Munich, taught by Prof. Dr. Linnhoff-Popien. This course typically enrolled 300-400 students per semester.
<InfoBox title="Position Details">
- **Role**: Teaching Assistant, Tutorial Coordinator
@@ -13,8 +14,6 @@ icon: /images/teaching/computer_os.png
- **Materials**: [WS 19/20](https://www.mobile.ifi.lmu.de/lehrveranstaltungen/bs-ws1920/), [WS 18/19](https://www.mobile.ifi.lmu.de/lehrveranstaltungen/bs-ws1819/)
</InfoBox>
Following the introductory course on Computer Architecture, I also served as a Teaching Assistant and Tutorial Coordinator for the subsequent **"Betriebssysteme" (Operating Systems)** lecture at LMU Munich, taught by Prof. Dr. Linnhoff-Popien. This course typically enrolled 300-400 students per semester.
My role involved supporting the lecture and managing the associated tutorial sessions:
- **Tutorial Coordination:** Led a team of 10-12 student tutors, organizing their schedules and ensuring consistent support for the students' learning process.

View File

@@ -6,14 +6,12 @@ teaser: /images/teaching/ios.png
icon: /images/teaching/ios.png
---
Building upon my experience supervising the [Android development practical course](/teaching/android), I also co-supervised the **"iOS Praktikum"** at LMU Munich. This hands-on lab course focused on native mobile application development for the Apple iOS platform using the **Swift** programming language.
<InfoBox title="Project Details">
- **Role**: Practical Course Supervisor / Teaching Assistant
- **Skills**: iOS Development (Swift), Mobile Application Architecture, Client-Server Communication, Wireless Technologies (WiFi/Bluetooth), Location Services (GPS), Agile Methodologies, Team Project Supervision, Code Review
- **Duration**: Winter Semester 2019/20
</InfoBox>
Building upon my experience supervising the [Android development practical course](/teaching/android), I also co-supervised the **"iOS Praktikum"** at LMU Munich. This hands-on lab course focused on native mobile application development for the Apple iOS platform using the **Swift** programming language.
The course was structured in two main phases:
1. **Introductory Phase:** Covered foundational theoretical concepts of iOS development and Swift programming, complemented by practical exercises to solidify understanding.

View File

@@ -23,7 +23,8 @@
"lucide-react": "^0.395.0",
"motion": "^12.7.4",
"next": "14.2.4",
"next-mdx-remote": "^5.0.0",
"mdx-bundler": "^10.0.1",
"esbuild": "^0.23.0",
"next-themes": "^0.3.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -45,7 +46,6 @@
"@types/node": "^20.17.30",
"@types/react": "^18.3.20",
"@types/react-dom": "^18.3.6",
"eslint": "^8.57.1",
"eslint-config-next": "14.2.4",
"postcss": "^8.5.3",
"tailwindcss": "^3.4.17",

490
pnpm-lock.yaml generated
View File

@@ -35,6 +35,9 @@ importers:
clsx:
specifier: ^2.1.1
version: 2.1.1
esbuild:
specifier: ^0.23.0
version: 0.23.1
framer-motion:
specifier: ^11.18.2
version: 11.18.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -44,15 +47,15 @@ importers:
lucide-react:
specifier: ^0.395.0
version: 0.395.0(react@18.3.1)
mdx-bundler:
specifier: ^10.0.1
version: 10.1.1(esbuild@0.23.1)
motion:
specifier: ^12.7.4
version: 12.23.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
next:
specifier: 14.2.4
version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
next-mdx-remote:
specifier: ^5.0.0
version: 5.0.0(@types/react@18.3.24)(react@18.3.1)
next-themes:
specifier: ^0.3.0
version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -111,9 +114,6 @@ importers:
'@types/react-dom':
specifier: ^18.3.6
version: 18.3.7(@types/react@18.3.24)
eslint:
specifier: ^8.57.1
version: 8.57.1
eslint-config-next:
specifier: 14.2.4
version: 14.2.4(eslint@8.57.1)(typescript@5.9.2)
@@ -133,12 +133,8 @@ packages:
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'}
'@babel/code-frame@7.27.1':
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
engines: {node: '>=6.9.0'}
'@babel/helper-validator-identifier@7.27.1':
resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==}
'@babel/runtime@7.28.3':
resolution: {integrity: sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==}
engines: {node: '>=6.9.0'}
'@emnapi/core@1.5.0':
@@ -150,6 +146,155 @@ packages:
'@emnapi/wasi-threads@1.1.0':
resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
'@esbuild-plugins/node-resolve@0.2.2':
resolution: {integrity: sha512-+t5FdX3ATQlb53UFDBRb4nqjYBz492bIrnVWvpQHpzZlu9BQL5HasMZhqc409ygUwOWCXZhrWr6NyZ6T6Y+cxw==}
peerDependencies:
esbuild: '*'
'@esbuild/aix-ppc64@0.23.1':
resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
'@esbuild/android-arm64@0.23.1':
resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.23.1':
resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
'@esbuild/android-x64@0.23.1':
resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
'@esbuild/darwin-arm64@0.23.1':
resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-x64@0.23.1':
resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
'@esbuild/freebsd-arm64@0.23.1':
resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-x64@0.23.1':
resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
'@esbuild/linux-arm64@0.23.1':
resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm@0.23.1':
resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
'@esbuild/linux-ia32@0.23.1':
resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.23.1':
resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-mips64el@0.23.1':
resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-ppc64@0.23.1':
resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-riscv64@0.23.1':
resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-s390x@0.23.1':
resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-x64@0.23.1':
resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
'@esbuild/netbsd-x64@0.23.1':
resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
'@esbuild/openbsd-arm64@0.23.1':
resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-x64@0.23.1':
resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
'@esbuild/sunos-x64@0.23.1':
resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
'@esbuild/win32-arm64@0.23.1':
resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-ia32@0.23.1':
resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-x64@0.23.1':
resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
'@eslint-community/eslint-utils@4.7.0':
resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -168,6 +313,9 @@ packages:
resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
'@fal-works/esbuild-plugin-global-externals@2.1.2':
resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==}
'@floating-ui/core@1.7.3':
resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==}
@@ -213,15 +361,14 @@ packages:
'@jridgewell/trace-mapping@0.3.30':
resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==}
'@mdx-js/esbuild@3.1.1':
resolution: {integrity: sha512-NS35VhTdvKNj5/B1JSD5W3kN1R0WDHgk+zCWq+tSChQw5L2Bgeiz7yyZPFrc5LWuPVOxE1xMbJr82bO9VVzmfQ==}
peerDependencies:
esbuild: '>=0.14.0'
'@mdx-js/mdx@3.1.1':
resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==}
'@mdx-js/react@3.1.1':
resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==}
peerDependencies:
'@types/react': '>=16'
react: '>=16'
'@napi-rs/wasm-runtime@0.2.12':
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
@@ -636,6 +783,9 @@ packages:
'@types/react@18.3.24':
resolution: {integrity: sha512-0dLEBsA1kI3OezMBF8nSsb7Nk19ZnsyE1LLhB8r27KbgU5H4pvuqZLdtE+aUkJVoXgTVuA+iLIwmZ0TuK4tx6A==}
'@types/resolve@1.20.6':
resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==}
'@types/unist@2.0.11':
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
@@ -1150,6 +1300,11 @@ packages:
esast-util-from-js@2.0.1:
resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==}
esbuild@0.23.1:
resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==}
engines: {node: '>=18'}
hasBin: true
escape-string-regexp@4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
@@ -1282,6 +1437,9 @@ packages:
estree-util-to-js@2.0.0:
resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==}
estree-util-value-to-estree@3.4.0:
resolution: {integrity: sha512-Zlp+gxis+gCfK12d3Srl2PdX2ybsEA8ZYy6vQGVQTNNYLEGRQQ56XB64bjemN8kxIKXP1nC9ip4Z+ILy9LGzvQ==}
estree-util-visit@2.0.0:
resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==}
@@ -1315,6 +1473,9 @@ packages:
fastq@1.19.1:
resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
fault@2.0.1:
resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==}
fdir@6.5.0:
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
engines: {node: '>=12.0.0'}
@@ -1351,6 +1512,10 @@ packages:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
format@0.2.2:
resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
engines: {node: '>=0.4.x'}
framer-motion@11.18.2:
resolution: {integrity: sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==}
peerDependencies:
@@ -1810,6 +1975,9 @@ packages:
mdast-util-from-markdown@2.0.2:
resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==}
mdast-util-frontmatter@2.0.1:
resolution: {integrity: sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==}
mdast-util-gfm-autolink-literal@2.0.1:
resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==}
@@ -1852,6 +2020,12 @@ packages:
mdast-util-to-string@4.0.0:
resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
mdx-bundler@10.1.1:
resolution: {integrity: sha512-87FtxC7miUPznwqEaAlJARinHJ6Qin9kDuG2E2BCCNEOszr62kHpqivI/IF/CmwObVSpvApVFFxN1ftM/Gykvw==}
engines: {node: '>=18', npm: '>=6'}
peerDependencies:
esbuild: 0.*
merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
@@ -1859,6 +2033,9 @@ packages:
micromark-core-commonmark@2.0.3:
resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
micromark-extension-frontmatter@2.0.0:
resolution: {integrity: sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==}
micromark-extension-gfm-autolink-literal@2.1.0:
resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==}
@@ -2035,12 +2212,6 @@ packages:
resolution: {integrity: sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==}
hasBin: true
next-mdx-remote@5.0.0:
resolution: {integrity: sha512-RNNbqRpK9/dcIFZs/esQhuLA8jANqlH694yqoDBK8hkVdJUndzzGmnPHa2nyi90N4Z9VmzuSWNRpr5ItT3M7xQ==}
engines: {node: '>=14', npm: '>=7'}
peerDependencies:
react: '>=16'
next-themes@0.3.0:
resolution: {integrity: sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==}
peerDependencies:
@@ -2333,12 +2504,18 @@ packages:
rehype-stringify@10.0.1:
resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==}
remark-frontmatter@5.0.0:
resolution: {integrity: sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==}
remark-gfm@4.0.1:
resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
remark-html@16.0.1:
resolution: {integrity: sha512-B9JqA5i0qZe0Nsf49q3OXyGvyXuZFDzAP2iOFLEumymuYJITVpiH1IgsTEwTpdptDmZlMDMWeDmSawdaJIGCXQ==}
remark-mdx-frontmatter@4.0.0:
resolution: {integrity: sha512-PZzAiDGOEfv1Ua7exQ8S5kKxkD8CDaSb4nM+1Mprs6u8dyvQifakh+kCj6NovfGXW+bTvrhjaR3srzjS2qJHKg==}
remark-mdx@3.1.1:
resolution: {integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==}
@@ -2603,6 +2780,9 @@ packages:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
toml@3.0.0:
resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==}
trim-lines@3.0.1:
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
@@ -2669,9 +2849,6 @@ packages:
unified@11.0.5:
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
unist-util-is@5.2.1:
resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==}
unist-util-is@6.0.0:
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
@@ -2681,18 +2858,12 @@ packages:
unist-util-position@5.0.0:
resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
unist-util-remove@3.1.1:
resolution: {integrity: sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw==}
unist-util-stringify-position@3.0.3:
resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==}
unist-util-stringify-position@4.0.0:
resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
unist-util-visit-parents@5.1.3:
resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==}
unist-util-visit-parents@6.0.1:
resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==}
@@ -2713,12 +2884,13 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
uuid@9.0.1:
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
hasBin: true
vfile-location@5.0.3:
resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==}
vfile-matter@5.0.1:
resolution: {integrity: sha512-o6roP82AiX0XfkyTHyRCMXgHfltUNlXSEqCIS80f+mbAyiQBE2fxtDVMtseyytGx75sihiJFo/zR6r/4LTs2Cw==}
vfile-message@3.1.4:
resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==}
@@ -2793,13 +2965,7 @@ snapshots:
'@alloc/quick-lru@5.2.0': {}
'@babel/code-frame@7.27.1':
dependencies:
'@babel/helper-validator-identifier': 7.27.1
js-tokens: 4.0.0
picocolors: 1.1.1
'@babel/helper-validator-identifier@7.27.1': {}
'@babel/runtime@7.28.3': {}
'@emnapi/core@1.5.0':
dependencies:
@@ -2817,6 +2983,88 @@ snapshots:
tslib: 2.8.1
optional: true
'@esbuild-plugins/node-resolve@0.2.2(esbuild@0.23.1)':
dependencies:
'@types/resolve': 1.20.6
debug: 4.4.1
esbuild: 0.23.1
escape-string-regexp: 4.0.0
resolve: 1.22.10
transitivePeerDependencies:
- supports-color
'@esbuild/aix-ppc64@0.23.1':
optional: true
'@esbuild/android-arm64@0.23.1':
optional: true
'@esbuild/android-arm@0.23.1':
optional: true
'@esbuild/android-x64@0.23.1':
optional: true
'@esbuild/darwin-arm64@0.23.1':
optional: true
'@esbuild/darwin-x64@0.23.1':
optional: true
'@esbuild/freebsd-arm64@0.23.1':
optional: true
'@esbuild/freebsd-x64@0.23.1':
optional: true
'@esbuild/linux-arm64@0.23.1':
optional: true
'@esbuild/linux-arm@0.23.1':
optional: true
'@esbuild/linux-ia32@0.23.1':
optional: true
'@esbuild/linux-loong64@0.23.1':
optional: true
'@esbuild/linux-mips64el@0.23.1':
optional: true
'@esbuild/linux-ppc64@0.23.1':
optional: true
'@esbuild/linux-riscv64@0.23.1':
optional: true
'@esbuild/linux-s390x@0.23.1':
optional: true
'@esbuild/linux-x64@0.23.1':
optional: true
'@esbuild/netbsd-x64@0.23.1':
optional: true
'@esbuild/openbsd-arm64@0.23.1':
optional: true
'@esbuild/openbsd-x64@0.23.1':
optional: true
'@esbuild/sunos-x64@0.23.1':
optional: true
'@esbuild/win32-arm64@0.23.1':
optional: true
'@esbuild/win32-ia32@0.23.1':
optional: true
'@esbuild/win32-x64@0.23.1':
optional: true
'@eslint-community/eslint-utils@4.7.0(eslint@8.57.1)':
dependencies:
eslint: 8.57.1
@@ -2840,6 +3088,8 @@ snapshots:
'@eslint/js@8.57.1': {}
'@fal-works/esbuild-plugin-global-externals@2.1.2': {}
'@floating-ui/core@1.7.3':
dependencies:
'@floating-ui/utils': 0.2.10
@@ -2892,6 +3142,17 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
'@mdx-js/esbuild@3.1.1(esbuild@0.23.1)':
dependencies:
'@mdx-js/mdx': 3.1.1
'@types/unist': 3.0.3
esbuild: 0.23.1
source-map: 0.7.6
vfile: 6.0.3
vfile-message: 4.0.3
transitivePeerDependencies:
- supports-color
'@mdx-js/mdx@3.1.1':
dependencies:
'@types/estree': 1.0.8
@@ -2922,12 +3183,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@mdx-js/react@3.1.1(@types/react@18.3.24)(react@18.3.1)':
dependencies:
'@types/mdx': 2.0.13
'@types/react': 18.3.24
react: 18.3.1
'@napi-rs/wasm-runtime@0.2.12':
dependencies:
'@emnapi/core': 1.5.0
@@ -3306,6 +3561,8 @@ snapshots:
'@types/prop-types': 15.7.15
csstype: 3.1.3
'@types/resolve@1.20.6': {}
'@types/unist@2.0.11': {}
'@types/unist@3.0.3': {}
@@ -3884,6 +4141,33 @@ snapshots:
esast-util-from-estree: 2.0.0
vfile-message: 4.0.3
esbuild@0.23.1:
optionalDependencies:
'@esbuild/aix-ppc64': 0.23.1
'@esbuild/android-arm': 0.23.1
'@esbuild/android-arm64': 0.23.1
'@esbuild/android-x64': 0.23.1
'@esbuild/darwin-arm64': 0.23.1
'@esbuild/darwin-x64': 0.23.1
'@esbuild/freebsd-arm64': 0.23.1
'@esbuild/freebsd-x64': 0.23.1
'@esbuild/linux-arm': 0.23.1
'@esbuild/linux-arm64': 0.23.1
'@esbuild/linux-ia32': 0.23.1
'@esbuild/linux-loong64': 0.23.1
'@esbuild/linux-mips64el': 0.23.1
'@esbuild/linux-ppc64': 0.23.1
'@esbuild/linux-riscv64': 0.23.1
'@esbuild/linux-s390x': 0.23.1
'@esbuild/linux-x64': 0.23.1
'@esbuild/netbsd-x64': 0.23.1
'@esbuild/openbsd-arm64': 0.23.1
'@esbuild/openbsd-x64': 0.23.1
'@esbuild/sunos-x64': 0.23.1
'@esbuild/win32-arm64': 0.23.1
'@esbuild/win32-ia32': 0.23.1
'@esbuild/win32-x64': 0.23.1
escape-string-regexp@4.0.0: {}
escape-string-regexp@5.0.0: {}
@@ -3895,7 +4179,7 @@ snapshots:
'@typescript-eslint/parser': 7.2.0(eslint@8.57.1)(typescript@5.9.2)
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(eslint@8.57.1))(eslint@8.57.1)
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1)
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1)
eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1)
eslint-plugin-react: 7.37.5(eslint@8.57.1)
@@ -3915,7 +4199,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.57.1))(eslint@8.57.1):
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.1
@@ -3930,14 +4214,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1):
eslint-module-utils@2.12.1(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 7.2.0(eslint@8.57.1)(typescript@5.9.2)
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(eslint@8.57.1))(eslint@8.57.1)
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1)
transitivePeerDependencies:
- supports-color
@@ -3952,7 +4236,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.1(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
eslint-module-utils: 2.12.1(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1)
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -4107,6 +4391,10 @@ snapshots:
astring: 1.9.0
source-map: 0.7.6
estree-util-value-to-estree@3.4.0:
dependencies:
'@types/estree': 1.0.8
estree-util-visit@2.0.0:
dependencies:
'@types/estree-jsx': 1.0.5
@@ -4142,6 +4430,10 @@ snapshots:
dependencies:
reusify: 1.1.0
fault@2.0.1:
dependencies:
format: 0.2.2
fdir@6.5.0(picomatch@4.0.3):
optionalDependencies:
picomatch: 4.0.3
@@ -4176,6 +4468,8 @@ snapshots:
cross-spawn: 7.0.6
signal-exit: 4.1.0
format@0.2.2: {}
framer-motion@11.18.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
motion-dom: 11.18.1
@@ -4722,6 +5016,17 @@ snapshots:
transitivePeerDependencies:
- supports-color
mdast-util-frontmatter@2.0.1:
dependencies:
'@types/mdast': 4.0.4
devlop: 1.1.0
escape-string-regexp: 5.0.0
mdast-util-from-markdown: 2.0.2
mdast-util-to-markdown: 2.1.2
micromark-extension-frontmatter: 2.0.0
transitivePeerDependencies:
- supports-color
mdast-util-gfm-autolink-literal@2.0.1:
dependencies:
'@types/mdast': 4.0.4
@@ -4861,6 +5166,21 @@ snapshots:
dependencies:
'@types/mdast': 4.0.4
mdx-bundler@10.1.1(esbuild@0.23.1):
dependencies:
'@babel/runtime': 7.28.3
'@esbuild-plugins/node-resolve': 0.2.2(esbuild@0.23.1)
'@fal-works/esbuild-plugin-global-externals': 2.1.2
'@mdx-js/esbuild': 3.1.1(esbuild@0.23.1)
esbuild: 0.23.1
gray-matter: 4.0.3
remark-frontmatter: 5.0.0
remark-mdx-frontmatter: 4.0.0
uuid: 9.0.1
vfile: 6.0.3
transitivePeerDependencies:
- supports-color
merge2@1.4.1: {}
micromark-core-commonmark@2.0.3:
@@ -4882,6 +5202,13 @@ snapshots:
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
micromark-extension-frontmatter@2.0.0:
dependencies:
fault: 2.0.1
micromark-util-character: 2.1.1
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
micromark-extension-gfm-autolink-literal@2.1.0:
dependencies:
micromark-util-character: 2.1.1
@@ -5191,19 +5518,6 @@ snapshots:
railroad-diagrams: 1.0.0
randexp: 0.4.6
next-mdx-remote@5.0.0(@types/react@18.3.24)(react@18.3.1):
dependencies:
'@babel/code-frame': 7.27.1
'@mdx-js/mdx': 3.1.1
'@mdx-js/react': 3.1.1(@types/react@18.3.24)(react@18.3.1)
react: 18.3.1
unist-util-remove: 3.1.1
vfile: 6.0.3
vfile-matter: 5.0.1
transitivePeerDependencies:
- '@types/react'
- supports-color
next-themes@0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
react: 18.3.1
@@ -5559,6 +5873,15 @@ snapshots:
hast-util-to-html: 9.0.5
unified: 11.0.5
remark-frontmatter@5.0.0:
dependencies:
'@types/mdast': 4.0.4
mdast-util-frontmatter: 2.0.1
micromark-extension-frontmatter: 2.0.0
unified: 11.0.5
transitivePeerDependencies:
- supports-color
remark-gfm@4.0.1:
dependencies:
'@types/mdast': 4.0.4
@@ -5578,6 +5901,15 @@ snapshots:
mdast-util-to-hast: 13.2.0
unified: 11.0.5
remark-mdx-frontmatter@4.0.0:
dependencies:
'@types/mdast': 4.0.4
estree-util-is-identifier-name: 3.0.0
estree-util-value-to-estree: 3.4.0
toml: 3.0.0
unified: 11.0.5
yaml: 2.8.1
remark-mdx@3.1.1:
dependencies:
mdast-util-mdx: 3.0.0
@@ -5927,6 +6259,8 @@ snapshots:
dependencies:
is-number: 7.0.0
toml@3.0.0: {}
trim-lines@3.0.1: {}
trough@2.2.0: {}
@@ -6018,10 +6352,6 @@ snapshots:
trough: 2.2.0
vfile: 6.0.3
unist-util-is@5.2.1:
dependencies:
'@types/unist': 2.0.11
unist-util-is@6.0.0:
dependencies:
'@types/unist': 3.0.3
@@ -6034,12 +6364,6 @@ snapshots:
dependencies:
'@types/unist': 3.0.3
unist-util-remove@3.1.1:
dependencies:
'@types/unist': 2.0.11
unist-util-is: 5.2.1
unist-util-visit-parents: 5.1.3
unist-util-stringify-position@3.0.3:
dependencies:
'@types/unist': 2.0.11
@@ -6048,11 +6372,6 @@ snapshots:
dependencies:
'@types/unist': 3.0.3
unist-util-visit-parents@5.1.3:
dependencies:
'@types/unist': 2.0.11
unist-util-is: 5.2.1
unist-util-visit-parents@6.0.1:
dependencies:
'@types/unist': 3.0.3
@@ -6098,16 +6417,13 @@ snapshots:
util-deprecate@1.0.2: {}
uuid@9.0.1: {}
vfile-location@5.0.3:
dependencies:
'@types/unist': 3.0.3
vfile: 6.0.3
vfile-matter@5.0.1:
dependencies:
vfile: 6.0.3
yaml: 2.8.1
vfile-message@3.1.4:
dependencies:
'@types/unist': 2.0.11

View File

@@ -142,13 +142,3 @@ code[data-line-numbers-max-digits="2"] > [data-line]::before {
code[data-line-numbers-max-digits="3"] > [data-line]::before {
width: 3rem;
}
.prose a {
/* Use the CSS variable we defined in the component */
color: var(--accent-color);
}
.prose a:hover {
/* Optional: slightly darken or lighten the color on hover for better feedback */
opacity: 0.8;
}

View File

@@ -7,7 +7,6 @@ import { cn } from "@/lib/utils";
import type { Metadata } from "next";
import { Inter as FontSans } from "next/font/google";
import "./globals.css";
import { AccentColorProvider } from "@/context/accent-color-context";
const fontSans = FontSans({
subsets: ["latin"],
@@ -65,13 +64,11 @@ export default function RootLayout({
>
<script defer src="https://umami.steffenillium.de/script.js" data-website-id="170441c3-f9ca-4dea-9f44-ba0573b0f9e5"></script>
<ThemeProvider attribute="class" defaultTheme="light">
<AccentColorProvider>
<TooltipProvider delayDuration={0}>
<Header />
{children}
<Navbar />
</TooltipProvider>
</AccentColorProvider>
<TooltipProvider delayDuration={0}>
<Header />
{children}
<Navbar />
</TooltipProvider>
</ThemeProvider>
</body>
</html>

View File

@@ -5,7 +5,7 @@ import { getPublicationsData } from '@/lib/publications';
import { Article } from '@/components/Article';
export default async function ResearchPage({ params }: { params: { slug: string } }) {
// --- FIX: `await` the result, as getPostBySlug is async again ---
// `getPostBySlug` is async, so `await` is correct
const post = await getPostBySlug('research', params.slug);
const publications = getPublicationsData();
@@ -16,7 +16,6 @@ export default async function ResearchPage({ params }: { params: { slug: string
const prevSlug = currentIndex > 0 ? allSlugs[currentIndex - 1] : null;
const nextSlug = currentIndex < allSlugs.length - 1 ? allSlugs[currentIndex + 1] : null;
// These calls need to be awaited as well
const prevPost = prevSlug ? await getPostBySlug('research', prevSlug) : null;
const nextPost = nextSlug ? await getPostBySlug('research', nextSlug) : null;
@@ -25,10 +24,11 @@ export default async function ResearchPage({ params }: { params: { slug: string
next: nextPost ? { slug: nextPost.slug, title: nextPost.frontmatter.title } : null,
};
// The 'post' object now has the correct shape for the <Article> component
return <Article post={post} publications={publications} navigation={navigation} basePath="research" />;
}
// --- No changes needed for these functions ---
// These functions remain unchanged
export async function generateStaticParams() {
const slugs = getPostSlugs('research');
return slugs.map((slug) => ({ slug }));
@@ -39,6 +39,6 @@ export async function generateMetadata({ params }: { params: { slug: string } })
if (!post) { return {}; }
return {
title: post.frontmatter.title,
description: post.frontmatter.description || DATA.description,
description: post.frontmatter.excerpt || DATA.description, // Use excerpt for description
};
}
}

View File

@@ -2,24 +2,25 @@
import { CitationProvider } from '@/context/citation-context';
import { ReferencesContainer } from '@/components/references-container';
import Image from 'next/image';
import { CustomMDX } from '@/components/custom-mdx';
import Link from 'next/link';
import { Publication } from '@/lib/publications';
import { useAccentColor } from '@/context/accent-color-context';
import { ProjectNavigation } from './project-navigation';
// --- FIX: Import the Image component ---
import Image from 'next/image';
// --- The prop types now reflect the output of `compile` ---
interface Post {
content: React.ReactElement; // This is now a compiled component
code: string;
frontmatter: {
title: string;
excerpt?: string;
teaser?: string;
tags?: string[];
// --- FIX: Add the optional 'icon' property to the interface ---
icon?: string;
};
}
interface NavigationLink { slug: string; title: string; }
interface ArticleProps {
post: Post;
@@ -29,8 +30,6 @@ interface ArticleProps {
}
export function Article({ post, publications, navigation, basePath }: ArticleProps) {
const accentColor = useAccentColor();
return (
<CitationProvider publications={publications}>
<main className="flex flex-col min-h-[100dvh] py-8">
@@ -40,15 +39,28 @@ export function Article({ post, publications, navigation, basePath }: ArticlePro
{post.frontmatter.excerpt && (<p className="text-lg text-muted-foreground mt-1">{post.frontmatter.excerpt}</p>)}
</header>
{post.frontmatter.icon && (
<div className="float-left mr-4 mb-0">
<Image
src={post.frontmatter.icon}
alt={`${post.frontmatter.title} icon`}
width={64}
height={64}
className=""
/>
</div>
)}
<div className="mt-8">
{/* --- FIX: Spread the props from the compiled post onto CustomMDX --- */}
<CustomMDX {...post} />
<CustomMDX code={post.code} />
</div>
{post.frontmatter.tags && (
<div className="flex flex-wrap gap-2 mt-8">
{post.frontmatter.tags.map((tag: string) => (
<Link key={tag} href={`/tags/${tag}`} className="px-3 py-1 text-sm font-medium bg-secondary text-secondary-foreground transition-colors" onMouseOver={(e) => e.currentTarget.style.backgroundColor = accentColor} onMouseOut={(e) => e.currentTarget.style.backgroundColor = ''}>{tag}</Link>
<Link key={tag} href={`/tags/${tag}`} className="px-3 py-1 text-sm font-medium bg-secondary text-secondary-foreground transition-colors hover:bg-primary hover:text-primary-foreground">
{tag}
</Link>
))}
</div>
)}

View File

@@ -1,16 +1,14 @@
"use client";
import { MDXRemote, MDXRemoteProps } from 'next-mdx-remote';
import { useMemo } from 'react';
import { getMDXComponent } from 'mdx-bundler/client';
import { mdxComponents } from './mdx';
// This component now receives the entire result from the `compile` function.
// The `source` prop is no longer used here.
export function CustomMDX(props: MDXRemoteProps) {
return (
<MDXRemote
{...props}
// Provide the client-side components for hydration
components={{ ...mdxComponents, ...(props.components || {}) }}
/>
);
interface CustomMDXProps {
code: string;
}
export function CustomMDX({ code }: CustomMDXProps) {
const Component = useMemo(() => getMDXComponent(code), [code]);
return <Component components={{ ...mdxComponents }} />;
}

View File

@@ -0,0 +1,50 @@
"use client";
import Image from "next/image";
import { cn } from "@/lib/utils";
interface FloatingImageProps {
src: string;
alt: string;
width: number;
height: number;
float?: "left" | "right";
caption?: string;
}
export function FloatingImage({
src,
alt,
width,
height,
float = "right", // Default to floating right
caption,
}: FloatingImageProps) {
const floatClasses = {
"float-right ml-6": float === "right",
"float-left mr-6": float === "left",
};
return (
// Use <figure> for semantic HTML, and `not-prose` to escape typography styles
<figure
className={cn(
"not-prose mb-4 w-full sm:w-1/2",
floatClasses
)}
>
<Image
src={src}
alt={alt}
width={width}
height={height}
className="m-0 rounded-lg" // remove default prose margins from image
/>
{caption && (
<figcaption className="mt-2 text-sm text-center italic text-muted-foreground">
{caption}
</figcaption>
)}
</figure>
);
}

View File

@@ -5,6 +5,7 @@ import Link from "next/link";
import React from "react";
import { InfoBox } from "./infobox";
import { Cite } from "./cite";
import { FloatingImage } from "./floating-image";
function CustomLink(props: any) {
@@ -75,16 +76,5 @@ export const mdxComponents = {
a: CustomLink,
InfoBox,
Cite,
FloatingImage: FloatingImage,
};
export const serverSafeComponents = {
// KEEP components that DO NOT use hooks
h1: mdxComponents.h1,
h2: mdxComponents.h2,
h3: mdxComponents.h3,
h4: mdxComponents.h4,
h5: mdxComponents.h5,
h6: mdxComponents.h6,
Image: mdxComponents.Image,
a: mdxComponents.a,
};

View File

@@ -2,7 +2,6 @@
import Link from 'next/link';
import { ArrowLeft, ArrowRight } from 'lucide-react';
import { useAccentColor } from '@/context/accent-color-context';
interface NavLink {
slug: string;
@@ -17,8 +16,6 @@ interface ProjectNavigationProps {
}
export function ProjectNavigation({ prev, next, basePath }: ProjectNavigationProps) {
const accentColor = useAccentColor();
if (!prev && !next) return null;
return (
@@ -32,7 +29,7 @@ export function ProjectNavigation({ prev, next, basePath }: ProjectNavigationPro
<ArrowLeft size={16} />
Previous
</div>
<div className="font-semibold truncate" style={{ color: accentColor }}>
<div className="font-semibold truncate">
{prev.title}
</div>
</Link>
@@ -46,7 +43,7 @@ export function ProjectNavigation({ prev, next, basePath }: ProjectNavigationPro
Next
<ArrowRight size={16} />
</div>
<div className="font-semibold truncate" style={{ color: accentColor }}>
<div className="font-semibold truncate">
{next.title}
</div>
</Link>

View File

@@ -1,47 +1,67 @@
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
// --- FIX: Import 'compile' from the correct RSC endpoint ---
import { compile } from 'next-mdx-remote/rsc';
// --- FIX: We need server-safe components for the compile step ---
import { serverSafeComponents } from '@/components/mdx';
import { bundleMDX } from 'mdx-bundler';
const contentDirectory = path.join(process.cwd(), 'content');
export function getPostSlugs(category: string) {
const categoryPath = path.join(contentDirectory, category);
if (!fs.existsSync(categoryPath)) { return []; }
const files = fs.readdirSync(categoryPath);
return files.map((file) => file.replace(/\.mdx$/, '').replace(/^\d{4}-\d{2}-\d{2}-/, ''));
export interface Frontmatter {
title: string;
date: string;
excerpt?: string;
teaser?: string;
tags?: string[];
icon?: string;
image?: string;
video?: string;
}
// --- FIX: This function MUST be async again ---
export async function getPostBySlug(category: string, slug: string) {
const categoryPath = path.join(contentDirectory, category);
if (!fs.existsSync(categoryPath)) { return null; }
const contentDirectory = path.join(process.cwd(), 'content');
const datePrefixRegex = /^\d{4}-\d{2}-\d{2}-/;
const files = fs.readdirSync(categoryPath);
const fileName = files.find((file) => file.replace(/\.mdx$/, '').endsWith(slug));
export function getPostSlugs(type: 'projects' | 'research' | 'teaching') {
const typeDirectory = path.join(contentDirectory, type);
if (!fs.existsSync(typeDirectory)) return [];
return fs.readdirSync(typeDirectory).map(file =>
file.replace(datePrefixRegex, '').replace(/\.mdx$/, '')
);
}
if (!fileName) { return null; }
export async function getPostBySlug(type: 'projects' | 'research' | 'teaching', slug: string) {
const typeDirectory = path.join(contentDirectory, type);
const allFiles = fs.readdirSync(typeDirectory);
const fileName = allFiles.find(file =>
file.replace(datePrefixRegex, '').replace(/\.mdx$/, '') === slug
);
const fullPath = path.join(categoryPath, fileName);
if (!fileName) {
console.error(`[MDX] Could not find a file for slug: ${slug} in ${typeDirectory}`);
return null;
}
const fullPath = path.join(typeDirectory, fileName);
const fileContents = fs.readFileSync(fullPath, 'utf8');
const { data, content } = matter(fileContents);
// --- FIX: Compile the MDX on the server ---
// This returns a pre-processed component and its frontmatter.
const source = await compile(content, {
components: serverSafeComponents, // Use components that are safe to run on the server
mdxOptions: {
parseFrontmatter: false, // We've already parsed it with gray-matter
},
const { code, frontmatter } = await bundleMDX({
source: fileContents,
});
// We now return the entire compiled result
return {
...source,
slug,
frontmatter: data, // Add our parsed frontmatter
frontmatter: frontmatter as Frontmatter,
code,
};
}
export function getSortedPostsData(type: 'projects' | 'research' | 'teaching') {
const postsDirectory = path.join(contentDirectory, type);
if (!fs.existsSync(postsDirectory)) return [];
const fileNames = fs.readdirSync(postsDirectory);
const allPostsData = fileNames.map((fileName) => {
const slug = fileName.replace(datePrefixRegex, "").replace(/\.mdx$/, "");
const fullPath = path.join(postsDirectory, fileName);
const fileContents = fs.readFileSync(fullPath, "utf8");
const { data } = matter(fileContents);
return { slug, href: `/${type}/${slug}`, ...data, };
});
// @ts-ignore
return allPostsData.sort((a, b) => new Date(b.date) - new Date(a.date));
}